$value ) { $attr = str_replace( 'attribute_', '', $key ); if ( isset( $allowed[ $attr ] ) && ! empty( $allowed[ $attr ] ) ) { if ( ! in_array( $value, $allowed[ $attr ], true ) ) { return false; } } } return true; } ) ); } /** * Normalise variation attribute values to slugs. * * get_available_variations() returns term slugs for global (taxonomy) * attributes but raw, case-preserved text for custom (product-level) * attributes (e.g. "White"). The configurator picker emits sanitize_title() * slugs and matches them by strict equality, both client-side (findVariation * in bundle.js) and in the allowlist filter above, so custom-attribute * variations never matched and showed "this combination is unavailable". * Slugging every value here fixes both paths and is a no-op for global * attributes, whose values are already slugs. Empty ("any") values stay the * wildcard the matcher expects. * * @param array $variations get_available_variations() output. * @return array */ function addon_boss_slugify_variation_attributes( array $variations ): array { foreach ( $variations as &$variation ) { if ( empty( $variation['attributes'] ) || ! is_array( $variation['attributes'] ) ) { continue; } foreach ( $variation['attributes'] as $key => $value ) { $variation['attributes'][ $key ] = ( '' === $value || null === $value ) ? '' : sanitize_title( (string) $value ); } } unset( $variation ); return $variations; }