tag in the document head, and expect WordPress to * provide it for us. */ add_theme_support( 'title-tag' ); /* * Enable support for Post Thumbnails on posts and pages. * * @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/ */ add_theme_support( 'post-thumbnails' ); // This theme uses wp_nav_menu() in one location. register_nav_menus( array( 'menu-1' => esc_html__( 'Primary', 'zen' ), ) ); /* * Switch default core markup for search form, comment form, and comments * to output valid HTML5. */ add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script', ) ); // Set up the WordPress core custom background feature. add_theme_support( 'custom-background', apply_filters( 'zen_custom_background_args', array( 'default-color' => 'ffffff', 'default-image' => '', ) ) ); // Add theme support for selective refresh for widgets. add_theme_support( 'customize-selective-refresh-widgets' ); /** * Add support for core custom logo. * * @link https://codex.wordpress.org/Theme_Logo */ add_theme_support( 'custom-logo', array( 'height' => 250, 'width' => 250, 'flex-width' => true, 'flex-height' => true, ) ); } add_action( 'after_setup_theme', 'zen_setup' ); /** * Set the content width in pixels, based on the theme's design and stylesheet. * * Priority 0 to make it available to lower priority callbacks. * * @global int $content_width */ function zen_content_width() { $GLOBALS['content_width'] = apply_filters( 'zen_content_width', 640 ); } add_action( 'after_setup_theme', 'zen_content_width', 0 ); /** * Register widget area. * * @link https://developer.wordpress.org/themes/functionality/sidebars/#registering-a-sidebar */ function zen_widgets_init() { register_sidebar( array( 'name' => esc_html__( 'Sidebar', 'zen' ), 'id' => 'sidebar-1', 'description' => esc_html__( 'Add widgets here.', 'zen' ), 'before_widget' => '
', 'after_widget' => '
', 'before_title' => '

', 'after_title' => '

