5 ) { $columns = 3; } // Validate aspect ratio. $allowed_aspect_ratios = array( '1/1', '3/4', '4/3', '16/9' ); if ( ! in_array( $image_aspect_ratio, $allowed_aspect_ratios, true ) ) { $image_aspect_ratio = '3/4'; } // --------------------------------------------------------------------------- // Query categories based on the selected source mode. // --------------------------------------------------------------------------- if ( 'manual' === $category_source ) { // Build a list of sanitised category IDs in user-defined order. $selected_ids = array(); $featured_map = array(); foreach ( $selected_categories as $item ) { if ( ! isset( $item['id'] ) ) { continue; } $id = absint( $item['id'] ); if ( ! $id ) { continue; } $selected_ids[] = $id; if ( ! empty( $item['featured'] ) ) { $featured_map[ $id ] = true; } } if ( empty( $selected_ids ) ) { return ''; } $terms = get_terms( array( 'taxonomy' => 'product_cat', 'include' => $selected_ids, 'hide_empty' => false, 'orderby' => 'include', ) ); } else { // All mode: exclude empty (optionally) and the actual "Uncategorized" category. $exclude_ids = array_map( 'absint', $exclude_categories ); // Only exclude the default product category if its slug is 'uncategorized'. $default_cat_id = absint( get_option( 'default_product_cat', 0 ) ); if ( $default_cat_id ) { $default_cat = get_term( $default_cat_id, 'product_cat' ); if ( $default_cat && ! is_wp_error( $default_cat ) && 'uncategorized' === $default_cat->slug ) { $exclude_ids[] = $default_cat_id; } } $exclude_ids = array_unique( array_filter( $exclude_ids ) ); $terms = get_terms( array( 'taxonomy' => 'product_cat', 'parent' => 0, 'hide_empty' => ! $show_empty, // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- get_terms() exclusion bounded to the default "uncategorized" product_cat term. 'exclude' => $exclude_ids, 'orderby' => 'menu_order', 'order' => 'ASC', ) ); $featured_map = array(); } // Bail silently if there are no categories to display. if ( is_wp_error( $terms ) || empty( $terms ) ) { return ''; } // --------------------------------------------------------------------------- // Build wrapper attributes. // --------------------------------------------------------------------------- $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => 'airo-wp-product-categories-grid airo-wp-product-categories-grid--cols-' . $columns, 'role' => 'navigation', 'aria-label' => __( 'Product categories', 'airo-wp' ), 'style' => '--airo-wp-pcg-aspect-ratio: ' . esc_attr( $image_aspect_ratio ) . ';', ) ); // --------------------------------------------------------------------------- // Placeholder SVG (2×2 grid icon) for categories without an image. // --------------------------------------------------------------------------- $placeholder_svg = ''; ?>