function it_provides_formatted_batch_config_for_the_job(GroupInterface $oroTshirt) { $oroTshirt->getCode()->willReturn('oro_tshirt'); $this->setGroup($oroTshirt); $this->setFilters([['id', 'IN', ['22', '7']]]); $this->getBatchConfig()->shouldReturn('{\\"filters\\":[[\\"id\\",\\"IN\\",[\\"22\\",\\"7\\"]]],\\"actions\\":{\\"field\\":\\"variant_group\\",\\"value\\":\\"oro_tshirt\\"}}'); }
function it_provides_formatted_batch_config_for_the_job(GroupInterface $oroTshirt) { $oroTshirt->getCode()->willReturn('oro_tshirt'); $this->setGroup($oroTshirt); $this->setFilters([['id', 'IN', ['22', '7']]]); $this->getBatchConfig()->shouldReturn(['filters' => [['id', 'IN', ['22', '7']]], 'actions' => ['field' => 'variant_group', 'value' => 'oro_tshirt']]); }
/** * @param VariantGroupAxis $constraint * @param GroupInterface $variantGroup */ protected function validateAttributeAxis(VariantGroupAxis $constraint, GroupInterface $variantGroup) { $allowedTypes = [AttributeTypes::OPTION_SIMPLE_SELECT, AttributeTypes::REFERENCE_DATA_SIMPLE_SELECT]; foreach ($variantGroup->getAxisAttributes() as $attribute) { if (!in_array($attribute->getAttributeType(), $allowedTypes)) { $this->addInvalidAxisViolation($constraint, $variantGroup->getCode(), $attribute->getCode()); } } }
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); }
/** * 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'])); } }
function it_provides_formatted_batch_config_for_the_job(GroupInterface $officeGroup, GroupInterface $bedroomGroup, ArrayCollection $groupCollection) { $officeGroup->getCode()->willReturn('office_room'); $bedroomGroup->getCode()->willReturn('bedroom'); $groupCollection->add($officeGroup); $groupCollection->add($bedroomGroup); $this->setGroups($groupCollection); $groupCollection->map(Argument::type('closure'))->willReturn($groupCollection); $groupCollection->toArray()->willReturn(['office_room', 'bedroom']); $this->setFilters([['id', 'IN', ['22', '7']]]); $this->getBatchConfig()->shouldReturn(['filters' => [['id', 'IN', ['22', '7']]], 'actions' => [['field' => 'groups', 'value' => ['office_room', 'bedroom']]]]); }
function it_provides_formatted_batch_config_for_the_job(GroupInterface $officeGroup, GroupInterface $bedroomGroup, ArrayCollection $groupCollection) { $officeGroup->getCode()->willReturn('office_room'); $bedroomGroup->getCode()->willReturn('bedroom'); $groupCollection->add($officeGroup); $groupCollection->add($bedroomGroup); $this->setGroups($groupCollection); $groupCollection->map(Argument::type('closure'))->willReturn($groupCollection); $groupCollection->toArray()->willReturn(['office_room', 'bedroom']); $this->setFilters([['id', 'IN', ['22', '7']]]); $this->getBatchConfig()->shouldReturn('{\\"filters\\":[[\\"id\\",\\"IN\\",[\\"22\\",\\"7\\"]]],\\"actions\\":[{\\"field\\":\\"groups\\",\\"value\\":[\\"office_room\\",\\"bedroom\\"]}]}'); }
/** * 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_adds_a_violation_if_axis_attributes_are_invalid($context, GroupInterface $variantGroup, GroupType $type, VariantGroupAxis $constraint, ConstraintViolationBuilderInterface $violation, AttributeInterface $invalidAxis) { $variantGroup->getId()->willReturn(12); $variantGroup->getType()->willReturn($type); $variantGroup->getCode()->willReturn('tshirt'); $type->isVariant()->willReturn(true); $variantGroup->getAxisAttributes()->willReturn([$invalidAxis]); $invalidAxis->getAttributeType()->willReturn(AttributeTypes::TEXT); $invalidAxis->getCode()->willReturn('name'); $violationData = ['%group%' => 'tshirt', '%attribute%' => 'name']; $context->buildViolation($constraint->invalidAxisMessage, $violationData)->shouldBeCalled()->willReturn($violation); $this->validate($variantGroup, $constraint); }
function it_adds_a_violation_when_validates_a_product_with_missing_value_for_an_axe_of_its_variant_group($context, ProductInterface $product, GroupInterface $tShirtVariantGroup, AttributeInterface $sizeAttribute, AttributeInterface $colorAttribute, ProductValueInterface $sizeValue, ProductValueInterface $identifierValue, HasVariantAxes $constraint, ConstraintViolationBuilderInterface $violation) { $tShirtVariantGroup->getCode()->willReturn('tshirt'); $tShirtVariantGroup->getAxisAttributes()->willReturn([$sizeAttribute, $colorAttribute]); $sizeAttribute->getCode()->willReturn('size'); $colorAttribute->getCode()->willReturn('color'); $product->getIdentifier()->willReturn($identifierValue); $product->getVariantGroup()->willReturn($tShirtVariantGroup); $product->getValue('size')->willReturn($sizeValue); $product->getValue('color')->willReturn(null); $sizeValue->getData()->willReturn('XL'); $context->buildViolation('The product "%product%" is in the variant group "%variant%" but it misses the following axes: %axes%.', ['%product%' => $identifierValue, '%variant%' => 'tshirt', '%axes%' => 'color'])->shouldBeCalled()->willReturn($violation); $this->validate($product, $constraint); }
function it_normalizes_a_product_associations_in_standard_format_only(ProductInterface $product, AssociationInterface $association1, AssociationInterface $association2, AssociationTypeInterface $associationType1, AssociationTypeInterface $associationType2, GroupInterface $group1, ProductInterface $productAssociated) { $group1->getCode()->willReturn('group_code'); $associationType1->getCode()->willReturn('XSELL'); $association1->getAssociationType()->willReturn($associationType1); $association1->getGroups()->willReturn([$group1]); $association1->getProducts()->willReturn([]); $productAssociated->getReference()->willReturn('product_code'); $associationType2->getCode()->willReturn('PACK'); $association2->getAssociationType()->willReturn($associationType2); $association2->getGroups()->willReturn([]); $association2->getProducts()->willReturn([$productAssociated]); $product->getAssociations()->willReturn([$association1, $association2]); $this->normalize($product, 'standard')->shouldReturn(['PACK' => ['groups' => [], 'products' => ['product_code']], 'XSELL' => ['groups' => ['group_code'], 'products' => []]]); }
/** * {@inheritdoc} * * @param GroupInterface $object */ public function normalize($object, $format = null, array $context = []) { $results = ['code' => $object->getCode(), 'type' => $object->getType()->getCode()]; $axisAttributes = $this->normalizeAxisAttributes($object); if (!empty($axisAttributes)) { $results += ['axis' => $axisAttributes]; } $results += $this->transNormalizer->normalize($object, $format, $context); if (isset($context['versioning']) && true === $context['versioning']) { $context['with_variant_group_values'] = true; } if (isset($context['with_variant_group_values']) && true === $context['with_variant_group_values']) { $results['values'] = $this->normalizeVariantGroupValues($object, $format, $context); } return $results; }
function it_saves_a_variant_group_and_copies_values_to_products($optionsResolver, $objectManager, $templateApplier, $eventDispatcher, GroupInterface $group, GroupType $type, ProductInterface $product, ProductTemplateInterface $template, ArrayCollection $products) { $optionsResolver->resolveSaveOptions(['copy_values_to_products' => true])->willReturn(['flush' => true, 'copy_values_to_products' => true, 'add_products' => [], 'remove_products' => []]); $group->getType()->willReturn($type); $group->getCode()->willReturn('my_code'); $objectManager->persist($group)->shouldBeCalled(); $objectManager->flush()->shouldBeCalled(); $type->isVariant()->willReturn(true); $group->getProductTemplate()->willReturn($template); $group->getProducts()->willReturn($products); $products->toArray()->willReturn([$product]); $templateApplier->apply($template, [$product])->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::PRE_SAVE, Argument::cetera())->shouldBeCalled(); $eventDispatcher->dispatch(StorageEvents::POST_SAVE, Argument::cetera())->shouldBeCalled(); $this->save($group, ['copy_values_to_products' => true]); }
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']); }
function it_normalizes_the_associations_of_the_product(ProductInterface $product, AssociationInterface $association1, AssociationInterface $association2, AssociationTypeInterface $type1, AssociationTypeInterface $type2, ProductInterface $productAssociated1, ProductInterface $productAssociated2, ProductInterface $productAssociated3, GroupInterface $groupAssociated1, GroupInterface $groupAssociated2) { $type1->getCode()->willReturn('wahou the type'); $type2->getCode()->willReturn('such a type'); $groupAssociated1->getCode()->willReturn('group 1'); $groupAssociated2->getCode()->willReturn('group 2'); $productAssociated1->getReference()->willReturn('product 1'); $productAssociated2->getReference()->willReturn('product 2'); $productAssociated3->getReference()->willReturn('product 3'); $association1->getAssociationType()->willReturn($type1); $association2->getAssociationType()->willReturn($type2); $association1->getGroups()->willReturn([$groupAssociated1]); $association2->getGroups()->willReturn([$groupAssociated1, $groupAssociated2]); $association1->getProducts()->willReturn([]); $association2->getProducts()->willReturn([$productAssociated1, $productAssociated2, $productAssociated3]); $product->getAssociations()->willReturn([$association1, $association2]); $this->normalize($product, 'json')->shouldReturn(['such a type' => ['groups' => ['group 1', 'group 2'], 'products' => ['product 1', 'product 2', 'product 3']], 'wahou the type' => ['groups' => ['group 1'], 'products' => []]]); }
function it_normalizes_product_with_associations($filter, ProductInterface $product, AttributeInterface $skuAttribute, ProductValueInterface $sku, Association $myCrossSell, AssociationTypeInterface $crossSell, Association $myUpSell, AssociationTypeInterface $upSell, GroupInterface $associatedGroup1, GroupInterface $associatedGroup2, ProductInterface $associatedProduct1, ProductInterface $associatedProduct2, ProductValueInterface $skuAssocProduct1, ProductValueInterface $skuAssocProduct2, Collection $values, FamilyInterface $family, $serializer) { $family->getCode()->willReturn('shoes'); $skuAttribute->getCode()->willReturn('sku'); $skuAttribute->getAttributeType()->willReturn('pim_catalog_identifier'); $skuAttribute->isLocalizable()->willReturn(false); $skuAttribute->isScopable()->willReturn(false); $sku->getAttribute()->willReturn($skuAttribute); $sku->getData()->willReturn('sku-001'); $crossSell->getCode()->willReturn('cross_sell'); $myCrossSell->getAssociationType()->willReturn($crossSell); $myCrossSell->getGroups()->willReturn([]); $myCrossSell->getProducts()->willReturn([]); $upSell->getCode()->willReturn('up_sell'); $myUpSell->getAssociationType()->willReturn($upSell); $associatedGroup1->getCode()->willReturn('associated_group1'); $associatedGroup2->getCode()->willReturn('associated_group2'); $myUpSell->getGroups()->willReturn([$associatedGroup1, $associatedGroup2]); $skuAssocProduct1->getAttribute()->willReturn($skuAttribute); $skuAssocProduct2->getAttribute()->willReturn($skuAttribute); $skuAssocProduct1->__toString()->willReturn('sku_assoc_product1'); $skuAssocProduct2->__toString()->willReturn('sku_assoc_product2'); $associatedProduct1->getIdentifier()->willReturn($skuAssocProduct1); $associatedProduct2->getIdentifier()->willReturn($skuAssocProduct2); $myUpSell->getProducts()->willReturn([$associatedProduct1, $associatedProduct2]); $product->getIdentifier()->willReturn($sku); $product->getFamily()->willReturn($family); $product->isEnabled()->willReturn(true); $product->getGroupCodes()->willReturn(['group1,group2', 'variant_group_1']); $product->getCategoryCodes()->willReturn(['nice shoes', 'converse']); $product->getAssociations()->willReturn([$myCrossSell, $myUpSell]); $product->getValues()->willReturn($values); $filter->filterCollection($values, 'pim.transform.product_value.flat', Argument::cetera())->willReturn([$sku]); $serializer->normalize($sku, 'flat', Argument::any())->willReturn(['sku' => 'sku-001']); $this->normalize($product, 'flat', [])->shouldReturn(['sku' => 'sku-001', 'family' => 'shoes', 'groups' => 'group1,group2,variant_group_1', 'categories' => 'nice shoes,converse', 'cross_sell-groups' => '', 'cross_sell-products' => '', 'up_sell-groups' => 'associated_group1,associated_group2', 'up_sell-products' => 'sku_assoc_product1,sku_assoc_product2', 'enabled' => 1]); }
/** * Returns the attribute codes for a group * * @param GroupInterface $group * * @return array */ protected function getGroupAttributeCodes(GroupInterface $group) { $code = $group->getCode(); if (!isset($this->groupAttributeCodes[$code])) { $this->groupAttributeCodes[$code] = $this->getAttributeCodes($group); } return $this->groupAttributeCodes[$code]; }
/** * 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_normalizes_group($normalizer, GroupInterface $group) { $group->getCode()->willReturn('mongo'); $normalizer->normalize($group, 'mongodb_json', [])->willReturn(['label' => 'translations']); $this->normalize($group, 'mongodb_json', [])->shouldReturn(['code' => 'mongo', 'label' => 'translations']); }
/** * @param GroupInterface $group * * @Given /^I should be on the ("([^"]*)" variant group) page$/ */ public function iShouldBeOnTheVariantGroupPage(GroupInterface $group) { $expectedAddress = $this->getPage('VariantGroup edit')->getUrl(['code' => $group->getCode()]); $this->getNavigationContext()->assertAddress($expectedAddress); }
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+']); }
/** * @param GroupInterface $group * @param string $type * * @throws \InvalidArgumentException */ protected function setType(GroupInterface $group, $type) { $groupType = $this->groupTypeRepository->findOneByIdentifier($type); if (null === $groupType) { throw new \InvalidArgumentException(sprintf('Type "%s" does not exist', $type)); } if ($groupType->isVariant()) { throw new \InvalidArgumentException(sprintf('Cannot process variant group "%s", only groups are accepted', $group->getCode())); } $group->setType($groupType); }
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(); }