=== zen_get_brand_checkbox_html === 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; === 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 === zen_shop_render_products === 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