', ) ); } add_action( 'widgets_init', 'zen_widgets_init' ); /** * Enqueue scripts and styles. */ function zen_scripts() { wp_enqueue_style( 'zen-style', get_stylesheet_uri(), array(), _S_VERSION ); wp_style_add_data( 'zen-style', 'rtl', 'replace' ); wp_enqueue_script( 'zen-navigation', get_template_directory_uri() . '/js/navigation.js', array(), _S_VERSION, true ); if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { wp_enqueue_script( 'comment-reply' ); } } add_action( 'wp_enqueue_scripts', 'zen_scripts' ); /** * Implement the Custom Header feature. */ require get_template_directory() . '/inc/custom-header.php'; /** * Custom template tags for this theme. */ require get_template_directory() . '/inc/template-tags.php'; /** * Functions which enhance the theme by hooking into WordPress. */ require get_template_directory() . '/inc/template-functions.php'; /** * Customizer additions. */ require get_template_directory() . '/inc/customizer.php'; /** * Load Jetpack compatibility file. */ if ( defined( 'JETPACK__VERSION' ) ) { require get_template_directory() . '/inc/jetpack.php'; } function zen_theme_scripts() { // Custom CSS (cache remove) wp_enqueue_style( 'main-style', get_template_directory_uri() . '/css/style.css', array(), time() ); // about css if (is_page('about')) { wp_enqueue_style( 'about-style', get_template_directory_uri() . '/css/about.css', array(), time() ); } // contact us css // only contact page if (is_page('contact')) { wp_enqueue_style( 'contact-style', get_template_directory_uri() . '/css/contact.css', array(), time() ); } // reseller.css if (is_page('become-a-reseller')) { wp_enqueue_style( 'reseller-style', get_template_directory_uri() . '/css/reseller.css', array(), time() ); } // Solutions page css if (is_page('solutions')) { wp_enqueue_style( 'solutions-style', get_template_directory_uri() . '/css/solutions.css', array(), time() ); } // Portfolio page css if (is_page('Portfolio')) { wp_enqueue_style( 'portfolio-style', get_template_directory_uri() . '/css/portfolio.css', array(), time() ); } // Resources page css if (is_page('Resources')) { wp_enqueue_style( 'Resources-style', get_template_directory_uri() . '/css/resources.css', array(), time() ); } // Insights page css if (is_page('Insights')) { wp_enqueue_style( 'Insights-style', get_template_directory_uri() . '/css/insights.css', array(), time() ); } // careers page css if (is_page('careers')) { wp_enqueue_style( 'careers-style', get_template_directory_uri() . '/css/careers.css', array(), time() ); } // Micron page css if (is_page('Micron')) { wp_enqueue_style( 'Micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); } // Micron page css if (is_page('micron-product')) { wp_enqueue_style( 'micron-product-style', get_template_directory_uri() . '/css/micron-product.css', array(), time() ); wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); } // crucial page css if (is_page('crucial')) { wp_enqueue_style( 'micron-product-style', get_template_directory_uri() . '/css/micron-product.css', array(), time() ); wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); } // 3cx page css if (is_page('3cx')) { wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); wp_enqueue_style( 'threecx-style', get_template_directory_uri() . '/css/3cx-1.css', array(), time() ); } // tabatalk page css if (is_page('tabatalk')) { wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); wp_enqueue_style( 'tabatalk-style', get_template_directory_uri() . '/css/tabatalk-1.css', array(), time() ); } // Snom page css if (is_page('Snom')) { wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); wp_enqueue_style( 'Snom-style', get_template_directory_uri() . '/css/Snom-1.css', array(), time() ); } // Yealink page css if (is_page('yealink')) { wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); wp_enqueue_style( 'yealink-style', get_template_directory_uri() . '/css/yealink-1.css', array(), time() ); } // Dinstar page css if (is_page('Dinstar')) { wp_enqueue_style( 'micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); wp_enqueue_style( 'Dinstar-style', get_template_directory_uri() . '/css/dinstar-1.css', array(), time() ); } // ezone page css if (is_page('ezone')) { wp_enqueue_style( 'Micron-style', get_template_directory_uri() . '/css/micron.css', array(), time() ); } // Custom JS wp_enqueue_script( 'main-js', get_template_directory_uri() . '/js/main.js', array('jquery'), time(), true ); // solutions page js if (is_page('solutions')) { wp_enqueue_script( 'solutions-js', get_template_directory_uri() . '/js/solutions.js', array(), time(), true ); } // micron-product page js if (is_page('micron-product')) { wp_enqueue_script( 'micron-product-js', get_template_directory_uri() . '/js/micron-product.js', array(), time(), true ); } // resources page js if (is_page('Resources')) { wp_enqueue_script( 'resources-js', get_template_directory_uri() . '/js/resources.js', array(), time(), true ); } } // Hook add_action('wp_enqueue_scripts', 'zen_theme_scripts'); function zen_theme_menu() { register_nav_menu('primary', 'Primary Menu'); } add_action('init', 'zen_theme_menu'); function add_bootstrap_classes($classes, $item, $args) { $classes[] = 'nav-item'; return $classes; } add_filter('nav_menu_css_class', 'add_bootstrap_classes', 10, 3); function add_link_class($atts) { $atts['class'] = 'nav-link'; return $atts; } add_filter('nav_menu_link_attributes', 'add_link_class'); function reading_time($content) { $word_count = str_word_count(strip_tags($content)); $reading_time = ceil($word_count / 200); // avg 200 wpm return $reading_time . ' min read'; } include('inc/cpt.php'); include('inc/resources-cpt.php'); include('inc/resources-render.php'); include('inc/events-cpt.php'); include('inc/events-render.php'); include('inc/newsletter-cpt.php'); include('inc/client-logos-cpt.php'); include('inc/testimonials-cpt.php'); include('inc/hero-media.php'); include('inc/footer-categories.php'); include('inc/sessions-marquee.php'); include('inc/mega-menu.php'); // _platform_solutions function create_platform_solutions_cpt() { register_post_type('platform_solutions', array( 'labels' => array( 'name' => 'Platform Solutions', 'singular_name' => 'Platform Solution' ), 'public' => true, 'has_archive' => false, 'menu_icon' => 'dashicons-screenoptions', 'supports' => array('title', 'editor'), 'taxonomies' => array('post_tag') ) ); } add_action('init', 'create_platform_solutions_cpt'); // collaboration_spaces function create_collaboration_spaces_cpt() { register_post_type('collaboration_spaces', array( 'labels' => array( 'name' => 'Collaboration Spaces', 'singular_name' => 'Collaboration Space', 'add_new' => 'Add New', 'add_new_item' => 'Add New Space', 'edit_item' => 'Edit Space', 'all_items' => 'All Spaces' ), 'public' => true, 'has_archive' => false, 'menu_icon' => 'dashicons-groups', 'supports' => array('title', 'editor', 'thumbnail') ) ); } add_action('init', 'create_collaboration_spaces_cpt'); // industry_solutions function create_industry_solutions_cpt() { register_post_type('industry_solutions', array( 'labels' => array( 'name' => 'Industry Solutions', 'singular_name' => 'Industry Solution', 'add_new' => 'Add New', 'add_new_item' => 'Add New Industry', 'edit_item' => 'Edit Industry', 'all_items' => 'All Industries' ), 'public' => true, 'has_archive' => false, 'menu_icon' => 'dashicons-building', 'supports' => array('title', 'editor', 'thumbnail'), 'rewrite' => array('slug' => 'industry-solutions') ) ); } add_action('init', 'create_industry_solutions_cpt'); function add_query_vars_filter($vars) { $vars[] = 'product_brand'; return $vars; } add_filter('query_vars', 'add_query_vars_filter'); function fix_brand_filter_not_archive($query) { if (!is_admin() && $query->is_main_query()) { // If on shop page with brand filter if (isset($_GET['product_brand']) && is_shop()) { // Prevent WP from treating it as taxonomy archive $query->is_tax = false; $query->is_archive = true; // Apply tax_query manually $tax_query = []; // BRAND if (!empty($_GET['product_brand'])) { $tax_query[] = [ 'taxonomy' => 'product_brand', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field($_GET['product_brand'])), ]; } // CATEGORY if (!empty($_GET['product_cat'])) { $tax_query[] = [ 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field($_GET['product_cat'])), ]; } $query->set('tax_query', $tax_query); } } } add_action('pre_get_posts', 'fix_brand_filter_not_archive'); add_filter('template_include', function($template) { if ((is_shop() || is_product_category()) && isset($_GET['product_brand'])) { return wc_locate_template('archive-product.php'); } return $template; }, 99); add_action('pre_get_posts', function($q) { if (is_admin() || !$q->is_main_query()) return; // ✅ Detect if URL is category (even with brand param) if (is_tax('product_cat') || isset($_GET['product_cat'])) { $tax_query = []; // ✅ CATEGORY from URL OR archive if (!empty($_GET['product_cat'])) { $cats = explode(',', sanitize_text_field($_GET['product_cat'])); $tax_query[] = [ 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $cats, ]; } elseif (is_tax('product_cat')) { $current_cat = get_queried_object(); $tax_query[] = [ 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => [$current_cat->slug], ]; } // ✅ BRAND FILTER (without switching template) if (!empty($_GET['product_brand'])) { $brands = explode(',', sanitize_text_field($_GET['product_brand'])); $tax_query[] = [ 'taxonomy' => 'product_brand', 'field' => 'slug', 'terms' => $brands, ]; } if (!empty($tax_query)) { $q->set('tax_query', $tax_query); } $q->set('post_type', 'product'); // 🔥 CRITICAL: prevent WP from treating it as brand page $q->is_tax = false; $q->is_archive = true; } }, 99); // ================================================================ // Dynamic Brand Page Content (ACF) — replaces hardcoded Micron/Crucial // copy on taxonomy-product_brand.php with per-brand editable fields. // If a field is left blank in wp-admin, the template falls back to a // sensible generic default that uses the real brand name. // ================================================================ if ( function_exists('acf_add_local_field_group') ) { acf_add_local_field_group(array( 'key' => 'group_zen_brand_dynamic_content', 'title' => 'Brand Page — Dynamic Content', 'fields' => array( array( 'key' => 'field_zbd_hero_badges', 'label' => 'Hero Floating Badges', 'name' => 'hero_badges', 'type' => 'repeater', 'instructions' => 'Up to 3 small floating badges shown over the hero image (e.g. 5G, IoT, Industrial). Leave empty to hide.', 'min' => 0, 'max' => 3, 'layout' => 'table', 'sub_fields' => array( array('key'=>'field_zbd_hero_badge_icon','label'=>'Icon (Font Awesome class)','name'=>'icon','type'=>'text','placeholder'=>'fas fa-wifi'), array('key'=>'field_zbd_hero_badge_label','label'=>'Label','name'=>'label','type'=>'text','placeholder'=>'5G'), ), ), array( 'key' => 'field_zbd_experience_number', 'label' => 'Experience Badge Number', 'name' => 'experience_number', 'type' => 'text', 'placeholder' => 'e.g. 25+', ), array( 'key' => 'field_zbd_experience_label', 'label' => 'Experience Badge Label', 'name' => 'experience_label', 'type' => 'text', 'placeholder' => 'e.g. Years of Innovation', ), array( 'key' => 'field_zbd_brand_stats', 'label' => 'About Section Stats', 'name' => 'brand_stats', 'type' => 'repeater', 'instructions' => 'Up to 3 short stat callouts next to the About the Brand description. Leave empty to use generic defaults.', 'min' => 0, 'max' => 3, 'layout' => 'table', 'sub_fields' => array( array('key'=>'field_zbd_stat_icon','label'=>'Icon (Font Awesome class)','name'=>'icon','type'=>'text','placeholder'=>'fas fa-globe'), array('key'=>'field_zbd_stat_number','label'=>'Stat Value','name'=>'number','type'=>'text','placeholder'=>'Guaranteed'), array('key'=>'field_zbd_stat_label','label'=>'Stat Label','name'=>'label','type'=>'text','placeholder'=>'Compatibility'), ), ), array( 'key' => 'field_zbd_value_prop_tag', 'label' => 'Value Proposition — Section Tag', 'name' => 'value_prop_tag', 'type' => 'text', 'placeholder' => 'e.g. Why Choose [Brand]', ), array( 'key' => 'field_zbd_value_prop_heading', 'label' => 'Value Proposition — Heading', 'name' => 'value_prop_heading', 'type' => 'text', ), array( 'key' => 'field_zbd_applications_tag', 'label' => 'Applications — Section Tag', 'name' => 'applications_tag', 'type' => 'text', ), array( 'key' => 'field_zbd_applications_heading', 'label' => 'Applications — Heading', 'name' => 'applications_heading', 'type' => 'text', ), array( 'key' => 'field_zbd_why_us_tag', 'label' => 'Why Buy From Us — Section Tag', 'name' => 'why_us_tag', 'type' => 'text', ), array( 'key' => 'field_zbd_why_us_heading', 'label' => 'Why Buy From Us — Heading', 'name' => 'why_us_heading', 'type' => 'text', ), array( 'key' => 'field_zbd_why_us_lead', 'label' => 'Why Buy From Us — Lead Text', 'name' => 'why_us_lead', 'type' => 'textarea', 'rows' => 2, ), array( 'key' => 'field_zbd_why_us_benefits', 'label' => 'Why Buy From Us — Benefits', 'name' => 'why_us_benefits', 'type' => 'repeater', 'instructions' => 'Up to 4 benefit tiles. Leave empty to use default distributor benefits with this brand\'s name inserted automatically.', 'min' => 0, 'max' => 4, 'layout' => 'table', 'sub_fields' => array( array('key'=>'field_zbd_benefit_icon','label'=>'Icon (Font Awesome class)','name'=>'icon','type'=>'text','placeholder'=>'fas fa-certificate'), array('key'=>'field_zbd_benefit_title','label'=>'Title','name'=>'title','type'=>'text'), array('key'=>'field_zbd_benefit_desc','label'=>'Description','name'=>'description','type'=>'textarea','rows'=>2), ), ), array( 'key' => 'field_zbd_partner_subtitle', 'label' => 'Official Partner Badge — Brand Name', 'name' => 'partner_subtitle', 'type' => 'text', 'instructions' => 'Leave empty to use the brand name automatically.', ), array( 'key' => 'field_zbd_cta_heading', 'label' => 'Bottom CTA — Heading', 'name' => 'cta_heading', 'type' => 'text', ), array( 'key' => 'field_zbd_cta_text', 'label' => 'Bottom CTA — Text', 'name' => 'cta_text', 'type' => 'textarea', 'rows' => 2, ), array( 'key' => 'field_zbd_products_section_label', 'label' => 'Products Section — Tag', 'name' => 'products_section_label', 'type' => 'text', 'placeholder' => 'Products', ), array( 'key' => 'field_zbd_products_section_heading', 'label' => 'Products Section — Heading', 'name' => 'products_section_heading', 'type' => 'text', ), array( 'key' => 'field_zbd_products_section_desc', 'label' => 'Products Section — Description', 'name' => 'products_section_desc', 'type' => 'textarea', 'rows' => 2, ), ), 'location' => array( array( array( 'param' => 'taxonomy', 'operator' => '==', 'value' => 'product_brand', ), ), ), )); } /* ============================================================ SHOP PAGE HERO — Per-Brand Overrides Powers the dynamic hero + sidebar CTA on /shop/?product_brand=X (previously hardcoded to always show "Micron"). Blank fields fall back to a sensible default built from the brand's real name. ============================================================ */ if ( function_exists('acf_add_local_field_group') ) { acf_add_local_field_group(array( 'key' => 'group_zen_shop_hero_brand', 'title' => 'Shop Page Hero — Brand Overrides', 'fields' => array( array( 'key' => 'field_zsh_badge', 'label' => 'Hero Badge Text', 'name' => 'shop_hero_badge', 'type' => 'text', 'placeholder' => 'Official Authorized Distributor', 'instructions' => 'Leave blank to use the default badge text.', ), array( 'key' => 'field_zsh_title_line1', 'label' => 'Hero Title — Line 1', 'name' => 'shop_hero_title_line1', 'type' => 'text', 'instructions' => 'Leave blank to use "[Brand Name] Enterprise".', ), array( 'key' => 'field_zsh_title_highlight', 'label' => 'Hero Title — Highlighted Line', 'name' => 'shop_hero_title_highlight', 'type' => 'text', 'instructions' => 'Leave blank to use "Product Catalog".', ), array( 'key' => 'field_zsh_subtitle', 'label' => 'Hero Subtitle', 'name' => 'shop_hero_subtitle', 'type' => 'textarea', 'rows' => 2, 'instructions' => 'Leave blank to use a generic subtitle mentioning this brand.', ), array( 'key' => 'field_zsh_cta_heading', 'label' => 'Sidebar CTA — Heading', 'name' => 'shop_sidebar_cta_heading', 'type' => 'text', 'placeholder' => 'Need Help Choosing?', ), array( 'key' => 'field_zsh_cta_text', 'label' => 'Sidebar CTA — Text', 'name' => 'shop_sidebar_cta_text', 'type' => 'textarea', 'rows' => 2, 'instructions' => 'Leave blank to use "Our experts will help you find the right [Brand Name] solution."', ), ), 'location' => array( array( array( 'param' => 'taxonomy', 'operator' => '==', 'value' => 'product_brand', ), ), ), )); } /* ============================================================ SHOP PAGE — Default / Generic Content (wp-admin Options Page) Used on /shop/ whenever no single brand filter is active (multiple brands selected, category-only filter, or no filter at all). Editable from "Shop Page Settings" in wp-admin. ============================================================ */ if ( function_exists('acf_add_options_page') ) { acf_add_options_page(array( 'page_title' => 'Shop Page Settings', 'menu_title' => 'Shop Page Settings', 'menu_slug' => 'shop-page-settings', 'capability' => 'manage_options', 'redirect' => false, 'icon_url' => 'dashicons-cart', )); } if ( function_exists('acf_add_local_field_group') ) { acf_add_local_field_group(array( 'key' => 'group_zen_shop_default_content', 'title' => 'Shop Page — Default Hero Content', 'fields' => array( array( 'key' => 'field_zshd_badge', 'label' => 'Default Hero Badge Text', 'name' => 'shop_default_badge', 'type' => 'text', 'default_value' => 'Official Authorized Distributor', ), array( 'key' => 'field_zshd_title_line1', 'label' => 'Default Hero Title — Line 1', 'name' => 'shop_default_title_line1', 'type' => 'text', 'default_value' => 'Explore Our', ), array( 'key' => 'field_zshd_title_highlight', 'label' => 'Default Hero Title — Highlighted Line', 'name' => 'shop_default_title_highlight', 'type' => 'text', 'default_value' => 'Product Catalog', ), array( 'key' => 'field_zshd_subtitle', 'label' => 'Default Hero Subtitle', 'name' => 'shop_default_subtitle', 'type' => 'textarea', 'rows' => 2, 'default_value' => 'Browse our complete product portfolio across all categories — genuine products sourced directly from authorized distribution channels.', ), array( 'key' => 'field_zshd_stat3_number', 'label' => 'Default Third Stat — Number', 'name' => 'shop_default_stat3_number', 'type' => 'text', 'default_value' => '500+', ), array( 'key' => 'field_zshd_stat3_label', 'label' => 'Default Third Stat — Label', 'name' => 'shop_default_stat3_label', 'type' => 'text', 'default_value' => 'Enterprises Served', ), array( 'key' => 'field_zshd_cta_heading', 'label' => 'Default Sidebar CTA — Heading', 'name' => 'shop_default_sidebar_cta_heading', 'type' => 'text', 'default_value' => 'Need Help Choosing?', ), array( 'key' => 'field_zshd_cta_text', 'label' => 'Default Sidebar CTA — Text', 'name' => 'shop_default_sidebar_cta_text', 'type' => 'textarea', 'rows' => 2, 'default_value' => 'Our experts will help you find the right solution for your business.', ), ), 'location' => array( array( array( 'param' => 'options_page', 'operator' => '==', 'value' => 'shop-page-settings', ), ), ), )); } /* ============================================================ SHOP PAGE — Shared product grid renderer (AJAX + initial load) Builds the WP_Query from the given filters and renders the exact same product-card markup used on page load, so AJAX filtering produces an identical result. 36 products per page. ============================================================ */ function zen_shop_render_products( $tax_query, $paged = 1, $sort_by = '' ) { $args = array( 'post_type' => 'product', 'posts_per_page' => 36, 'paged' => $paged, 'tax_query' => $tax_query, ); if ( $sort_by === 'date' ) { $args['orderby'] = 'date'; $args['order'] = 'DESC'; } elseif ( $sort_by === 'title' ) { $args['orderby'] = 'title'; $args['order'] = 'ASC'; } elseif ( $sort_by === 'popularity' ) { $args['meta_key'] = 'total_sales'; $args['orderby'] = 'meta_value_num'; } $query = new WP_Query( $args ); ob_start(); $zen_cat_brand_cache = array(); ?>
have_posts()): ?> have_posts()): $query->the_post(); global $product; ?> get_date_created()); $is_new = ( time() - $created ) < ( $newness_days * DAY_IN_SECONDS ); $total_sales = $product->get_total_sales(); $is_popular = $total_sales > 50; // adjust threshold ?> slug !== 'uncategorized'; } ) ) : array(); $card_brand_terms = get_the_terms( get_the_ID(), 'product_brand' ); $card_brand_terms = ( $card_brand_terms && !is_wp_error( $card_brand_terms ) ) ? $card_brand_terms : array(); $card_brand_top = null; if ( count( $card_brand_terms ) >= 1 ) { $first_brand_term = $card_brand_terms[0]; $card_brand_top = $first_brand_term->parent ? get_term( $first_brand_term->parent, 'product_brand' ) : $first_brand_term; } $card_solution_label = 'Generic'; $card_brand_label = ( $card_brand_top && !is_wp_error( $card_brand_top ) ) ? $card_brand_top->name : ''; if ( count( $card_cat_terms ) === 1 ) { $cat_slug = $card_cat_terms[0]->slug; $brand_matches_cat = true; if ( $card_brand_top && !is_wp_error( $card_brand_top ) ) { if ( !isset( $zen_cat_brand_cache[ $cat_slug ] ) ) { $cat_brand_terms = zen_get_cascaded_brands( $cat_slug ); $zen_cat_brand_cache[ $cat_slug ] = is_array( $cat_brand_terms ) ? wp_list_pluck( $cat_brand_terms, 'term_id' ) : array(); } $brand_matches_cat = in_array( $card_brand_top->term_id, $zen_cat_brand_cache[ $cat_slug ] ); } if ( $brand_matches_cat ) { $card_solution_label = $card_cat_terms[0]->name; } } ?>
Popular New
·

