function it_normalizes_attribute_for_versioning($attribute, AttributeOptionInterface $size, AttributeOptionValueInterface $en, AttributeOptionValueInterface $fr)
 {
     $attribute->getLocaleSpecificCodes()->willReturn(['en_US', 'fr_FR']);
     $attribute->isLocalizable()->willReturn(true);
     $attribute->isScopable()->willReturn(true);
     $attribute->getOptions()->willReturn([$size]);
     $size->getCode()->willReturn('size');
     $size->getOptionValues()->willReturn([$en, $fr]);
     $en->getLocale()->willReturn('en_US');
     $en->getValue()->willReturn('big');
     $fr->getLocale()->willReturn('fr_FR');
     $fr->getValue()->willReturn('grand');
     $attribute->getSortOrder()->willReturn(1);
     $attribute->isRequired()->willReturn(false);
     $attribute->getMaxCharacters()->willReturn(null);
     $attribute->getValidationRule()->willReturn(null);
     $attribute->getValidationRegexp()->willReturn(null);
     $attribute->isWysiwygEnabled()->willReturn(false);
     $attribute->getNumberMin()->willReturn(1);
     $attribute->getNumberMax()->willReturn(10);
     $attribute->isDecimalsAllowed()->willReturn(false);
     $attribute->isNegativeAllowed()->willReturn(false);
     $attribute->getDateMin()->willReturn(null);
     $attribute->getDateMax()->willReturn(null);
     $attribute->getMaxFileSize()->willReturn(0);
     $this->normalize($attribute, null, ['versioning' => true])->shouldReturn(['type' => 'Yes/No', 'code' => 'attribute_size', 'group' => 'size', 'unique' => 1, 'useable_as_grid_filter' => 0, 'allowed_extensions' => 'csv,xml,json', 'metric_family' => 'Length', 'default_metric_unit' => 'Centimenter', 'reference_data_name' => 'color', 'available_locales' => ['en_US', 'fr_FR'], 'localizable' => true, 'scope' => 'Channel', 'options' => ['size' => ['en_US' => 'big', 'fr_FR' => 'grand']], 'sort_order' => 1, 'required' => 0, 'max_characters' => '', 'validation_rule' => '', 'validation_regexp' => '', 'wysiwyg_enabled' => '', 'number_min' => '1', 'number_max' => '10', 'decimals_allowed' => '', 'negative_allowed' => '', 'date_min' => '', 'date_max' => '', 'metric_family' => 'Length', 'default_metric_unit' => 'Centimenter', 'max_file_size' => '0']);
 }
 function it_generates_a_query_to_update_product_select_attributes($namingUtility, AttributeOptionInterface $blue, AttributeInterface $color)
 {
     $blue->getAttribute()->willReturn($color);
     $namingUtility->getAttributeNormFields($color)->willReturn(['normalizedData.color-fr_FR', 'normalizedData.color-en_US']);
     $blue->getCode()->willReturn('blue');
     $this->generateQuery($blue, 'code', 'blue', 'bluee')->shouldReturn([[['normalizedData.color-fr_FR' => ['$elemMatch' => ['code' => 'blue']]], ['$set' => ['normalizedData.color-fr_FR.$.code' => 'bluee']], ['multiple' => true]], [['normalizedData.color-en_US' => ['$elemMatch' => ['code' => 'blue']]], ['$set' => ['normalizedData.color-en_US.$.code' => 'bluee']], ['multiple' => true]]]);
 }
 function it_does_violations_if_attribute_type_is_not_allowed($context, AttributeOptionInterface $attributeOption, AttributeInterface $notAllowedAttribute, AttributeTypeForOption $constraint, ConstraintViolationBuilderInterface $violation)
 {
     $attributeOption->getAttribute()->willReturn($notAllowedAttribute);
     $notAllowedAttribute->getAttributeType()->willReturn(AttributeTypes::TEXT);
     $notAllowedAttribute->getCode()->willReturn('attributeCode');
     $violationData = ['%attribute%' => 'attributeCode'];
     $context->buildViolation($constraint->invalidAttributeMessage, $violationData)->shouldBeCalled()->willReturn($violation);
     $this->validate($attributeOption, $constraint);
 }
 function it_normalizes_attribute_option(AttributeOptionInterface $option, AttributeOptionValueInterface $valueUs, AttributeOptionValueInterface $valueFr)
 {
     $option->getId()->willReturn(42);
     $option->getCode()->willReturn('red');
     $valueUs->getLocale()->willReturn('en_US');
     $valueUs->getValue()->willReturn('Red');
     $valueFr->getLocale()->willReturn('fr_FR');
     $valueFr->getValue()->willReturn('Rouge');
     $option->getOptionValues()->willReturn([$valueUs, $valueFr]);
     $this->normalize($option, 'mongodb_json', [])->shouldReturn(['id' => 42, 'code' => 'red', 'optionValues' => ['en_US' => ['value' => 'Red', 'locale' => 'en_US'], 'fr_FR' => ['value' => 'Rouge', 'locale' => 'fr_FR']]]);
 }
 /**
  * Returns an array containing the label values
  *
  * @param AttributeOptionInterface $entity
  * @param array                    $context
  *
  * @return array
  */
 protected function normalizeLabel(AttributeOptionInterface $entity, $context)
 {
     $locales = isset($context['locales']) ? $context['locales'] : [];
     $labels = array_fill_keys($locales, '');
     foreach ($entity->getOptionValues() as $translation) {
         if (empty($locales) || in_array($translation->getLocale(), $locales)) {
             $labels[$translation->getLocale()] = $translation->getValue();
         }
     }
     return ['label' => $labels];
 }
 /**
  * {@inheritdoc}
  */
 protected function normalizeLabel(AttributeOptionInterface $entity, $context)
 {
     $labels = [];
     foreach ($context['locales'] as $locale) {
         $labels[sprintf('label-%s', $locale)] = '';
     }
     foreach ($entity->getOptionValues() as $translation) {
         if (empty($context['locales']) || in_array($translation->getLocale(), $context['locales'])) {
             $labels[sprintf('label-%s', $translation->getLocale())] = $translation->getValue();
         }
     }
     return $labels;
 }
 function it_sets_simpleselect_option_to_a_product_value($builder, $attrOptionRepository, AttributeInterface $attribute, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductValueInterface $productValue, AttributeOptionInterface $attributeOption)
 {
     $locale = 'fr_FR';
     $scope = 'mobile';
     $attribute->getCode()->willReturn('attributeCode');
     $attributeOption->getCode()->willReturn('attributeOptionCode');
     $attrOptionRepository->findOneBy(['code' => 'attributeOptionCode', 'attribute' => $attribute])->shouldBeCalledTimes(1)->willReturn($attributeOption);
     $productValue->setOption($attributeOption)->shouldBeCalled();
     $builder->addProductValue($product2, $attribute, $locale, $scope)->willReturn($productValue);
     $product1->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $product2->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn(null);
     $product3->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $this->setValue([$product1, $product2, $product3], $attribute, 'attributeOptionCode', $locale, $scope);
 }
 function it_sets_attribute_data_simpleselect_option_to_a_product_value($builder, $attrOptionRepository, AttributeInterface $attribute, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductValueInterface $productValue, AttributeOptionInterface $attributeOption)
 {
     $locale = 'fr_FR';
     $scope = 'mobile';
     $attribute->getCode()->willReturn('attributeCode');
     $attributeOption->getCode()->willReturn('red');
     $attrOptionRepository->findOneByIdentifier('attributeCode.red')->shouldBeCalledTimes(3)->willReturn($attributeOption);
     $productValue->setOption($attributeOption)->shouldBeCalled();
     $builder->addProductValue($product2, $attribute, $locale, $scope)->willReturn($productValue);
     $product1->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $product2->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn(null);
     $product3->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $this->setAttributeData($product1, $attribute, 'red', ['locale' => $locale, 'scope' => $scope]);
     $this->setAttributeData($product2, $attribute, 'red', ['locale' => $locale, 'scope' => $scope]);
     $this->setAttributeData($product3, $attribute, 'red', ['locale' => $locale, 'scope' => $scope]);
 }
 function it_adds_attribute_data_on_multiselect_value_to_a_product_value($builder, $attrOptionRepository, AttributeInterface $attribute, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductValueInterface $productValue, AttributeOptionInterface $attributeOption)
 {
     $locale = 'fr_FR';
     $scope = 'mobile';
     $attribute->getCode()->willReturn('attributeCode');
     $attributeOption->getCode()->willReturn('attributeOptionCode');
     $attrOptionRepository->findOneBy(['code' => 'attributeOptionCode', 'attribute' => $attribute])->shouldBeCalledTimes(3)->willReturn($attributeOption);
     $productValue->addOption($attributeOption)->shouldBeCalled();
     $builder->addProductValue($product2, $attribute, $locale, $scope)->willReturn($productValue);
     $product1->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $product2->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn(null);
     $product3->getValue('attributeCode', $locale, $scope)->shouldBeCalled()->willReturn($productValue);
     $this->addAttributeData($product1, $attribute, ['attributeOptionCode'], ['locale' => $locale, 'scope' => $scope]);
     $this->addAttributeData($product2, $attribute, ['attributeOptionCode'], ['locale' => $locale, 'scope' => $scope]);
     $this->addAttributeData($product3, $attribute, ['attributeOptionCode'], ['locale' => $locale, 'scope' => $scope]);
 }
 function it_does_not_update_readonly_fields_on_an_existing_attribute_option(AttributeOptionInterface $attributeOption, AttributeOptionValueInterface $attributeOptionValue)
 {
     $attributeOption->getId()->willReturn(42);
     $attributeOption->getAttribute()->willReturn(null);
     // read only fields
     $attributeOption->setCode('mycode')->shouldNotBeCalled();
     $attributeOption->setAttribute(Argument::any())->shouldNotBeCalled();
     $attributeOption->setSortOrder(12)->shouldBeCalled();
     $attributeOption->setLocale('de_DE')->shouldBeCalled();
     $attributeOption->getTranslation()->willReturn($attributeOptionValue);
     $attributeOptionValue->setLabel('210 x 1219 mm')->shouldBeCalled();
     $this->update($attributeOption, ['code' => 'mycode', 'attribute' => 'myattribute', 'sort_order' => 12, 'labels' => ['de_DE' => '210 x 1219 mm']]);
 }
 function it_throws_an_exception_when_attribute_option_is_not_valid($attributeRepository, $validator, AttributeOptionInterface $attributeOption, AttributeInterface $attribute, AttributeGroupInterface $attributeGroup, AttributeOptionValueInterface $attributeOptionValue)
 {
     $attributeOption->getId()->willReturn(null);
     $attributeOption->getAttribute()->willReturn($attribute);
     $attribute->getGroup()->willReturn($attributeGroup);
     $attributeOption->setCode('mycode')->shouldBeCalled();
     $attributeRepository->findOneByIdentifier('myattribute')->willReturn(null);
     $attributeOption->setAttribute($attribute)->shouldNotBeCalled();
     $attributeOption->setSortOrder(12)->shouldBeCalled();
     $attributeOption->setLocale('de_DE')->shouldBeCalled();
     $attributeOption->getTranslation()->willReturn($attributeOptionValue);
     $attributeOptionValue->setLabel('210 x 1219 mm')->shouldBeCalled();
     $violationList = new ConstraintViolationList();
     $violationList->add(new ConstraintViolation('', '', [], $attributeOption, null, null));
     $validator->validate($attributeOption)->willReturn($violationList);
     $this->shouldThrow('Pim\\Bundle\\CatalogBundle\\Exception\\BusinessValidationException')->during('update', [$attributeOption, ['code' => 'mycode', 'attribute' => 'myattribute', 'sort_order' => 12, 'labels' => ['de_DE' => '210 x 1219 mm']]]);
 }
 function it_provides_all_locales_if_no_list_provided_in_context(AttributeOptionInterface $option, AttributeInterface $attribute, AttributeOptionValueInterface $valueEn, AttributeOptionValueInterface $valueFr, AttributeOptionValueInterface $valueDe)
 {
     $option->getCode()->willReturn('red');
     $option->getAttribute()->willReturn($attribute);
     $option->getSortOrder()->willReturn(1);
     $attribute->getCode()->willReturn('color');
     $option->getOptionValues()->willReturn(['en_US' => $valueEn, 'fr_FR' => $valueFr, 'de_DE' => $valueDe]);
     $valueEn->getLocale()->willReturn('en_US');
     $valueEn->getValue()->willReturn('Red');
     $valueFr->getLocale()->willReturn('fr_FR');
     $valueFr->getValue()->willReturn('Rouge');
     $valueDe->getLocale()->willReturn('de_DE');
     $valueDe->getValue()->willReturn('');
     $this->normalize($option, null, ['locales' => []])->shouldReturn(['attribute' => 'color', 'code' => 'red', 'sort_order' => 1, 'label' => ['en_US' => 'Red', 'fr_FR' => 'Rouge', 'de_DE' => '']]);
 }
 /**
  * @param AttributeOptionInterface $attributeOption
  * @param string                   $field
  * @param mixed                    $data
  *
  * @throws \InvalidArgumentException
  */
 protected function setData(AttributeOptionInterface $attributeOption, $field, $data)
 {
     if ('code' === $field) {
         $attributeOption->setCode($data);
     }
     if ('attribute' === $field) {
         $attribute = $this->findAttribute($data);
         if (null !== $attribute) {
             $attributeOption->setAttribute($attribute);
         } else {
             throw new \InvalidArgumentException(sprintf('Attribute "%s" does not exist', $data));
         }
     }
     if ('labels' === $field) {
         foreach ($data as $localeCode => $label) {
             $attributeOption->setLocale($localeCode);
             $translation = $attributeOption->getTranslation();
             $translation->setLabel($label);
         }
     }
     if ('sort_order' === $field) {
         $attributeOption->setSortOrder($data);
     }
 }
 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 findAllWithAttributeOption(AttributeOptionInterface $option)
 {
     $backendType = $option->getAttribute()->getBackendType();
     $qb = $this->createQueryBuilder('p')->leftJoin('p.values', 'value')->leftJoin(sprintf('value.%s', $backendType), 'option');
     if ('options' === $backendType) {
         $qb->where($qb->expr()->in('option', ':option'));
     } else {
         $qb->where('option=:option');
     }
     return $qb->setParameter('option', $option)->getQuery()->getResult();
 }
 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 addOption(AttributeOptionInterface $option)
 {
     $this->options[] = $option;
     $option->setAttribute($this);
     return $this;
 }
 /**
  * {@inheritdoc}
  */
 public function findAllWithAttributeOption(AttributeOptionInterface $option)
 {
     $id = (int) $option->getId();
     $qb = $this->createQueryBuilder('p');
     if ('options' === $option->getAttribute()->getBackendType()) {
         $qb->field('values.optionIds')->in([$id]);
     } else {
         $qb->field('values.option')->equals($id);
     }
     return $qb->getQuery()->execute()->toArray();
 }
 /**
  * @param AttributeTypeForOption   $constraint
  * @param AttributeOptionInterface $option
  */
 protected function addInvalidAttributeViolation(AttributeTypeForOption $constraint, AttributeOptionInterface $option)
 {
     $this->context->buildViolation($constraint->invalidAttributeMessage, ['%attribute%' => $option->getAttribute()->getCode()])->addViolation();
 }
 /**
  * @param AttributeOptionInterface $attributeOption
  *
  * @throws \InvalidArgumentException
  *
  * @return ConstraintViolationListInterface
  */
 protected function validateAttributeOption(AttributeOptionInterface $attributeOption)
 {
     // TODO: ugly fix to workaround issue with "attribute.group.code: This value should not be blank."
     // in case of existing option, attribute is a proxy, attribute group too, the validated group code is null
     null !== $attributeOption->getAttribute() ? $attributeOption->getAttribute()->getGroup()->getCode() : null;
     return $this->validator->validate($attributeOption);
 }