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' => '',
'before_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): ?>
$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' );
}