/**
  * {@inheritdoc}
  */
 public function prepareValueFormData(ProductValueInterface $value)
 {
     if (!is_null($value->getData())) {
         return $value->getData();
     }
     return $this->metricFactory->createMetric($value->getAttribute()->getMetricFamily());
 }
 /**
  * {@inheritdoc}
  */
 public function prepareValueFormData(ProductValueInterface $value)
 {
     if ($value->getData() && $value->getData()->isEmpty()) {
         return $value->getAttribute()->getDefaultValue();
     }
     $iterator = $value->getData()->getIterator();
     if (true === $value->getAttribute()->getProperty('autoOptionSorting')) {
         $iterator->uasort('strcasecmp');
     } else {
         $iterator->uasort(function ($first, $second) {
             return $first->getSortOrder() < $second->getSortOrder() ? -1 : 1;
         });
     }
     return new ArrayCollection(iterator_to_array($iterator));
 }
 function let(AttributeConstraintGuesser $guesser, ProductValueInterface $value, AttributeInterface $color, AttributeOptionInterface $red)
 {
     $value->getAttribute()->willReturn($color);
     $value->getData()->willReturn(new ArrayCollection([$red]));
     $color->getBackendType()->willReturn(AbstractAttributeType::BACKEND_TYPE_OPTIONS);
     $this->beConstructedWith(AbstractAttributeType::BACKEND_TYPE_OPTIONS, 'pim_ajax_entity', $guesser);
 }
 function it_converts_metric_values_given_the_configured_base_unit_in_the_channel($converter, ProductValueInterface $weightValue, ProductValueInterface $surfaceValue, ProductValueInterface $nameValue, AttributeInterface $weight, AttributeInterface $surface, AttributeInterface $name, MetricInterface $weightMetric, MetricInterface $surfaceMetric, ProductInterface $product, ChannelInterface $channel)
 {
     $weightValue->getAttribute()->willReturn($weight);
     $weightValue->getData()->willReturn($weightMetric);
     $weight->getCode()->willReturn('weight');
     $weightMetric->getFamily()->willReturn('Weight');
     $weightMetric->getUnit()->willReturn('KILOGRAM');
     $weightMetric->getData()->willReturn(1);
     $surfaceValue->getAttribute()->willReturn($surface);
     $surfaceValue->getData()->willReturn($surfaceMetric);
     $surface->getCode()->willReturn('surface');
     $surfaceMetric->getFamily()->willReturn('Surface');
     $surfaceMetric->getUnit()->willReturn('METER_SQUARE');
     $surfaceMetric->getData()->willReturn(10);
     $nameValue->getAttribute()->willReturn($name);
     $nameValue->getData()->willReturn('foobar');
     $product->getValues()->willReturn(array($weightValue, $surfaceValue, $nameValue));
     $channel->getConversionUnits()->willReturn(array('weight' => 'GRAM'));
     $converter->setFamily('Weight')->shouldBeCalled();
     $converter->convert('KILOGRAM', 'GRAM', 1)->willReturn(0.001);
     $converter->setFamily('Surface')->shouldNotBeCalled();
     $weightMetric->setData(0.001)->shouldBeCalled();
     $weightMetric->setUnit('GRAM')->shouldBeCalled();
     $this->convert($product, $channel);
 }
 function it_copies_simple_select_value_to_a_product_value($builder, $attrValidatorHelper, AttributeInterface $fromAttribute, AttributeInterface $toAttribute, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductInterface $product4, ProductValueInterface $fromProductValue, ProductValueInterface $toProductValue, AttributeOptionInterface $attributeOption)
 {
     $fromLocale = 'fr_FR';
     $toLocale = 'fr_FR';
     $toScope = 'mobile';
     $fromScope = 'mobile';
     $fromAttribute->getCode()->willReturn('fromAttributeCode');
     $toAttribute->getCode()->willReturn('toAttributeCode');
     $attrValidatorHelper->validateLocale(Argument::cetera())->shouldBeCalled();
     $attrValidatorHelper->validateScope(Argument::cetera())->shouldBeCalled();
     $fromProductValue->getData()->willReturn($attributeOption);
     $toProductValue->setOption($attributeOption)->shouldBeCalledTimes(3);
     $product1->getValue('fromAttributeCode', $fromLocale, $fromScope)->willReturn($fromProductValue);
     $product1->getValue('toAttributeCode', $toLocale, $toScope)->willReturn($toProductValue);
     $product2->getValue('fromAttributeCode', $fromLocale, $fromScope)->willReturn(null);
     $product2->getValue('toAttributeCode', $toLocale, $toScope)->willReturn($toProductValue);
     $product3->getValue('fromAttributeCode', $fromLocale, $fromScope)->willReturn($fromProductValue);
     $product3->getValue('toAttributeCode', $toLocale, $toScope)->willReturn(null);
     $product4->getValue('fromAttributeCode', $fromLocale, $fromScope)->willReturn($fromProductValue);
     $product4->getValue('toAttributeCode', $toLocale, $toScope)->willReturn($toProductValue);
     $builder->addProductValue($product3, $toAttribute, $toLocale, $toScope)->shouldBeCalledTimes(1)->willReturn($toProductValue);
     $products = [$product1, $product2, $product3, $product4];
     foreach ($products as $product) {
         $this->copyAttributeData($product, $product, $fromAttribute, $toAttribute, ['from_locale' => $fromLocale, 'to_locale' => $toLocale, 'from_scope' => $fromScope, 'to_scope' => $toScope]);
     }
 }
 function it_adds_violation_with_non_unique_value(ProductManager $productManager, ProductValueInterface $value, ExecutionContextInterface $context, UniqueValue $constraint)
 {
     $value->getData()->willReturn('a content');
     $productManager->valueExists($value)->willReturn(true);
     $context->addViolation($constraint->message)->shouldBeCalled();
     $this->validate("my_value", $constraint)->shouldReturn(null);
 }
 /**
  * {@inheritdoc}
  */
 public function supportsValue(ProductValueInterface $productValue)
 {
     $data = $productValue->getData();
     if (null === $data || '' === $data || [] === $data || $data instanceof \Countable && 0 === count($data)) {
         return true;
     }
     return false;
 }
 public function it_succesfully_checks_complete_attribute(ProductValueInterface $value, ChannelInterface $channel, LocaleInterface $locale, ProductValueCompleteCheckerInterface $completenessChecker, AttributeInterface $attribute)
 {
     $value->getAttribute()->willReturn($attribute);
     $value->getData()->willReturn('foo');
     $this->addProductValueChecker($completenessChecker);
     $completenessChecker->supportsValue($value)->willReturn(true);
     $completenessChecker->isComplete($value, $channel, $locale)->willReturn(true);
     $this->isComplete($value, $channel, $locale)->shouldReturn(true);
 }
 function it_normalizes_product_value_which_is_not_a_number($productValueNormalizer, $localizer, ProductValueInterface $productValue, AttributeInterface $attribute)
 {
     $options = ['decimal_separator' => ','];
     $productValue->getData()->willReturn('shoes');
     $attribute->getAttributeType()->willReturn(AttributeTypes::TEXT);
     $productValue->getAttribute()->willReturn($attribute);
     $productValueNormalizer->normalize($productValue, null, $options)->willReturn(['simple-select' => 'shoes']);
     $localizer->convertDefaultToLocalized('', $options)->shouldNotBeCalled();
     $this->normalize($productValue, null, $options)->shouldReturn(['simple-select' => 'shoes']);
 }
 function it_normalizes_value_with_decimal_support_backend(ProductValueInterface $value, AbstractAttribute $attribute)
 {
     $attribute->getCode()->willReturn('code');
     $attribute->getBackendType()->willReturn('decimal');
     $attribute->isLocalizable()->willReturn(false);
     $attribute->isScopable()->willReturn(false);
     $value->getData()->willReturn('42.42');
     $value->getAttribute()->willReturn($attribute);
     $this->normalize($value, 'mongodb_json', [])->shouldReturn(['code' => 42.42]);
 }
 public function it_succesfully_checks_incomplete_price_collection(ProductValueInterface $value, ChannelInterface $channel, LocaleInterface $locale, ArrayCollection $arrayCollection, CurrencyInterface $currency1, CurrencyInterface $currency2, ProductPriceInterface $price1)
 {
     $channel->getCurrencies()->willReturn($arrayCollection);
     $arrayCollection->toArray()->willReturn([$currency1, $currency2]);
     $currency1->getCode()->willReturn('USD');
     $price1->getCurrency()->willReturn('USD');
     $price1->getData()->willReturn(null);
     $value->getData()->willReturn([$price1]);
     $this->isComplete($value, $channel, $locale)->shouldReturn(false);
 }
 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_normalizes_a_product_value_into_mongodb_document($mongoFactory, $serializer, ProductValueInterface $value, AttributeInterface $attribute, \MongoDBRef $mongoDBRef, \MongoId $mongoId)
 {
     $context = ['_id' => $mongoId, 'collection_name' => 'product'];
     $mongoFactory->createMongoId()->willReturn($mongoId);
     $mongoFactory->createMongoDBRef('product', $mongoId)->willReturn($mongoDBRef);
     $attribute->getId()->willReturn(123);
     $attribute->getBackendType()->willReturn('text');
     $value->getAttribute()->willReturn($attribute);
     $value->getData()->willReturn('my description');
     $value->getLocale()->willReturn(null);
     $value->getScope()->willReturn(null);
     $this->normalize($value, 'mongodb_document', $context)->shouldReturn(['_id' => $mongoId, 'attribute' => 123, 'entity' => $mongoDBRef, 'text' => 'my description']);
 }
 /**
  * {@inheritdoc}
  */
 public function isComplete(ProductValueInterface $productValue, ChannelInterface $channel = null, LocaleInterface $locale = null)
 {
     $expectedCurrencies = array_map(function ($currency) {
         return $currency->getCode();
     }, $channel->getCurrencies()->toArray());
     foreach ($expectedCurrencies as $currency) {
         foreach ($productValue->getData() as $price) {
             if ($price->getCurrency() === $currency && null === $price->getData()) {
                 return false;
             }
         }
     }
     return true;
 }
 function it_does_not_convert_null_metric_values_in_the_channel($converter, ProductValueInterface $weightValue, AttributeInterface $weight, MetricInterface $weightMetric, ProductInterface $product, ChannelInterface $channel)
 {
     $weightValue->getAttribute()->willReturn($weight);
     $weightValue->getData()->willReturn($weightMetric);
     $weight->getCode()->willReturn('weight');
     $weightMetric->getFamily()->willReturn('Weight');
     $weightMetric->getUnit()->willReturn(null);
     $weightMetric->getData()->willReturn(null);
     $product->getValues()->willReturn(array($weightValue));
     $channel->getConversionUnits()->willReturn(array('weight' => 'GRAM'));
     $converter->setFamily('Weight')->shouldNotBeCalled();
     $converter->convert('KILOGRAM', 'GRAM', 1)->shouldNotBeCalled();
     $weightMetric->setData(null)->shouldNotBeCalled();
     $weightMetric->setUnit('GRAM')->shouldNotBeCalled();
     $this->convert($product, $channel);
 }
 /**
  * Validate that prices contain the currencies required by the channel
  *
  * @param ProductValueInterface $value
  * @param Constraint            $constraint
  *
  * @return null
  */
 protected function validatePrices(ProductValueInterface $value, Constraint $constraint)
 {
     $channel = $constraint->getChannel();
     $expectedCurrencies = array_map(function ($currency) {
         return $currency->getCode();
     }, $channel->getCurrencies()->toArray());
     foreach ($expectedCurrencies as $currency) {
         foreach ($value->getData() as $price) {
             if ($price->getCurrency() === $currency) {
                 if ($price->getData() === null) {
                     $this->context->addViolation($constraint->messageComplete);
                 }
             }
         }
     }
 }
 function it_does_not_add_value_if_already_present(ProductValueInterface $notPresent, ProductInterface $product, AttributeInterface $attribute, ProductValueInterface $present, ProductInterface $anotherProduct)
 {
     $notPresent->getProduct()->willReturn($product);
     $notPresent->getData()->willReturn('new-data');
     $notPresent->getAttribute()->willReturn($attribute);
     $notPresent->getLocale()->willReturn(null);
     $notPresent->getScope()->willReturn(null);
     $attribute->getCode()->willReturn('sku');
     $this->addValue($notPresent)->shouldReturn(true);
     $present->getProduct()->willReturn($anotherProduct);
     $present->getData()->willReturn('new-data');
     $present->getAttribute()->willReturn($attribute);
     $present->getLocale()->willReturn(null);
     $present->getScope()->willReturn(null);
     $attribute->getCode()->willReturn('sku');
     $this->addValue($present)->shouldReturn(false);
 }
 function it_returns_flat_data_with_media(ChannelInterface $channel, $channelManager, ProductInterface $product, ProductMediaInterface $media1, ProductMediaInterface $media2, ProductValueInterface $value1, ProductValueInterface $value2, AttributeInterface $attribute, $serializer)
 {
     $media1->getFilename()->willReturn('media_name');
     $media1->getOriginalFilename()->willReturn('media_original_name');
     $media2->getFilename()->willReturn('media_name');
     $media2->getOriginalFilename()->willReturn('media_original_name');
     $value1->getAttribute()->willReturn($attribute);
     $value1->getData()->willReturn($media1);
     $value2->getAttribute()->willReturn($attribute);
     $value2->getData()->willReturn($media2);
     $attribute->getAttributeType()->willReturn('pim_catalog_image');
     $product->getValues()->willReturn([$value1, $value2]);
     $serializer->normalize([$media1, $media2], 'flat', ['field_name' => 'media', 'prepare_copy' => true])->willReturn(['normalized_media1', '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']]);
 }
 function it_converts_metric_data_before_updating(LifecycleEventArgs $args, MetricInterface $metric, MeasureManager $manager, MeasureConverter $converter, DocumentManager $dm, ProductInterface $product, ProductValueInterface $productValue, UnitOfWork $uow, ClassMetadata $metadata)
 {
     $args->getObject()->willReturn($product);
     $product->getValues()->willReturn([$productValue]);
     $productValue->getData()->willReturn($metric);
     $metric->getId()->willReturn(12);
     $args->getObjectManager()->willReturn($dm);
     $dm->getUnitOfWork()->willReturn($uow);
     $uow->recomputeSingleDocumentChangeSet(Argument::type('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'), $metric)->shouldBeCalled();
     $metric->getUnit()->willReturn('cm');
     $metric->getFamily()->willReturn('distance');
     $metric->getData()->willReturn(100);
     $manager->getStandardUnitForFamily('distance')->willReturn('m');
     $converter->setFamily('distance')->shouldBeCalled()->willReturn($converter);
     $converter->convertBaseToStandard('cm', 100)->willReturn(1);
     $metric->setBaseData(1)->shouldBeCalled()->willReturn($metric);
     $metric->setBaseUnit('m')->shouldBeCalled();
     $dm->getClassMetadata(Argument::any())->willReturn($metadata);
     $dm->getUnitOfWork()->willReturn($uow);
     $uow->recomputeSingleDocumentChangeSet($metadata, $metric)->shouldBeCalled();
     $this->preUpdate($args);
 }
 /**
  * Validate metric type and default metric unit
  *
  * @param AttributeInterface|MetricInterface|ProductValueInterface $object
  * @param Constraint                                               $constraint
  */
 public function validate($object, Constraint $constraint)
 {
     if ($object instanceof AttributeInterface) {
         $familyProperty = 'metricFamily';
         $unitProperty = 'defaultMetricUnit';
     } elseif ($object instanceof MetricInterface && null !== $object->getData()) {
         $familyProperty = 'family';
         $unitProperty = 'unit';
     } elseif ($object instanceof ProductValueInterface && null !== $object->getMetric() && (null !== $object->getMetric()->getUnit() || null !== $object->getMetric()->getData())) {
         $object = $object->getMetric();
         $familyProperty = 'family';
         $unitProperty = 'unit';
     } else {
         return;
     }
     $family = $this->propertyAccessor->getValue($object, $familyProperty);
     $unit = $this->propertyAccessor->getValue($object, $unitProperty);
     if (!array_key_exists($family, $this->measures)) {
         $this->context->buildViolation($constraint->familyMessage)->atPath($familyProperty)->addViolation();
     } elseif (!array_key_exists($unit, $this->measures[$family]['units'])) {
         $this->context->buildViolation($constraint->unitMessage)->atPath($unitProperty)->addViolation();
     }
 }
 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]);
 }
 function it_normalizes_a_value_with_ordered_options_with_a_option_collection_data(ProductValueInterface $value, AttributeInterface $multiColorAttribute, SerializerInterface $serializer, AttributeOptionInterface $redOption, AttributeOptionInterface $blueOption, ArrayCollection $collection)
 {
     $collection->toArray()->willReturn([$redOption, $blueOption]);
     $collection->isEmpty()->willReturn(false);
     $value->getData()->willReturn($collection);
     $value->getAttribute()->willReturn($multiColorAttribute);
     $value->getLocale()->willReturn('en_US');
     $multiColorAttribute->getCode()->willReturn('colors');
     $multiColorAttribute->isLocaleSpecific()->willReturn(false);
     $multiColorAttribute->isLocalizable()->willReturn(false);
     $multiColorAttribute->isScopable()->willReturn(false);
     $multiColorAttribute->getBackendType()->willReturn('options');
     $redOption->getSortOrder()->willReturn(10)->shouldBeCalled();
     $blueOption->getSortOrder()->willReturn(11)->shouldBeCalled();
     // phpspec raises this php bug https://bugs.php.net/bug.php?id=50688,
     // warning: usort(): Array was modified by the user comparison function in ProductValueNormalizer.php line 178
     $previousReporting = error_reporting();
     error_reporting(0);
     $serializer->normalize(Argument::type('Doctrine\\Common\\Collections\\ArrayCollection'), 'flat', ['field_name' => 'colors'])->shouldBeCalled()->willReturn(['colors' => 'red, blue']);
     $this->normalize($value, 'flat', [])->shouldReturn(['colors' => 'red, blue']);
     error_reporting($previousReporting);
 }
 /**
  * {@inheritdoc}
  */
 public function valueExists(ProductValueInterface $value)
 {
     $criteria = array('attribute' => $value->getAttribute(), $value->getAttribute()->getBackendType() => $value->getData());
     $result = $this->getEntityManager()->getRepository(get_class($value))->findBy($criteria);
     return 0 !== count($result) && !(1 === count($result) && $value === ($result instanceof \Iterator ? $result->current() : current($result)));
 }
 /**
  * Get the normalized value.
  *
  * @param ProductValueInterface $value
  * @param string                $attributeCode
  * @param array                 $prestashopAttributes
  * @param array                 $prestashopAttributesOptions
  * @param MappingCollection     $attributeMapping
  * @param string                $currencyCode
  *
  * @throws AttributeNotFoundException If the given attribute doesn't exist in Prestashop
  *
  * @return array
  */
 protected function getNormalizedValue(ProductValueInterface $value, $attributeCode, array $prestashopAttributes, array $prestashopAttributesOptions, MappingCollection $attributeMapping, $currencyCode)
 {
     $data = $value->getData();
     $attribute = $value->getAttribute();
     if (!isset($prestashopAttributes[$attributeCode])) {
         throw new AttributeNotFoundException(sprintf('The prestashop attribute %s doesn\'t exist or isn\'t in the requested attributeSet. You should ' . 'create it first or adding it to the corresponding attributeSet', $attributeCode));
     }
     $normalizer = $this->getNormalizer($data);
     $attributeScope = $prestashopAttributes[$attributeCode]['scope'];
     $normalizedValue = $this->normalizeData($data, $normalizer, $attribute, $attributeCode, $attributeScope, $prestashopAttributesOptions, $currencyCode, $attributeMapping);
     return [$attributeCode => $normalizedValue];
 }
 /**
  * @param ProductValueInterface $productValue
  *
  * @return string
  */
 protected function getValueData(ProductValueInterface $productValue)
 {
     $data = $productValue->getData();
     return $data instanceof \DateTime ? $data->format('Y-m-d') : (string) $data;
 }
 function it_normalizes_empty_date($productValueNormalizer, $localizerRegistry, ProductValueInterface $productValue, AttributeInterface $attribute, DateLocalizer $dateLocalizer)
 {
     $options = ['date_format' => 'd/m/Y'];
     $productValue->getData()->willReturn('');
     $attribute->getAttributeType()->willReturn(AttributeTypes::DATE);
     $productValue->getAttribute()->willReturn($attribute);
     $localizerRegistry->getProductValueLocalizer('pim_catalog_date')->willReturn($dateLocalizer);
     $productValueNormalizer->normalize($productValue, null, $options)->willReturn(['data' => '']);
     $dateLocalizer->localize('', $options)->willReturn('');
     $this->normalize($productValue, null, $options)->shouldReturn(['data' => '']);
 }
 function it_cleans_products_with_duplicated_axis($groupRepository, $productRepository, $jobConfigurationRepo, $saver, $paginatorFactory, $pqbFactory, GroupInterface $variantGroup, ProductQueryBuilderInterface $productQueryBuilder, StepExecution $stepExecution, CursorInterface $cursor, JobExecution $jobExecution, PaginatorInterface $paginator1, PaginatorInterface $paginator2, TranslatorInterface $translator, JobConfigurationInterface $jobConfiguration, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductInterface $product4, AttributeInterface $attribute1, ProductValueInterface $productValue1, ProductValueInterface $productValue2, ProductValueInterface $productValue3, ProductValueInterface $productValue4, AttributeOptionInterface $attributeOption1, AttributeOptionInterface $attributeOption2, AttributeOptionInterface $attributeOption3, AttributeOptionInterface $attributeOption4)
 {
     $this->setStepExecution($stepExecution);
     $configuration = ['filters' => [['field' => 'id', 'operator' => 'IN', 'value' => [1, 2, 3, 4], 'context' => []]], 'actions' => ['value' => 'variant_group_code']];
     $groupRepository->findOneByIdentifier('variant_group_code')->willReturn($variantGroup);
     $variantGroup->getId()->willReturn(42);
     $variantGroup->getAxisAttributes()->willReturn([$attribute1]);
     $attributeOption1->getCode()->willReturn('option_code_1');
     $productValue1->getData()->willReturn($attributeOption1);
     $attributeOption2->getCode()->willReturn('option_code_1');
     $productValue2->getData()->willReturn($attributeOption2);
     $attributeOption3->getCode()->willReturn('option_code_3');
     $productValue3->getData()->willReturn($attributeOption3);
     $attributeOption4->getCode()->willReturn('option_code_4');
     $productValue4->getData()->willReturn($attributeOption4);
     $product1->getId()->willReturn(1);
     $product2->getId()->willReturn(2);
     $product3->getId()->willReturn(3);
     $product4->getId()->willReturn(4);
     $attribute1->getCode()->willReturn('code_1');
     $product1->getValue('code_1')->willReturn($productValue1);
     $product2->getValue('code_1')->willReturn($productValue2);
     $product3->getValue('code_1')->willReturn($productValue3);
     $product4->getValue('code_1')->willReturn($productValue4);
     $productRepository->getEligibleProductIdsForVariantGroup(42)->willReturn([1, 2, 3, 4]);
     $stepExecution->getJobExecution()->willReturn($jobExecution);
     $jobConfigurationRepo->findOneBy(['jobExecution' => $jobExecution])->willReturn($jobConfiguration);
     $pqbFactory->create()->willReturn($productQueryBuilder);
     $translator->trans('add_to_variant_group.steps.cleaner.warning.description')->willReturn('Product can\'t be set in the selected variant group: duplicate variation axis values with' . ' another product in selection');
     $productPage = [$product1, $product2, $product3, $product4];
     $excludedProducts = [$product1, $product2];
     $paginatorFactory->createPaginator($cursor)->willReturn($paginator1, $paginator2);
     $paginator1->rewind()->willReturn();
     $paginator1->count()->willReturn(1);
     $paginator1->valid()->willReturn(true, false);
     $paginator1->next()->willReturn();
     $paginator1->current()->willReturn($productPage);
     $paginator2->rewind()->willReturn();
     $paginator2->count()->willReturn(1);
     $paginator2->valid()->willReturn(true, false);
     $paginator2->next()->willReturn();
     $paginator2->current()->willReturn($excludedProducts);
     $stepExecution->incrementSummaryInfo('skipped_products')->shouldBeCalledTimes(2);
     $stepExecution->addWarning('duplicated', 'Product can\'t be set in the selected variant group: duplicate variation axis values with another product' . ' in selection', [], Argument::any())->shouldBeCalledTimes(2);
     $productQueryBuilder->addFilter('id', 'IN', [1, 2, 3, 4], [])->shouldBeCalledTimes(1);
     $productQueryBuilder->addFilter('id', 'IN', [1, 2], ['locale' => null, 'scope' => null])->shouldBeCalledTimes(1);
     $productQueryBuilder->execute()->willReturn($cursor);
     $saver->save($jobConfiguration)->shouldBeCalled();
     $jobConfiguration->setConfiguration(json_encode(['filters' => [['field' => 'id', 'operator' => 'IN', 'value' => [2 => 3, 3 => 4]]], 'actions' => ['value' => 'variant_group_code']]))->shouldBeCalled();
     $this->execute($configuration);
 }
 /**
  * {@inheritdoc}
  */
 public function valueExists(ProductValueInterface $value)
 {
     $productQueryBuilder = $this->queryBuilderFactory->create();
     $qb = $productQueryBuilder->getQueryBuilder();
     $productQueryBuilder->addFilter($value->getAttribute()->getCode(), '=', $value->getData());
     $result = $qb->hydrate(false)->getQuery()->execute();
     if (0 === $result->count() || 1 === $result->count() && $value->getEntity()->getId() === (string) $result->getNext()['_id']) {
         return false;
     }
     return true;
 }
 function it_returns_null_when_unknown_backendtype($context, ProductValueComplete $constraint, ProductValueInterface $productValue, AttributeInterface $attribute)
 {
     $constraint->getChannel()->willReturn($this->getChannel());
     $metric = new Metric();
     $productValue->getMetric()->willReturn($metric);
     $productValue->getData()->willReturn('data');
     $attribute->getBackendType()->willReturn('unknown_metric');
     $productValue->getAttribute()->willReturn($attribute);
     $context->buildViolation(Argument::any())->shouldNotBeCalled();
     $this->validate($productValue, $constraint);
 }
 /**
  * Copy attribute price into a price collection attribute
  *
  * @param ProductValueInterface $fromValue
  * @param ProductValueInterface $toValue
  */
 protected function copyOptions(ProductValueInterface $fromValue, ProductValueInterface $toValue)
 {
     foreach ($fromValue->getData() as $price) {
         $this->productBuilder->addPriceForCurrencyWithData($toValue, $price->getCurrency(), $price->getData());
     }
 }