/** * {@inheritdoc} */ protected function normalizeVariantGroupValues(GroupInterface $group, $format, array $context) { if (!$group->getType()->isVariant() || null === $group->getProductTemplate()) { return []; } $valuesData = $group->getProductTemplate()->getValuesData(); $values = $this->valuesDenormalizer->denormalize($valuesData, 'ProductValue[]', 'json'); $normalizedValues = []; foreach ($values as $value) { $normalizedValues = array_replace($normalizedValues, $this->serializer->normalize($value, $format, ['entity' => 'product'] + $context)); } ksort($normalizedValues); return $normalizedValues; }
function it_updates_a_variant_group($attributeRepository, $groupTypeRepository, $productBuilder, GroupInterface $variantGroup, AttributeInterface $attribute, GroupTypeInterface $type, GroupTranslation $translatable, ProductInterface $product, ProductTemplateInterface $productTemplate) { $groupTypeRepository->findOneByIdentifier('VARIANT')->willReturn($type); $attributeRepository->findOneByIdentifier('main_color')->willReturn($attribute); $attributeRepository->findOneByIdentifier('secondary_color')->willReturn($attribute); $variantGroup->getTranslation()->willReturn($translatable); $translatable->setLabel('T-shirt super beau')->shouldBeCalled(); $variantGroup->setCode('mycode')->shouldBeCalled(); $variantGroup->setLocale('fr_FR')->shouldBeCalled(); $variantGroup->setType($type)->shouldBeCalled(); $variantGroup->getId()->willReturn(null); $variantGroup->addAxisAttribute(Argument::any())->shouldBeCalled(); $productTemplate->getValuesData()->willReturn([]); $productTemplate->setValues(Argument::any())->shouldBeCalled(); $productTemplate->setValuesData(['main_color' => [['locale' => null, 'scope' => null, 'data' => 'white']]])->shouldBeCalled(); $variantGroup->getProductTemplate()->willReturn($productTemplate); $variantGroup->setProductTemplate($productTemplate)->shouldBeCalled(); $productValue = new ProductValue(); $identifierValue = new ProductValue(); $productBuilder->createProduct()->willReturn($product); $product->getValues()->willReturn(new ArrayCollection([$productValue, $identifierValue])); $product->getIdentifier()->willReturn($identifierValue); $values = ['code' => 'mycode', 'axis' => ['main_color', 'secondary_color'], 'type' => 'VARIANT', 'labels' => ['fr_FR' => 'T-shirt super beau'], 'values' => ['main_color' => [['locale' => null, 'scope' => null, 'data' => 'white']]]]; $this->update($variantGroup, $values, []); }
/** * Normalize the variant group values * * @param GroupInterface $variantGroup * * @return array */ protected function normalizeVariantGroupValues(GroupInterface $variantGroup) { if (null === ($template = $variantGroup->getProductTemplate())) { return []; } return $template->getValuesData(); }
function it_handles_media_values_of_variant_group_product_templates($templateMediaManager, $eventDispatcher, GroupInterface $group, GroupType $type, ProductTemplateInterface $template) { $group->getType()->willReturn($type); $group->getCode()->willReturn('my_code'); $type->isVariant()->willReturn(true); $group->getProductTemplate()->willReturn($template); $templateMediaManager->handleProductTemplateMedia($template)->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::PRE_SAVE, Argument::cetera())->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::POST_SAVE, Argument::cetera())->shouldBeCalled(); $this->save($group); }
function it_throws_an_exception_if_media_of_variant_group_is_not_found($normalizer, $denormalizer, ArrayCollection $productValuesCollection, ArrayCollection $mediaCollection, ProductMediaInterface $media, GroupInterface $variantGroup, ProductTemplateInterface $productTemplate, ProductValueInterface $productValue) { $variantGroup->getProductTemplate()->willReturn($productTemplate); $variantGroup->getCode()->willReturn('my_variant_group'); $productTemplate->getValuesData()->willReturn([$productValue]); $denormalizer->denormalize([$productValue], 'ProductValue[]', 'json')->willReturn($productValuesCollection); $productValuesCollection->filter(Argument::cetera())->willReturn($mediaCollection); $mediaCollection->toArray()->willReturn([$media]); $normalizer->normalize([$media], 'csv', ['field_name' => 'media', 'prepare_copy' => true, 'identifier' => 'my_variant_group'])->willThrow(new FileNotFoundException('upload/path/img.jpg')); $this->shouldThrow(new InvalidItemException('The file "upload/path/img.jpg" does not exist', ['item' => 'my_variant_group', 'uploadDirectory' => 'upload/path/']))->duringProcess($variantGroup); }
function it_returns_non_eligible_attributes($attributeRepository, GroupInterface $group, ProductTemplateInterface $template, AttributeInterface $length, AttributeInterface $name, AttributeInterface $color, AttributeInterface $identifier, Collection $collection) { $group->getProductTemplate()->willReturn($template); $group->getAxisAttributes()->willReturn($collection); $collection->toArray()->willReturn([$length]); $template->getValuesData()->willReturn(['name' => 'foo', 'color' => 'bar']); $attributeRepository->findOneByIdentifier('name')->willReturn($name); $attributeRepository->findOneByIdentifier('color')->willReturn($color); $attributeRepository->findBy(['unique' => true])->willReturn([$name, $identifier]); $attributes = [$length, $name, $color, $identifier]; $this->getNonEligibleAttributes($group)->shouldReturn($attributes); }
/** * Fetch medias in local filesystem * * @param GroupInterface $variantGroup * @param string $directory */ protected function fetchMedia(GroupInterface $variantGroup, $directory) { if (null === ($productTemplate = $variantGroup->getProductTemplate())) { return; } $identifier = $variantGroup->getCode(); $this->variantGroupUpdater->update($variantGroup, ['values' => $productTemplate->getValuesData()]); $this->mediaFetcher->fetchAll($productTemplate->getValues(), $directory, $identifier); foreach ($this->mediaFetcher->getErrors() as $error) { $this->stepExecution->addWarning($error['message'], [], new DataInvalidItem($error['media'])); } }
/** * Validate variant group product template values * * @param GroupInterface $variantGroup * @param Constraint $constraint */ protected function validateProductTemplateValues(GroupInterface $variantGroup, Constraint $constraint) { $template = $variantGroup->getProductTemplate(); $valuesData = $template->getValuesData(); $forbiddenAttrCodes = $this->attributeRepository->findUniqueAttributeCodes(); foreach ($variantGroup->getAxisAttributes() as $axisAttribute) { $forbiddenAttrCodes[] = $axisAttribute->getCode(); } $invalidAttrCodes = array_intersect($forbiddenAttrCodes, array_keys($valuesData)); if (count($invalidAttrCodes) > 0) { $this->context->buildViolation($constraint->message, ['%group%' => $variantGroup->getCode(), '%attributes%' => $this->formatValues($invalidAttrCodes)])->addViolation(); } }
function it_does_not_copy_values_to_products_when_template_is_empty(GroupInterface $variantGroup, ProductTemplateInterface $productTemplate, Collection $productCollection, ProductInterface $productOne, ProductInterface $productTwo, $productTplApplier, $stepExecution) { $variantGroup->getId()->willReturn(42); $stepExecution->incrementSummaryInfo('process')->shouldBeCalled(); $variantGroup->getProductTemplate()->willReturn($productTemplate); $productTemplate->getValuesData()->willReturn([]); $variantGroup->getProducts()->willReturn($productCollection); $productCollection->isEmpty()->willReturn(false); $productCollection->toArray()->willReturn([$productOne, $productTwo]); $productCollection->count()->willReturn(2); $productTplApplier->apply($productTemplate, [$productOne, $productTwo])->shouldNotBeCalled(); $this->write([$variantGroup]); }
function it_handles_media_values_of_variant_group_product_templates($optionsResolver, $templateMediaManager, $eventDispatcher, GroupInterface $group, GroupType $type, ProductTemplateInterface $template) { $optionsResolver->resolveSaveOptions(Argument::any())->willReturn(['flush' => true, 'copy_values_to_products' => false]); $group->getProducts()->willReturn(new ArrayCollection([])); $group->getType()->willReturn($type); $group->getCode()->willReturn('my_code'); $group->getId()->willReturn(null); $group->getProductTemplate()->willReturn($template); $type->isVariant()->willReturn(true); $templateMediaManager->handleProductTemplateMedia($template)->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::PRE_SAVE, Argument::cetera())->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::POST_SAVE, Argument::cetera())->shouldBeCalled(); $this->save($group); }
/** * Get non eligible attributes to a product template * * @param GroupInterface $variantGroup * * @return AttributeInterface[] */ public function getNonEligibleAttributes(GroupInterface $variantGroup) { $attributes = $variantGroup->getAxisAttributes()->toArray(); $template = $variantGroup->getProductTemplate(); if (null !== $template) { foreach (array_keys($template->getValuesData()) as $attributeCode) { $attributes[] = $this->attributeRepository->findOneByIdentifier($attributeCode); } } $uniqueAttributes = $this->attributeRepository->findBy(['unique' => true]); foreach ($uniqueAttributes as $attribute) { if (!in_array($attribute, $attributes)) { $attributes[] = $attribute; } } return $attributes; }
function it_adds_a_violation_if_variant_group_template_contains_a_unique_attribute(GroupInterface $variantGroup, GroupType $type, ProductTemplateInterface $template, VariantGroupValues $constraint, $attributeRepository, $context, ConstraintViolationBuilderInterface $violation) { $variantGroup->getType()->willReturn($type); $variantGroup->getCode()->willReturn('tshirt'); $type->isVariant()->willReturn(true); $variantGroup->getProductTemplate()->willReturn($template); $variantGroup->getAxisAttributes()->willReturn([]); $attributeRepository->findUniqueAttributeCodes()->willReturn(['sku', 'barcode']); $template->getValuesData()->willReturn(['sku' => 'SKU-001']); $violationData = ['%group%' => 'tshirt', '%attributes%' => '"sku"']; $context->buildViolation($constraint->message, $violationData)->shouldBeCalled()->willReturn($violation); $this->validate($variantGroup, $constraint); $template->getValuesData()->willReturn(['sku' => 'SKU-001', 'barcode' => 01122334455]); $violationData = ['%group%' => 'tshirt', '%attributes%' => '"sku", "barcode"']; $context->buildViolation($constraint->message, $violationData)->shouldBeCalled()->willReturn($violation); $this->validate($variantGroup, $constraint); }
function it_normalizes_a_variant_group_with_its_values($transNormalizer, $valuesDenormalizer, $valuesNormalizer, GroupInterface $group, GroupTypeInterface $groupType, AttributeInterface $attr, ProductTemplateInterface $productTemplate) { $groupType->getCode()->willReturn('VARIANT'); $groupType->isVariant()->willReturn(true); $group->getCode()->willReturn('laser_sabers'); $valuesData = ['name' => 'Light saber model', 'size' => '120']; $context = ['with_variant_group_values' => true]; $format = 'csv'; $productTemplate->getValuesData()->willReturn($valuesData); $valuesDenormalizer->denormalize($valuesData, Argument::any(), Argument::any())->willReturn('denormalized_values'); $valuesNormalizer->normalize('denormalized_values', Argument::any(), Argument::any())->willReturn('normalized_values'); $group->getProductTemplate()->willReturn($productTemplate); $group->getType()->willReturn($groupType); $attr->getCode()->willReturn('light_color'); $group->getAxisAttributes()->willReturn([$attr]); $transNormalizer->normalize($group, $format, $context)->willReturn([]); $this->normalize($group, $format, $context)->shouldReturn(['code' => 'laser_sabers', 'type' => 'VARIANT', 'axis' => ['light_color'], 'values' => 'normalized_values']); }
/** * Copy variant group values to products * * @param GroupInterface $variantGroup */ protected function copyValuesToProducts(GroupInterface $variantGroup) { $template = $variantGroup->getProductTemplate(); $products = $variantGroup->getProducts(); if ($template && count($template->getValuesData()) > 0 && count($products) > 0) { $skippedMessages = $this->productTplApplier->apply($template, $products->toArray()); $nbSkipped = count($skippedMessages); $nbUpdated = count($products) - $nbSkipped; $this->incrementUpdatedProductsCount($nbUpdated); if ($nbSkipped > 0) { $this->incrementSkippedProductsCount($nbSkipped, $skippedMessages); } } }
/** * Prepares media files present in the product template of the variant group for export. * Returns an array of files to be copied from 'filePath' to 'exportPath'. * * @param GroupInterface $group * * @throws InvalidItemException If a media file is not found * * @return array */ protected function prepareVariantGroupMedia(GroupInterface $group) { $mediaValues = $this->getProductTemplateMediaValues($group->getProductTemplate()); if (count($mediaValues) < 1) { return []; } try { return $this->normalizer->normalize($mediaValues, $this->format, ['field_name' => 'media', 'prepare_copy' => true, 'identifier' => $group->getCode()]); } catch (FileNotFoundException $e) { throw new InvalidItemException($e->getMessage(), ['item' => $group->getCode(), 'uploadDirectory' => $this->uploadDirectory]); } }
function it_merges_original_and_new_values(GroupInterface $variantGroup, ProductTemplateInterface $template, ProductBuilderInterface $productBuilder, ProductInterface $product, ProductValueInterface $identifier, ArrayCollection $values, \Iterator $valuesIterator) { $originalValues = ['description' => [['locale' => 'en_US', 'scope' => 'ecommerce', 'data' => 'original description en_US'], ['locale' => 'de_DE', 'scope' => 'ecommerce', 'data' => 'original description de_DE']]]; $newValues = ['description' => [['locale' => 'en_US', 'scope' => 'ecommerce', 'data' => 'new description en_US'], ['locale' => 'fr_FR', 'scope' => 'ecommerce', 'data' => 'new description fr_FR']]]; $expectedValues = ['description' => [['locale' => 'en_US', 'scope' => 'ecommerce', 'data' => 'new description en_US'], ['locale' => 'de_DE', 'scope' => 'ecommerce', 'data' => 'original description de_DE'], ['locale' => 'fr_FR', 'scope' => 'ecommerce', 'data' => 'new description fr_FR']]]; $variantGroup->getProductTemplate()->willReturn($template); $template->getValuesData()->willReturn($originalValues); $productBuilder->createProduct()->willReturn($product); $product->getValues()->willReturn($values); $product->getIdentifier()->willReturn($identifier); $values->removeElement($identifier)->shouldBeCalled(); $values->getIterator()->willReturn($valuesIterator); $template->setValues($values)->shouldBeCalled(); $template->setValuesData($expectedValues)->shouldBeCalled(); $variantGroup->setProductTemplate($template)->shouldBeCalled(); $this->setValues($variantGroup, $newValues); }
/** * Normalize the variant group values * * @param GroupInterface $group * @param string $format * @param array $context * * @return array */ protected function normalizeVariantGroupValues(GroupInterface $group, $format, array $context) { if (!$group->getType()->isVariant() || null === $group->getProductTemplate()) { return []; } $context["entity"] = "variant-group"; // As variant group > product template > values data are not type hinted we cannot normalize them directly // so we first denormalize them into product values using the common format then normalize them // this allow to transform localization based values for example return $this->valuesNormalizer->normalize($this->valuesDenormalizer->denormalize($group->getProductTemplate()->getValuesData(), $format, $context), $format, $context); }
/** * Convert localized values in template of a variant group * * @param GroupInterface $group */ protected function convertLocalizedValues(GroupInterface $group) { $template = $group->getProductTemplate(); if (null === $template) { return; } $options = ['locale' => $this->request->getLocale(), 'disable_grouping_separator' => true]; $valuesData = $this->localizedConverter->convertLocalizedToDefaultValues($template->getValuesData(), $options); $template->setValuesData($valuesData); }
function it_has_attribute_in_a_variant_group_template(AttributeInterface $attribute, GroupInterface $group, GroupTypeInterface $groupType, ArrayCollection $groupAttributes, ProductTemplateInterface $template) { $groupType->isVariant()->willReturn(true); $groupAttributes->contains($attribute)->willReturn(false); $template->hasValueForAttribute($attribute)->shouldBeCalled()->willReturn(true); $group->getType()->willReturn($groupType); $group->getProductTemplate()->willReturn($template); $group->getAxisAttributes()->willReturn($groupAttributes); $group->addProduct($this)->willReturn($this); $this->addGroup($group); $this->hasAttributeInVariantGroup($attribute)->shouldReturn(true); }
function it_throws_an_exception_if_media_of_variant_group_is_not_found($objectDetacher, $normalizer, $mediaFetcher, $stepExecution, $variantGroupUpdater, ArrayCollection $productValueCollection, FileInfoInterface $media1, FileInfoInterface $media2, GroupInterface $variantGroup, ProductTemplateInterface $productTemplate, ProductValueInterface $productValue1, ProductValueInterface $productValue2, JobParameters $jobParameters, JobExecution $jobExecution, JobInstance $jobInstance, ExecutionContext $executionContext) { $stepExecution->getJobParameters()->willReturn($jobParameters); $jobParameters->get('filePath')->willReturn('my/path/variant_group.csv'); $jobParameters->has('with_media')->willReturn(true); $jobParameters->get('with_media')->willReturn(true); $variantGroup->getProductTemplate()->willReturn($productTemplate); $variantGroup->getCode()->willReturn('my_variant_group'); $productValueCollection->toArray()->willReturn([$productValue1, $productValue2]); $productValue1->setMedia($media1); $productValue2->setMedia($media2); $stepExecution->getJobExecution()->willReturn($jobExecution); $jobExecution->getJobInstance()->willReturn($jobInstance); $jobExecution->getId()->willReturn(100); $jobInstance->getCode()->willReturn('csv_variant_group_export'); $jobExecution->getExecutionContext()->willReturn($executionContext); $executionContext->get(JobInterface::WORKING_DIRECTORY_PARAMETER)->willReturn('/working/directory/'); $values = ['picture' => ['locale' => null, 'scope' => null, 'data' => ['filePath' => 'path/not_found.jpg']]]; $variantStandard = ['code' => 'my_variant_group', 'values' => $values]; $normalizer->normalize($variantGroup, null, ['with_variant_group_values' => true, 'identifier' => 'my_variant_group'])->willReturn($variantStandard); $variantGroupUpdater->update($variantGroup, ['values' => $variantStandard['values']])->shouldBeCalled(); $productTemplate->getValuesData()->willReturn($variantStandard['values']); $productTemplate->getValues()->willReturn($productValueCollection); $mediaFetcher->fetchAll($productValueCollection, '/working/directory/', 'my_variant_group')->shouldBeCalled(); $mediaFetcher->getErrors()->willReturn([['message' => 'The media has not been found or is not currently available', 'media' => ['filePath' => 'path/not_found.jpg']]]); $stepExecution->addWarning('The media has not been found or is not currently available', [], new DataInvalidItem(['filePath' => 'path/not_found.jpg']))->shouldBeCalled(); $this->process($variantGroup)->shouldReturn($variantStandard); $objectDetacher->detach($variantGroup)->shouldBeCalled(); }
function it_normalizes_a_variant_group_with_its_values_on_versioning_context($transNormalizer, $valuesDenormalizer, GroupInterface $group, CustomSerializer $serializer, GroupTypeInterface $groupType, AttributeInterface $attr, ProductTemplateInterface $productTemplate, ProductValueInterface $productValue1) { $groupType->getCode()->willReturn('VARIANT'); $groupType->isVariant()->willReturn(true); $group->getCode()->willReturn('lego'); $valuesData = ['name' => 'Light saber model', 'size' => '120']; $context = ['versioning' => true]; $format = 'csv'; $productTemplate->getValuesData()->willReturn($valuesData); $valuesDenormalizer->denormalize($valuesData, 'ProductValue[]', 'json')->willReturn([$productValue1]); $newContext = array_merge($context, ['with_variant_group_values' => true]); $serializer->normalize($productValue1, $format, ['entity' => 'product'] + $newContext)->willReturn(['age' => '6+']); $group->getProductTemplate()->willReturn($productTemplate); $group->getType()->willReturn($groupType); $attr->getCode()->willReturn('model'); $group->getAxisAttributes()->willReturn([$attr]); $transNormalizer->normalize($group, $format, $context)->willReturn([]); $this->setSerializer($serializer); $this->normalize($group, $format, $context)->shouldReturn(['code' => 'lego', 'type' => 'VARIANT', 'axis' => 'model', 'age' => '6+']); }
/** * Copy the variant group values on any products belonging in the variant group * * @param GroupInterface $group */ protected function copyVariantGroupValues(GroupInterface $group) { $template = $group->getProductTemplate(); $products = $group->getProducts()->toArray(); $this->productTplApplier->apply($template, $products); }
/** * @param GroupInterface $variantGroup * * @return \Pim\Component\Catalog\Model\ProductTemplateInterface */ protected function getProductTemplate(GroupInterface $variantGroup) { if ($variantGroup->getProductTemplate()) { $template = $variantGroup->getProductTemplate(); } else { $template = new $this->templateClass(); $variantGroup->setProductTemplate($template); } return $template; }
/** * Normalize the variant group values * * @param GroupInterface $group * @param string $format * @param array $context * * @return array */ protected function normalizeVariantGroupValues(GroupInterface $group, $format, array $context) { $valuesData = []; if ($group->getType()->isVariant() && null !== $group->getProductTemplate()) { $template = $group->getProductTemplate(); $valuesData = $template->getValuesData(); } return $valuesData; }