diff --git a/src/DataMapper/Product/OptionsDataMapper.php b/src/DataMapper/Product/OptionsDataMapper.php new file mode 100644 index 0000000..4667cc7 --- /dev/null +++ b/src/DataMapper/Product/OptionsDataMapper.php @@ -0,0 +1,45 @@ +supports($source, $target, $indexScope, $context)); + + foreach ($source->getEnabledVariants() as $variant) { + foreach ($variant->getOptionValues() as $optionValue) { + $option = $optionValue->getOption()?->getCode(); + if ($option === null) { + continue; + } + + $target->options[$option][] = (string) $optionValue->getValue(); + } + } + + foreach ($target->options as $option => $values) { + $target->options[$option] = array_values(array_unique($values)); + } + } + + /** + * @psalm-assert-if-true ProductInterface $source + * @psalm-assert-if-true ProductDocument $target + */ + public function supports(IndexableInterface $source, Document $target, IndexScope $indexScope, array $context = []): bool + { + return $source instanceof ProductInterface && $target instanceof ProductDocument; + } +} diff --git a/src/Document/Product.php b/src/Document/Product.php index f4d9a70..db99cd1 100644 --- a/src/Document/Product.php +++ b/src/Document/Product.php @@ -43,6 +43,9 @@ class Product extends Document implements UrlAwareInterface, ImageUrlsAwareInter public ?float $originalPrice = null; + /** @var array> */ + public array $options = []; + /** * This attribute will allow you to create a filter like 'Only show products on sale' */ diff --git a/src/Normalizer/ProductNormalizer.php b/src/Normalizer/ProductNormalizer.php new file mode 100644 index 0000000..6ddb836 --- /dev/null +++ b/src/Normalizer/ProductNormalizer.php @@ -0,0 +1,59 @@ +supportsNormalization($object)) { + throw new LogicException(sprintf('The object must be an instance of %s', Product::class)); + } + + $data = $this->normalizer->normalize($object, $format, $context); + if ($data instanceof \ArrayObject) { + $data = $data->getArrayCopy(); + } + + if (!is_array($data)) { + throw new LogicException('The normalized product data must be an array or an ArrayObject'); + } + + /** + * @var string $option + * @var list $values + */ + foreach ($data['options'] as $option => $values) { + $data[$option . '_option'] = $values; + } + + unset($data['options']); + + return $data; + } + + /** + * @psalm-assert-if-true Product $data + */ + public function supportsNormalization(mixed $data, ?string $format = null): bool + { + return $data instanceof Product; + } + + public function getSupportedTypes(?string $format): array + { + return [ + Product::class => true, + ]; + } +} diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 8a9d8b6..05e32da 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -11,6 +11,7 @@ + diff --git a/src/Resources/config/services/data_mapper.xml b/src/Resources/config/services/data_mapper.xml index ecc8c21..7b1c79e 100644 --- a/src/Resources/config/services/data_mapper.xml +++ b/src/Resources/config/services/data_mapper.xml @@ -41,6 +41,10 @@ + + + + diff --git a/src/Resources/config/services/normalizer.xml b/src/Resources/config/services/normalizer.xml new file mode 100644 index 0000000..b501224 --- /dev/null +++ b/src/Resources/config/services/normalizer.xml @@ -0,0 +1,11 @@ + + + + + + + + + +