function it_gets_association_status_for_a_given_product($magentoSoapClient, ProductInterface $product) { $magentoSoapClient->call('catalog_product_link.list', ['up_sell', 'sku-012', 'sku'])->willReturn('up_sell'); $magentoSoapClient->call('catalog_product_link.list', ['cross_sell', 'sku-012', 'sku'])->willReturn('cross_sell'); $magentoSoapClient->call('catalog_product_link.list', ['related', 'sku-012', 'sku'])->willReturn('related'); $magentoSoapClient->call('catalog_product_link.list', ['grouped', 'sku-012', 'sku'])->willReturn('grouped'); $product->getIdentifier()->willReturn('sku-012'); $this->getAssociationsStatus($product)->shouldReturn(['up_sell' => 'up_sell', 'cross_sell' => 'cross_sell', 'related' => 'related', 'grouped' => 'grouped']); }
function it_generates_association_calls_for_given_products($webservice, ProductInterface $product, ProductInterface $associatedProduct, Association $association, AssociationType $associationType) { $webservice->getAssociationsStatus($product)->willReturn(['up_sell' => [], 'cross_sell' => [['sku' => 'sku-011']], 'related' => []]); $product->getIdentifier()->willReturn('sku-012'); $product->getAssociations()->willReturn([$association]); $association->getAssociationType()->willReturn($associationType); $association->getProducts()->willReturn([$associatedProduct]); $associatedProduct->getIdentifier()->willReturn('sku-011'); $associationType->getCode()->willReturn('UPSELL'); $this->process([$product])->shouldReturn(['remove' => [['type' => 'cross_sell', 'product' => 'sku-012', 'linkedProduct' => 'sku-011', 'identifierType' => 'sku']], 'create' => [['type' => 'up_sell', 'product' => 'sku-012', 'linkedProduct' => 'sku-011', 'identifierType' => 'sku']]]); }
function it_does_not_validate_products_with_multiple_variant_group($context, $onlyOneVariantGroup, ProductInterface $mug, CustomGroupInterface $mugVariantGroup, CustomGroupInterface $otherGroup, GroupTypeInterface $variantType) { $mug->getGroups()->willReturn([$mugVariantGroup, $otherGroup]); $mugVariantGroup->getType()->willReturn($variantType); $mugVariantGroup->__toString()->willReturn('mug'); $otherGroup->getType()->willReturn($variantType); $otherGroup->__toString()->willReturn('other'); $variantType->isVariant()->willReturn(true); $mug->getIdentifier()->willReturn('mug'); $context->addViolation($onlyOneVariantGroup->message, ['%groups%' => 'mug, other', '%product%' => 'mug'])->shouldBeCalled(); $this->validate($mug, $onlyOneVariantGroup); }
function it_throws_an_exception_if_no_file_is_found(ChannelInterface $channel, ProductInterface $product, ChannelManager $channelManager, Serializer $serializer, ProductValueInterface $productValue, AttributeInterface $attribute) { $product->getValues()->willReturn([$productValue]); $productValue->getAttribute()->willReturn($attribute); $attribute->getAttributeType()->willReturn('pim_catalog_image'); $product->getIdentifier()->willReturn($productValue); $productValue->getData()->willReturn('data'); $this->setChannel('foobar'); $channelManager->getChannelByCode('foobar')->willReturn($channel); $serializer->normalize(['data'], 'flat', ['field_name' => 'media', 'prepare_copy' => true])->willThrow('Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException'); $this->shouldThrow('Akeneo\\Bundle\\BatchBundle\\Item\\InvalidItemException')->during('process', [$product]); }
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_does_not_generate_association_calls_for_given_products_if_associated_product_is_not_complete_nor_enable($webservice, ProductInterface $product, ProductInterface $associatedProduct, Association $association, AssociationType $associationType, Completeness $completeness) { $webservice->getAssociationsStatus($product)->willReturn(['up_sell' => [], 'cross_sell' => [['sku' => 'sku-011']], 'related' => []]); $product->getIdentifier()->willReturn('sku-012'); $product->getAssociations()->willReturn([$association]); $association->getAssociationType()->willReturn($associationType); $association->getProducts()->willReturn([$associatedProduct]); $associatedProduct->getIdentifier()->willReturn('sku-011'); $associatedProduct->isEnabled()->willReturn(false); $associatedProduct->getCompletenesses()->willReturn([$completeness]); $completeness->getRatio()->willReturn(50); $associationType->getCode()->willReturn('UPSELL'); $this->process([$product])->shouldReturn(['remove' => [['type' => 'cross_sell', 'product' => 'sku-012', 'linkedProduct' => 'sku-011', 'identifierType' => 'sku']], 'create' => []]); }
function it_generates_warning_message_if_there_is_products_in_a_variant_group($groupRepository, $productMassActionRepo, CustomGroupInterface $shoes, ProductInterface $product1, ProductInterface $product2) { $product1->getVariantGroup()->willReturn(null); $product1->getIdentifier()->shouldNotBeCalled(); $product2->getVariantGroup()->willReturn($shoes); $product2->getIdentifier()->shouldBeCalled()->willReturn('shirt_000'); $this->setObjectsToMassEdit([$product1, $product2]); $product1->getId()->willReturn(1); $product2->getId()->willReturn(2); $productMassActionRepo->findCommonAttributeIds(Argument::type('array'))->willReturn([]); $groupRepository->getVariantGroupsByAttributeIds([])->willReturn([$shoes]); $shoes->getId()->willReturn(42); $groupRepository->getVariantGroupsByIds([42], false)->willReturn([]); $groupRepository->countVariantGroups()->willReturn(1); $this->getFormOptions(); $this->getWarningMessages()->shouldReturn([['key' => 'pim_enrich.mass_edit_action.add-to-variant-group.already_in_variant_group_or_not_valid', 'options' => ['%products%' => 'shirt_000']]]); }
function it_updates_a_variant_group($attributeRepository, $groupTypeRepository, $productBuilder, GroupInterface $variantGroup, AttributeInterface $attribute, GroupTypeInterface $type, GroupTranslation $translatable, ProductInterface $product, ProductValueInterface $productValue, 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(); $product->getValues()->willReturn(new ArrayCollection([$productValue])); $product->getIdentifier()->willReturn($productValue); $productBuilder->createProduct()->willReturn($product); $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, []); }
function it_returns_flat_data_with_media($channelManager, Filesystem $filesystem, ChannelInterface $channel, ProductInterface $product, FileInterface $media1, FileInterface $media2, ProductValueInterface $value1, ProductValueInterface $value2, AttributeInterface $attribute, ProductValueInterface $identifierValue, AttributeInterface $identifierAttribute, $serializer) { $media1->getKey()->willReturn('key/to/media1.jpg'); $media2->getKey()->willReturn('key/to/media2.jpg'); $value1->getAttribute()->willReturn($attribute); $value1->getMedia()->willReturn($media1); $value2->getAttribute()->willReturn($attribute); $value2->getMedia()->willReturn($media2); $attribute->getAttributeType()->willReturn('pim_catalog_image'); $product->getValues()->willReturn([$value1, $value2, $identifierValue]); $identifierValue->getAttribute()->willReturn($identifierAttribute); $identifierAttribute->getAttributeType()->willReturn('pim_catalog_identifier'); $product->getIdentifier()->willReturn($identifierValue); $identifierValue->getData()->willReturn('data'); $filesystem->has('key/to/media1.jpg')->willReturn(true); $filesystem->has('key/to/media2.jpg')->willReturn(true); $serializer->normalize($media1, 'flat', ['field_name' => 'media', 'prepare_copy' => true, 'value' => $value1])->willReturn(['normalized_media1']); $serializer->normalize($media2, 'flat', ['field_name' => 'media', 'prepare_copy' => true, 'value' => $value2])->willReturn(['normalized_media2']); $serializer->normalize($product, 'flat', ['scopeCode' => 'foobar', 'localeCodes' => ''])->willReturn(['normalized_product']); $channelManager->getChannelByCode('foobar')->willReturn($channel); $this->setChannel('foobar'); $this->process($product)->shouldReturn(['media' => [['normalized_media1'], ['normalized_media2']], 'product' => ['normalized_product']]); }
/** * @param ProductInterface $product * @param ProductValueInterface $value * * @return string */ public function generateFilenamePrefix(ProductInterface $product, ProductValueInterface $value) { return sprintf('%s-%s-%s-%s-%s-%s', $product->getId(), Urlizer::urlize($product->getIdentifier(), '_'), $value->getAttribute()->getCode(), $value->getLocale(), $value->getScope(), time()); }
/** * Get remove association calls for a given product. * * @param ProductInterface $product * @param array $associationStatus * * @return array */ protected function getRemoveCallsForProduct(ProductInterface $product, array $associationStatus) { $removeAssociationCalls = []; foreach ($associationStatus as $associationType => $associatedProducts) { foreach ($associatedProducts as $associatedProduct) { $removeAssociationCalls[] = ['type' => $associationType, 'product' => (string) $product->getIdentifier(), 'linkedProduct' => (string) $associatedProduct['sku'], 'identifierType' => 'sku']; } } return $removeAssociationCalls; }
function it_normalizes_product_with_a_multiselect_value($filter, $serializer, ProductInterface $product, AbstractAttribute $skuAttribute, AbstractAttribute $colorsAttribute, AbstractProductValue $sku, AbstractProductValue $colors, AttributeOption $red, AttributeOption $blue, Collection $values, Family $family) { $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'); $colorsAttribute->getCode()->willReturn('colors'); $colorsAttribute->isLocalizable()->willReturn(false); $colorsAttribute->isScopable()->willReturn(false); $colors->getAttribute()->willReturn($colorsAttribute); $colors->getData()->willReturn([$red, $blue]); $product->getIdentifier()->willReturn($sku); $product->getFamily()->willReturn($family); $product->isEnabled()->willReturn(true); $product->getGroupCodes()->willReturn(''); $product->getCategoryCodes()->willReturn(''); $product->getAssociations()->willReturn([]); $product->getValues()->willReturn($values); $filter->filter($values, ['identifier' => $sku, 'scopeCode' => null, 'localeCodes' => []])->willReturn([$sku, $colors]); $serializer->normalize($sku, 'flat', Argument::any())->willReturn(['sku' => 'sku-001']); $serializer->normalize($colors, 'flat', Argument::any())->willReturn(['colors' => 'red, blue']); $this->normalize($product, 'flat', [])->shouldReturn(['sku' => 'sku-001', 'family' => 'shoes', 'groups' => '', 'categories' => '', 'colors' => 'red, blue', 'enabled' => 1]); }
/** * Prepare query criteria for variant group * * @param GroupInterface $variantGroup * @param ProductInterface $product * @param Constraint $constraint * * @return array */ protected function prepareQueryCriterias(GroupInterface $variantGroup, ProductInterface $product, Constraint $constraint) { $criteria = []; foreach ($variantGroup->getAxisAttributes() as $attribute) { $value = $product->getValue($attribute->getCode()); // we don't add criteria when option is null, as this check is performed by HasVariantAxesValidator if (null === $value || null === $value->getOption() && !$attribute->isBackendTypeReferenceData()) { $this->addEmptyAxisViolation($constraint, $variantGroup->getLabel(), $product->getIdentifier()->getVarchar(), $attribute->getCode()); continue; } $current = ['attribute' => $attribute]; if (null !== $value->getOption()) { $current['option'] = $value->getOption(); } elseif ($attribute->isBackendTypeReferenceData()) { $current['referenceData'] = ['name' => $attribute->getReferenceDataName(), 'data' => $value->getData()]; } $criteria[] = $current; } return $criteria; }
/** * Test if the product attribute set changed. * * @param ProductInterface $product * @param array $prestashopProducts * * @return bool */ protected function attributeSetChanged(ProductInterface $product, $prestashopProducts) { foreach ($prestashopProducts as $prestashopProduct) { if ($prestashopProduct['sku'] == $product->getIdentifier()->getData() && $prestashopProduct['set'] != $this->getAttributeSetId($product->getFamily()->getCode(), $product)) { return true; } } return false; }
/** * {@inheritdoc} */ public function getReference() { return $this->owner ? $this->owner->getIdentifier() . '.' . $this->associationType->getCode() : null; }
/** * Get associations status. * * @param ProductInterface $product * * @return array */ public function getAssociationsStatus(ProductInterface $product) { $associationStatus = []; $sku = (string) $product->getIdentifier(); $associationStatus['up_sell'] = $this->client->call(self::SOAP_ACTION_LINK_LIST, ['up_sell', $sku, 'sku']); $associationStatus['cross_sell'] = $this->client->call(self::SOAP_ACTION_LINK_LIST, ['cross_sell', $sku, 'sku']); $associationStatus['related'] = $this->client->call(self::SOAP_ACTION_LINK_LIST, ['related', $sku, 'sku']); $associationStatus['grouped'] = $this->client->call(self::SOAP_ACTION_LINK_LIST, ['grouped', $sku, 'sku']); return $associationStatus; }
/** * Get filtered values * * @param ProductInterface $product * @param array $context * * @return ProductValueInterface[] */ protected function getFilteredValues(ProductInterface $product, array $context = []) { $values = $product->getValues(); $context = ['identifier' => $product->getIdentifier(), 'scopeCode' => $context['scopeCode'], 'localeCodes' => $context['localeCodes']]; foreach ($this->valuesFilters as $filter) { $values = $filter->filter($values, $context); } return $values; }
/** * Get values array for a given product * * @param ProductInterface $product The given product * @param array $magentoAttributes Attribute list from Magento * @param array $magentoAttributesOptions Attribute options list from Magento * @param string $localeCode The locale to apply * @param string $scopeCode The akeneo scope * @param MappingCollection $categoryMapping Root category mapping * @param MappingCollection $attributeCodeMapping Attribute mapping * @param boolean $onlyLocalized If true, only get translatable attributes * * @return array Computed data */ public function getValues(ProductInterface $product, $magentoAttributes, $magentoAttributesOptions, $localeCode, $scopeCode, MappingCollection $categoryMapping, MappingCollection $attributeCodeMapping, $onlyLocalized) { $normalizedValues = []; $context = ['identifier' => $product->getIdentifier(), 'scopeCode' => $scopeCode, 'localeCode' => $localeCode, 'onlyLocalized' => $onlyLocalized, 'magentoAttributes' => $magentoAttributes, 'magentoAttributesOptions' => $magentoAttributesOptions, 'attributeCodeMapping' => $attributeCodeMapping, 'currencyCode' => $this->currencyCode]; foreach ($product->getValues() as $value) { $normalizedValue = $this->productValueNormalizer->normalize($value, 'MagentoArray', $context); if ($normalizedValue !== null) { $normalizedValues = array_merge($normalizedValues, $normalizedValue); } } $normalizedValues = array_merge($normalizedValues, $this->getCustomValue($product, $attributeCodeMapping, ['categoryMapping' => $categoryMapping, 'scopeCode' => $scopeCode])); ksort($normalizedValues); return $normalizedValues; }
function it_throws_an_exception_if_something_goes_wrong_with_media_normalization($serializer, ProductInterface $product, ProductMediaInterface $media, ProductValueInterface $value, ProductValueInterface $value2, AttributeInterface $attribute) { $product->getValues()->willReturn([$value]); $product->getIdentifier()->willReturn($value2); $value->getAttribute()->willReturn($attribute); $value->getData()->willReturn($media); $value2->getData()->willReturn(23); $attribute->getAttributeType()->willReturn('pim_catalog_image'); $serializer->normalize([$media], Argument::cetera())->willThrow(new FileNotFoundException('upload/path/img.jpg')); $this->shouldThrow(new InvalidItemException('The file "upload/path/img.jpg" does not exist', ['item' => 23, 'uploadDirectory' => 'upload/path/']))->duringProcess($product); }
function it_generates_filename_prefix(ProductInterface $product, ProductValueInterface $value, ProductValueInterface $identifier, AttributeInterface $attribute) { $identifier->getData()->shouldBeCalled(); $product->getIdentifier()->willReturn($identifier); $value->getAttribute()->willReturn($attribute); $attribute->getCode()->shouldBeCalled(); $value->getLocale()->shouldBeCalled(); $value->getScope()->shouldBeCalled(); $this->generateFilenamePrefix($product, $value); }
/** * Prepare query criteria for variant group * * @param GroupInterface $variantGroup * @param ProductInterface $product * @param Constraint $constraint * * @return array */ protected function prepareQueryCriterias(GroupInterface $variantGroup, ProductInterface $product, Constraint $constraint) { $criteria = array(); foreach ($variantGroup->getAxisAttributes() as $attribute) { $value = $product->getValue($attribute->getCode()); // we don't add criteria when option is null, as this check is performed by HasVariantAxesValidator if (null !== $value && null !== $value->getOption()) { $criteria[] = ['attribute' => $attribute, 'option' => $value->getOption()]; } else { $this->addEmptyAxisViolation($constraint, $variantGroup->getLabel(), $product->getIdentifier()->getVarchar(), $attribute->getCode()); } } return $criteria; }
/** * Generate url key from product name and identifier. * The identifier is included to make sure the url_key is unique, as required in Prestashop. * * If name is localized, the default locale is used to get the value. * * @param ProductInterface $product * @param MappingCollection $attributeCodeMapping * @param string $localeCode * @param string $scopeCode * @param boolean $skuFirst * * @return string */ protected function generateUrlKey(ProductInterface $product, MappingCollection $attributeCodeMapping, $localeCode, $scopeCode, $skuFirst = false) { $identifier = $product->getIdentifier(); $nameAttribute = $attributeCodeMapping->getSource(self::NAME); $name = $product->getValue($nameAttribute, $localeCode, $scopeCode); if (false === $skuFirst) { $url = Urlizer::urlize($name . '-' . $identifier); } else { $url = Urlizer::urlize($identifier . '-' . $name); } return $url; }
function it_normalizes_product_with_price($filter, ProductInterface $product, AttributeInterface $priceAttribute, ProductValueInterface $price, Collection $prices, Collection $values, ProductPriceInterface $productPrice, FamilyInterface $family, SerializerInterface $serializer) { $family->getCode()->willReturn('shoes'); $priceAttribute->getCode()->willReturn('price'); $priceAttribute->getAttributeType()->willReturn('pim_catalog_price_collection'); $priceAttribute->isLocalizable()->willReturn(false); $priceAttribute->isScopable()->willReturn(false); $price->getAttribute()->willReturn($priceAttribute); $price->getData()->willReturn(null); $productPrice->getData()->willReturn("356.00"); $productPrice->getCurrency()->willReturn("EUR"); $prices->add($productPrice); $price->getPrices()->willReturn($prices); $product->getIdentifier()->willReturn($price); $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([]); $values->add($price); $product->getValues()->willReturn($values); $filter->filterCollection($values, 'pim.transform.product_value.flat', Argument::cetera())->willReturn([$price]); $serializer->normalize($price, 'flat', Argument::any())->willReturn(['price-EUR' => '356.00']); $this->normalize($product, 'flat', ['price-EUR' => ''])->shouldReturn(['price-EUR' => '356.00', 'family' => 'shoes', 'groups' => 'group1, group2, variant_group_1', 'categories' => 'nice shoes, converse', 'enabled' => 1]); }
/** * Serialize a single product * * @param ProductInterface $product * @param string[] $channels * @param string[] $locales * * @return array */ protected function serializeProduct(ProductInterface $product, $channels, $locales) { $url = $this->generateUrl('oro_api_get_product', array('identifier' => $product->getIdentifier()->getData()), true); $handler = $this->container->get('pim_webservice.handler.rest.product'); $data = $handler->get($product, $channels, $locales, $url); return $data; }