File "utils.js"
Full Path: /home/vantageo/public_html/cache/cache/.wp-cli/wp-content/plugins/woocommerce/packages/woocommerce-blocks/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/utils.js
File size: 6.18 KB
MIME-type: text/x-java
Charset: utf-8
/**
* External dependencies
*/
import { keyBy } from 'lodash';
import { decodeEntities } from '@wordpress/html-entities';
/**
* Key an array of attributes by name,
*
* @param {Object} attributes Attributes array.
*/
export const getAttributes = ( attributes ) => {
return attributes
? keyBy(
Object.values( attributes ).filter(
( { has_variations: hasVariations } ) => hasVariations
),
'name'
)
: {};
};
/**
* Format variations from the API into a map of just the attribute names and values.
*
* Note, each item is keyed by the variation ID with an id: prefix. This is to prevent the object
* being reordered when iterated.
*
* @param {Object} variations List of Variation objects and attributes keyed by variation ID.
*/
export const getVariationAttributes = ( variations ) => {
if ( ! variations ) {
return {};
}
const attributesMap = {};
variations.forEach( ( { id, attributes } ) => {
attributesMap[ `id:${ id }` ] = {
id,
attributes: attributes.reduce( ( acc, { name, value } ) => {
acc[ name ] = value;
return acc;
}, {} ),
};
} );
return attributesMap;
};
/**
* Given a list of variations and a list of attribute values, return variations which match.
*
* Allows an attribute to be excluded by name. This is used to filter displayed options for
* individual attribute selects.
*
* @param {Object} attributes List of attribute names and terms.
* @param {Object} variationAttributes Attributes for each variation keyed by variation ID.
* @param {Object} selectedAttributes Attribute Name Value pairs of current selections by the user.
* @return {Array} List of matching variation IDs.
*/
export const getVariationsMatchingSelectedAttributes = (
attributes,
variationAttributes,
selectedAttributes
) => {
const variationIds = Object.values( variationAttributes ).map(
( { id: variationId } ) => {
return variationId;
}
);
// If nothing is selected yet, just return all variations.
if (
Object.values( selectedAttributes ).every( ( value ) => value === '' )
) {
return variationIds;
}
const attributeNames = Object.keys( attributes );
return variationIds.filter( ( variationId ) =>
attributeNames.every( ( attributeName ) => {
const selectedAttribute = selectedAttributes[ attributeName ] || '';
const variationAttribute =
variationAttributes[ 'id:' + variationId ].attributes[
attributeName
];
// If there is no selected attribute, consider this a match.
if ( selectedAttribute === '' ) {
return true;
}
// If the variation attributes for this attribute are set to null, it matches all values.
if ( variationAttribute === null ) {
return true;
}
// Otherwise, only match if the selected values are the same.
return variationAttribute === selectedAttribute;
} )
);
};
/**
* Given a list of variations and a list of attribute values, returns the first matched variation ID.
*
* @param {Object} attributes List of attribute names and terms.
* @param {Object} variationAttributes Attributes for each variation keyed by variation ID.
* @param {Object} selectedAttributes Attribute Name Value pairs of current selections by the user.
* @return {number} Variation ID.
*/
export const getVariationMatchingSelectedAttributes = (
attributes,
variationAttributes,
selectedAttributes
) => {
const matchingVariationIds = getVariationsMatchingSelectedAttributes(
attributes,
variationAttributes,
selectedAttributes
);
return matchingVariationIds[ 0 ] || 0;
};
/**
* Given a list of terms, filter them and return valid options for the select boxes.
*
* @see getActiveSelectControlOptions
* @param {Object} attributeTerms List of attribute term objects.
* @param {?Array} validAttributeTerms Valid values if selections have been made already.
* @return {Array} Value/Label pairs of select box options.
*/
const getValidSelectControlOptions = (
attributeTerms,
validAttributeTerms = null
) => {
return Object.values( attributeTerms )
.map( ( { name, slug } ) => {
if (
validAttributeTerms === null ||
validAttributeTerms.includes( null ) ||
validAttributeTerms.includes( slug )
) {
return {
value: slug,
label: decodeEntities( name ),
};
}
return null;
} )
.filter( Boolean );
};
/**
* Given a list of terms, filter them and return active options for the select boxes. This factors in
* which options should be hidden due to current selections.
*
* @param {Object} attributes List of attribute names and terms.
* @param {Object} variationAttributes Attributes for each variation keyed by variation ID.
* @param {Object} selectedAttributes Attribute Name Value pairs of current selections by the user.
* @return {Object} Select box options.
*/
export const getActiveSelectControlOptions = (
attributes,
variationAttributes,
selectedAttributes
) => {
const options = {};
const attributeNames = Object.keys( attributes );
const hasSelectedAttributes =
Object.values( selectedAttributes ).filter( Boolean ).length > 0;
attributeNames.forEach( ( attributeName ) => {
const currentAttribute = attributes[ attributeName ];
const selectedAttributesExcludingCurrentAttribute = {
...selectedAttributes,
[ attributeName ]: null,
};
// This finds matching variations for selected attributes apart from this one. This will be
// used to get valid attribute terms of the current attribute narrowed down by those matching
// variation IDs. For example, if I had Large Blue Shirts and Medium Red Shirts, I want to only
// show Red shirts if Medium is selected.
const matchingVariationIds = hasSelectedAttributes
? getVariationsMatchingSelectedAttributes(
attributes,
variationAttributes,
selectedAttributesExcludingCurrentAttribute
)
: null;
// Uses the above matching variation IDs to get the attributes from just those variations.
const validAttributeTerms =
matchingVariationIds !== null
? matchingVariationIds.map(
( varId ) =>
variationAttributes[ 'id:' + varId ].attributes[
attributeName
]
)
: null;
// Intersects attributes with valid attributes.
options[ attributeName ] = getValidSelectControlOptions(
currentAttribute.terms,
validAttributeTerms
);
} );
return options;
};