Skip to content

Commit

Permalink
Merge pull request #34 from fixeditforyou/handle-multiselect-values
Browse files Browse the repository at this point in the history
Handle multi-select attribute values
  • Loading branch information
mmenozzi authored Feb 5, 2021
2 parents f632825 + e2914b9 commit ce62ae0
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 15 deletions.
123 changes: 115 additions & 8 deletions spec/ValueHandler/AttributeValueHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ function it_throws_exception_during_handle_when_attribute_is_not_found(ProductVa
->during('handle', [$productVariant, self::NOT_EXISTING_ATTRIBUTE_CODE, []]);
}

function it_creates_text_product_attribute_value_from_factory_with_all_locales_if_it_does_not_already_exists(
function it_creates_text_product_attribute_value_from_factory_with_all_locales_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductAttributeValueInterface $itAttributeValue,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -207,7 +207,7 @@ function it_creates_text_product_attribute_value_from_factory_with_all_locales_i
$deAttributeValue->setValue('Agape')->shouldHaveBeenCalled();
}

function it_creates_text_product_attribute_value_from_factory_with_the_given_locale_if_it_does_not_already_exists(
function it_creates_text_product_attribute_value_from_factory_with_the_given_locale_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductAttributeValueInterface $itAttributeValue,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -242,7 +242,7 @@ function it_creates_text_product_attribute_value_from_factory_with_the_given_loc
$deAttributeValue->setValue('Holz')->shouldNotHaveBeenCalled();
}

function it_creates_checkbox_product_attribute_value_from_factory_with_all_locales_if_it_does_not_already_exists(
function it_creates_checkbox_product_attribute_value_from_factory_with_all_locales_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductAttributeValueInterface $itAttributeValue,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -273,7 +273,7 @@ function it_creates_checkbox_product_attribute_value_from_factory_with_all_local
$deAttributeValue->setValue(true)->shouldHaveBeenCalled();
}

function it_creates_checkbox_product_attribute_value_from_factory_with_the_given_locale_if_it_does_not_already_exists(
function it_creates_checkbox_product_attribute_value_from_factory_with_the_given_locale_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductAttributeValueInterface $itAttributeValue,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -308,7 +308,7 @@ function it_creates_checkbox_product_attribute_value_from_factory_with_the_given
$deAttributeValue->setValue(false)->shouldNotHaveBeenCalled();
}

function it_creates_product_select_attribute_value_with_the_given_locale_if_it_does_not_already_exists(
function it_creates_select_product_attribute_value_with_the_given_locale_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -339,7 +339,7 @@ function it_creates_product_select_attribute_value_with_the_given_locale_if_it_d
$itAttributeValue->setValue(['brand_agape_IT'])->shouldHaveBeenCalled();
}

function it_creates_select_product_attribute_value_with_all_locales_if_it_does_not_already_exists(
function it_creates_select_product_attribute_value_with_all_locales_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -369,7 +369,68 @@ function it_creates_select_product_attribute_value_with_all_locales_if_it_does_n
$product->addAttribute($deAttributeValue)->shouldHaveBeenCalled();
}

function it_creates_integer_product_attribute_value_with_all_locales_if_it_does_not_already_exists(
function it_creates_select_product_attribute_value_with_all_options_and_the_given_locale_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductAttributeValueInterface $enAttributeValue,
ProductAttributeValueInterface $itAttributeValue,
FactoryInterface $factory
) {
$factory->createNew()->willReturn($enAttributeValue, $itAttributeValue);
$product->getAttributeByCodeAndLocale(Argument::type('string'), Argument::type('string'))->willReturn(null);
$value = [
[
'scope' => null,
'locale' => 'en_US',
'data' => ['brand_agape_US', 'brand_agape', 'brand_agape_plus'],
],
[
'scope' => null,
'locale' => 'it_IT',
'data' => ['brand_agape_IT', 'brand_agape', 'brand_agape_plus'],
],
];
$this->handle($productVariant, self::SELECT_ATTRIBUTE_CODE, $value);

$product->addAttribute($enAttributeValue)->shouldHaveBeenCalled();
$product->addAttribute($itAttributeValue)->shouldHaveBeenCalled();
$enAttributeValue->setLocaleCode('en_US')->shouldHaveBeenCalled();
$enAttributeValue->setValue(['brand_agape_US', 'brand_agape', 'brand_agape_plus'])->shouldHaveBeenCalled();
$itAttributeValue->setLocaleCode('it_IT')->shouldHaveBeenCalled();
$itAttributeValue->setValue(['brand_agape_IT', 'brand_agape', 'brand_agape_plus'])->shouldHaveBeenCalled();
}

