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;
 }