SKU:get_sku() ? $product->get_sku() : 'N/A'; ?>

(4.8)
get_short_description(); if ( empty( $card_short_desc ) ) { $card_short_desc = get_the_excerpt(); } $card_short_desc = wp_trim_words( wp_strip_all_tags( $card_short_desc ), 20 ); ?>

' . esc_html($tag->name) . ''; } } ?>

No products found.

max_num_pages > 1): ?>
'#%#%', 'format' => '', 'current' => max(1, $paged), 'total' => $query->max_num_pages, 'prev_text' => '« Prev', 'next_text' => 'Next »', 'type' => 'list', ]); ?>
$html, 'found_posts' => $query->found_posts, 'max_num_pages' => $query->max_num_pages, ); } add_action( 'wp_ajax_zen_filter_products', 'zen_ajax_filter_products' ); add_action( 'wp_ajax_nopriv_zen_filter_products', 'zen_ajax_filter_products' ); function zen_ajax_filter_products() { $tax_query = array(); if ( !empty($_POST['product_cat']) ) { $tax_query[] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field(wp_unslash($_POST['product_cat']))), 'operator' => 'IN', ); } if ( !empty($_POST['product_brand']) ) { $tax_query[] = array( 'taxonomy' => 'product_brand', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field(wp_unslash($_POST['product_brand']))), 'operator' => 'IN', ); } if ( !empty($_POST['product_technology']) ) { $tax_query[] = array( 'taxonomy' => 'pa_technology', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field(wp_unslash($_POST['product_technology']))), 'operator' => 'IN', ); } if ( !empty($_POST['product_connectivity']) ) { $tax_query[] = array( 'taxonomy' => 'pa_connectivity', 'field' => 'slug', 'terms' => explode(',', sanitize_text_field(wp_unslash($_POST['product_connectivity']))), 'operator' => 'IN', ); } $paged = !empty($_POST['paged']) ? absint($_POST['paged']) : 1; $sort_by = !empty($_POST['sort_by']) ? sanitize_text_field(wp_unslash($_POST['sort_by'])) : ''; $result = zen_shop_render_products( $tax_query, $paged, $sort_by ); $posted_cats = !empty($_POST['product_cat']) ? explode(',', sanitize_text_field(wp_unslash($_POST['product_cat']))) : array(); $cat_single = ( count($posted_cats) === 1 ) ? trim($posted_cats[0]) : ''; $posted_brands = !empty($_POST['product_brand']) ? explode(',', sanitize_text_field(wp_unslash($_POST['product_brand']))) : array(); $brand_single = ( count($posted_brands) === 1 ) ? trim($posted_brands[0]) : ''; $result['brand_options_html'] = zen_get_brand_options_html( $posted_cats, $brand_single ); $result['brand_checkboxes_html'] = zen_get_brand_checkbox_html( $posted_cats, $posted_brands ); $result['hero_title_line1'] = zen_get_hero_title_line1( $posted_cats, $posted_brands ); $result['active_filter_summary'] = zen_get_active_filter_summary( $posted_cats, $posted_brands ); wp_send_json_success( $result ); } /* ============================================================ SHOP PAGE — Brand dropdown options (cascading with Solutions) Shared by the initial page render and the AJAX filter handler so both stay in sync automatically. ============================================================ */ function zen_get_cascaded_brands( $cat_slugs ) { $cat_slugs = array_values( array_filter( array_map( 'trim', (array) $cat_slugs ) ) ); if ( !empty( $cat_slugs ) ) { $product_ids = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'fields' => 'ids', 'tax_query' => array( array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $cat_slugs, 'operator' => 'IN', ) ), ) ); $brands_raw = !empty( $product_ids ) ? wp_get_object_terms( $product_ids, 'product_brand', array( 'fields' => 'all_with_object_id' ) ) : array(); // Tally how many of the currently scoped products carry each exact brand term, // so the displayed count always matches what checking that box will actually return. $own_counts = array(); foreach ( $brands_raw as $tb ) { if ( is_wp_error( $tb ) ) { continue; } $own_counts[ $tb->term_id ] = isset( $own_counts[ $tb->term_id ] ) ? $own_counts[ $tb->term_id ] + 1 : 1; } $seen = array(); $brands = array(); foreach ( $brands_raw as $tb ) { if ( is_wp_error( $tb ) ) { continue; } $tb_top = $tb->parent ? get_term( $tb->parent, 'product_brand' ) : $tb; if ( $tb_top && !is_wp_error( $tb_top ) && !isset( $seen[ $tb_top->term_id ] ) ) { $seen[ $tb_top->term_id ] = true; $tb_top->zen_children = array(); $brands[] = $tb_top; } } $by_id = array(); foreach ( $brands as $b ) { $by_id[ $b->term_id ] = $b; } $seen_child = array(); foreach ( $brands_raw as $tb ) { if ( is_wp_error( $tb ) ) { continue; } if ( $tb->parent && isset( $by_id[ $tb->parent ] ) && !isset( $seen_child[ $tb->term_id ] ) ) { $seen_child[ $tb->term_id ] = true; $by_id[ $tb->parent ]->zen_children[] = $tb; } } // Replace each term's raw sitewide count with the count scoped to the selected Solution(s). foreach ( $brands as $b ) { $b->count = isset( $own_counts[ $b->term_id ] ) ? $own_counts[ $b->term_id ] : 0; foreach ( $b->zen_children as $child ) { $child->count = isset( $own_counts[ $child->term_id ] ) ? $own_counts[ $child->term_id ] : 0; } } usort( $brands, function( $a, $b ) { return strcasecmp( $a->name, $b->name ); } ); } else { $brands = get_terms( array( 'taxonomy' => 'product_brand', 'parent' => 0, 'hide_empty' => true ) ); if ( !is_wp_error( $brands ) ) { foreach ( $brands as $b ) { $b->zen_children = get_terms( array( 'taxonomy' => 'product_brand', 'parent' => $b->term_id, 'hide_empty' => true ) ); } } } return $brands; } function zen_get_brand_options_html( $cat_single, $selected_brand_single = '' ) { $brands = zen_get_cascaded_brands( $cat_single ); $html = ''; if ( !empty( $brands ) && !is_wp_error( $brands ) ) { foreach ( $brands as $tbrand ) { $html .= ''; } } return $html; } /** * SHOP PAGE — Sidebar brand checkbox list (cascading with Solutions) * Shared by the initial page render and the AJAX filter handler * so both stay in sync automatically. */ function zen_get_brand_checkbox_html( $cat_slugs, $selected_brands = array() ) { $brands = zen_get_cascaded_brands( $cat_slugs ); $html = ''; if ( empty( $brands ) || is_wp_error( $brands ) ) { return $html; } foreach ( $brands as $brand ) { $checked_parent = in_array( $brand->slug, $selected_brands ) ? 'checked' : ''; $html .= ''; $sub_brands = isset( $brand->zen_children ) ? $brand->zen_children : array(); if ( !empty( $sub_brands ) && !is_wp_error( $sub_brands ) ) { $html .= '
'; foreach ( $sub_brands as $sub ) { $checked_child = in_array( $sub->slug, $selected_brands ) ? 'checked' : ''; $html .= ''; } $html .= '
'; } } return $html; } /** * SHOP PAGE — Map of brand slug => associated Solution (category) slugs. * Powers the sidebar behaviour where checking a Brand first auto-selects * the Solution(s) that brand's products actually belong to. */ function zen_get_brand_category_map() { $map = array(); $product_ids = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'fields' => 'ids' ) ); if ( empty( $product_ids ) ) { return $map; } $brand_pairs = wp_get_object_terms( $product_ids, 'product_brand', array( 'fields' => 'all_with_object_id' ) ); $cat_pairs = wp_get_object_terms( $product_ids, 'product_cat', array( 'fields' => 'all_with_object_id' ) ); if ( is_wp_error( $brand_pairs ) || is_wp_error( $cat_pairs ) ) { return $map; } $cats_by_product = array(); foreach ( $cat_pairs as $cp ) { if ( is_wp_error( $cp ) || $cp->slug === 'uncategorized' ) { continue; } if ( !isset( $cats_by_product[ $cp->object_id ] ) ) { $cats_by_product[ $cp->object_id ] = array(); } $cats_by_product[ $cp->object_id ][] = $cp->slug; } foreach ( $brand_pairs as $bp ) { if ( is_wp_error( $bp ) ) { continue; } $cat_slugs = isset( $cats_by_product[ $bp->object_id ] ) ? $cats_by_product[ $bp->object_id ] : array(); if ( empty( $cat_slugs ) ) { continue; } if ( !isset( $map[ $bp->slug ] ) ) { $map[ $bp->slug ] = array(); } foreach ( $cat_slugs as $cs ) { if ( !in_array( $cs, $map[ $bp->slug ] ) ) { $map[ $bp->slug ][] = $cs; } } if ( $bp->parent ) { $parent = get_term( $bp->parent, 'product_brand' ); if ( $parent && !is_wp_error( $parent ) ) { if ( !isset( $map[ $parent->slug ] ) ) { $map[ $parent->slug ] = array(); } foreach ( $cat_slugs as $cs ) { if ( !in_array( $cs, $map[ $parent->slug ] ) ) { $map[ $parent->slug ][] = $cs; } } } } } return $map; } /** * SHOP PAGE — Hero title line1 ("[Brand] Enterprise" / "[Brand] Generic" / default) * Shared by the initial page render logic and the AJAX filter handler so the * hero title stays in sync when Solutions/Brand filters change without a reload. */ function zen_get_active_filter_summary( $cat_slugs, $brand_slugs ) { $cat_slugs = array_values( array_filter( array_map( 'trim', (array) $cat_slugs ) ) ); $brand_slugs = array_values( array_filter( array_map( 'trim', (array) $brand_slugs ) ) ); if ( empty( $cat_slugs ) ) { $solution_label = 'All Solutions'; } else { $cat_names = array(); foreach ( $cat_slugs as $slug ) { $term = get_term_by( 'slug', $slug, 'product_cat' ); if ( $term && !is_wp_error( $term ) ) { $cat_names[] = html_entity_decode( $term->name, ENT_QUOTES ); } } $solution_label = !empty( $cat_names ) ? implode( ', ', $cat_names ) : 'All Solutions'; } if ( empty( $brand_slugs ) ) { $brand_label = 'All Brands'; } else { $brand_names = array(); foreach ( $brand_slugs as $slug ) { $term = get_term_by( 'slug', $slug, 'product_brand' ); if ( $term && !is_wp_error( $term ) ) { $brand_names[] = html_entity_decode( $term->name, ENT_QUOTES ); } } $brand_label = !empty( $brand_names ) ? implode( ', ', $brand_names ) : 'All Brands'; } return 'Search Result for Solution : ' . esc_html( $solution_label ) . ' and Brands : ' . esc_html( $brand_label ) . ''; } function zen_get_hero_title_line1( $cat_slugs, $brand_slugs ) { $brand_slugs = array_values( array_filter( array_map( 'trim', (array) $brand_slugs ) ) ); $hero_brand_term = null; if ( !empty( $brand_slugs ) ) { $first_term = get_term_by( 'slug', $brand_slugs[0], 'product_brand' ); if ( $first_term && !is_wp_error( $first_term ) ) { $hero_brand_term = $first_term->parent ? get_term( $first_term->parent, 'product_brand' ) : $first_term; } } if ( !$hero_brand_term || is_wp_error( $hero_brand_term ) ) { $default_title = get_field( 'shop_default_title_line1', 'option' ); return $default_title ?: 'Explore Our'; } $hero_tid = 'product_brand_' . $hero_brand_term->term_id; $override = get_field( 'shop_hero_title_line1', $hero_tid ); if ( $override ) { return $override; } $cat_slugs = array_values( array_filter( array_map( 'trim', (array) $cat_slugs ) ) ); $generic = true; if ( count( $cat_slugs ) === 1 ) { $generic = false; $cat_brand_terms = zen_get_cascaded_brands( $cat_slugs[0] ); $cat_brand_ids = is_array( $cat_brand_terms ) ? wp_list_pluck( $cat_brand_terms, 'term_id' ) : array(); if ( !in_array( $hero_brand_term->term_id, $cat_brand_ids ) ) { $generic = true; } } return $hero_brand_term->name . ' ' . ( $generic ? 'Generic' : 'Enterprise' ); }