function it_creates_select_product_attribute_value_with_all_options_and_all_locales_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductAttributeValueInterface $enAttributeValue,
ProductAttributeValueInterface $itAttributeValue,
ProductAttributeValueInterface $deAttributeValue,
FactoryInterface $factory
) {
$factory->createNew()->willReturn($enAttributeValue, $itAttributeValue, $deAttributeValue);
$product->getAttributeByCodeAndLocale(Argument::type('string'), Argument::type('string'))->willReturn(null);
$value = [
[
'scope' => null,
'locale' => null,
'data' => ['brand_agape', 'brand_agape_plus'],
],
];
$this->handle($productVariant, self::SELECT_ATTRIBUTE_CODE, $value);

$enAttributeValue->setLocaleCode('en_US')->shouldHaveBeenCalled();
$enAttributeValue->setValue(['brand_agape', 'brand_agape_plus'])->shouldHaveBeenCalled();
$itAttributeValue->setLocaleCode('it_IT')->shouldHaveBeenCalled();
$itAttributeValue->setValue(['brand_agape', 'brand_agape_plus'])->shouldHaveBeenCalled();
$deAttributeValue->setLocaleCode('de_DE')->shouldHaveBeenCalled();
$deAttributeValue->setValue(['brand_agape', 'brand_agape_plus'])->shouldHaveBeenCalled();
$product->addAttribute($enAttributeValue)->shouldHaveBeenCalled();
$product->addAttribute($itAttributeValue)->shouldHaveBeenCalled();
$product->addAttribute($deAttributeValue)->shouldHaveBeenCalled();
}

function it_creates_integer_product_attribute_value_with_all_locales_if_it_does_not_already_exist(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductAttributeValueInterface $enAttributeValue,
Expand Down Expand Up @@ -416,7 +477,53 @@ function it_throws_error_when_select_value_is_not_an_existing_option(
->shouldThrow(
new \InvalidArgumentException(
'This select attribute can only save existing attribute options. ' .
'Attribute option with the given brand_not_existing code does not exist.',
'Attribute option codes [brand_not_existing] do not exist.',
)
)
->during('handle', [$productVariant, self::SELECT_ATTRIBUTE_CODE, $value]);
}

function it_throws_error_when_select_values_are_not_existing_options(
ProductVariantInterface $productVariant,
ProductInterface $product
) {
$product->getAttributeByCodeAndLocale(Argument::type('string'), Argument::type('string'))->willReturn(null);
$value = [
[
'scope' => null,
'locale' => null,
'data' => ['brand_not_existing'],
],
];

$this
->shouldThrow(
new \InvalidArgumentException(
'This select attribute can only save existing attribute options. ' .
'Attribute option codes [brand_not_existing] do not exist.',
)
)
->during('handle', [$productVariant, self::SELECT_ATTRIBUTE_CODE, $value]);
}

function it_throws_error_when_select_values_are_not_all_existing_options(
ProductVariantInterface $productVariant,
ProductInterface $product
) {
$product->getAttributeByCodeAndLocale(Argument::type('string'), Argument::type('string'))->willReturn(null);
$value = [
[
'scope' => null,
'locale' => null,
'data' => ['brand_agape', 'brand_not_existing'],
],
];

$this
->shouldThrow(
new \InvalidArgumentException(
'This select attribute can only save existing attribute options. ' .
'Attribute option codes [brand_not_existing] do not exist.',
)
)
->during('handle', [$productVariant, self::SELECT_ATTRIBUTE_CODE, $value]);
Expand Down
15 changes: 8 additions & 7 deletions src/ValueHandler/AttributeValueHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public function handle($subject, string $attributeCode, array $value): void
}

/**
* @param bool|string $value
* @param array|int|string|bool $value
*/
private function addAttributeValue(
AttributeInterface $attribute,
Expand Down Expand Up @@ -147,26 +147,27 @@ private function isProductOption(ProductVariantInterface $subject, string $attri
}

/**
* @param int|string|bool $value
* @param array|int|string|bool $value
*
* @return array|int|string|bool
*/
private function getAttributeValue(AttributeInterface $attribute, $value)
{
if ($attribute->getType() === SelectAttributeType::TYPE) {
$value = (array) $value;
$attributeConfiguration = $attribute->getConfiguration();
$possibleOptionsCodes = array_map('strval', array_keys($attributeConfiguration['choices']));
if (!in_array($value, $possibleOptionsCodes, true)) {
$invalid = array_diff($value, $possibleOptionsCodes);

if (!empty($invalid)) {
throw new \InvalidArgumentException(
sprintf(
'This select attribute can only save existing attribute options. ' .
'Attribute option with the given %s code does not exist.',
$value
'Attribute option codes [%s] do not exist.',
implode(', ', $invalid)
)
);
}

return [$value];
}

return $value;
Expand Down

0 comments on commit ce62ae0

Please sign in to comment.