/**
  * Get the media attributes
  *
  * @return string[]
  */
 public function getMediaAttributes()
 {
     if (null === $this->mediaAttributes) {
         $this->mediaAttributes = $this->attributeRepository->findMediaAttributeCodes();
     }
     return $this->mediaAttributes;
 }
 /**
  * @return array
  */
 public function resolveAttributeColumns()
 {
     if (empty($this->attributesFields)) {
         // TODO: Put a Cursor to avoid a findAll on attributes (╯°□°)╯︵ ┻━┻
         $attributes = $this->attributeRepository->findAll();
         $currencyCodes = $this->currencyRepository->getActivatedCurrencyCodes();
         $values = $this->valuesResolver->resolveEligibleValues($attributes);
         foreach ($values as $value) {
             $field = $this->resolveFlatAttributeName($value['attribute'], $value['locale'], $value['scope']);
             if (AttributeTypes::PRICE_COLLECTION === $value['type']) {
                 $this->attributesFields[] = $field;
                 foreach ($currencyCodes as $currencyCode) {
                     $currencyField = sprintf('%s-%s', $field, $currencyCode);
                     $this->attributesFields[] = $currencyField;
                 }
             } elseif (AttributeTypes::METRIC === $value['type']) {
                 $this->attributesFields[] = $field;
                 $metricField = sprintf('%s-%s', $field, 'unit');
                 $this->attributesFields[] = $metricField;
             } else {
                 $this->attributesFields[] = $field;
             }
         }
     }
     return $this->attributesFields;
 }
 /**
  * {@inheritdoc}
  */
 public function getFilter($code, $operator)
 {
     $attribute = $this->attributeRepository->findOneBy(['code' => FieldFilterHelper::getCode($code)]);
     if (null !== $attribute) {
         return $this->getAttributeFilter($attribute, $operator);
     }
     return $this->getFieldFilter($code, $operator);
 }
 /**
  * Find common attributes
  * Common attributes are:
  *   - not unique (and not identifier)
  *   - without value AND link to family
  *   - with value
  *
  * @param ProductInterface[] $products
  *
  * @return AttributeInterface[]
  */
 public function findCommonAttributes(array $products)
 {
     $productIds = [];
     foreach ($products as $product) {
         $productIds[] = $product->getId();
     }
     $attributeIds = $this->massActionRepository->findCommonAttributeIds($productIds);
     return $this->attributeRepository->findWithGroups(array_unique($attributeIds), ['conditions' => ['unique' => 0]]);
 }
 /**
  * Load the attribute for this filter
  * Required to prepare choice url params and filter configuration
  *
  * @throws \LogicException
  *
  * @return AttributeInterface
  */
 protected function getAttribute()
 {
     $fieldName = $this->get(ProductFilterUtility::DATA_NAME_KEY);
     $attribute = $this->attributeRepository->findOneByCode($fieldName);
     if (!$attribute) {
         throw new \LogicException(sprintf('There is no attribute with code %s.', $fieldName));
     }
     return $attribute;
 }
 /**
  * Don't allow creating an identifier attribute if one already exists
  *
  * @param AttributeInterface $attribute
  * @param Constraint         $constraint
  */
 public function validate($attribute, Constraint $constraint)
 {
     if (AttributeTypes::IDENTIFIER === $attribute->getAttributeType()) {
         $identifier = $this->attributeRepository->getIdentifier();
         if ($identifier && $identifier->getId() !== $attribute->getId()) {
             $this->context->buildViolation($constraint->message)->atPath('attribute_type')->addViolation();
         }
     }
 }
 /**
  * Get a list of available attributes
  *
  * @param string $typeCode
  * @return AttributeInterface[]
  */
 public function getAttributes($typeCode)
 {
     $attributeCodes = $this->repository->getAttributeCodesByType($typeCode);
     $attributeList = [];
     foreach ($attributeCodes as $attributeCode) {
         $attributeList[] = $this->repository->findOneByIdentifier($attributeCode);
     }
     return $attributeList;
 }
 /**
  * Get fields for products
  *
  * @param array $productIds
  *
  * @return array
  */
 public function getFieldsList($productIds)
 {
     $this->prepareAvailableAttributeIds($productIds);
     $attributes = $this->getAttributeIds();
     if (empty($attributes)) {
         return [];
     }
     $attributes = $this->attributeRepository->findBy(['id' => $this->getAttributeIds()]);
     return $this->prepareFieldsList($attributes);
 }
 /**
  * Normalize the attributes
  *
  * @param FamilyInterface $family
  *
  * @return array
  */
 protected function normalizeAttributes(FamilyInterface $family)
 {
     $attributes = $this->collectionFilter->filterCollection($this->attributeRepository->findAttributesByFamily($family), 'pim.internal_api.attribute.view');
     $normalizedAttributes = [];
     foreach ($attributes as $attribute) {
         $normalizedAttributes[] = $attribute->getCode();
     }
     sort($normalizedAttributes);
     return $normalizedAttributes;
 }
 /**
  * Get axis as choice list
  *
  * @deprecated not used anymore except in datagrid configuration, will be removed in 1.5
  *
  * @return array
  */
 public function getAvailableAxisChoices()
 {
     $attributes = $this->attributeRepository->findAllAxis();
     $choices = [];
     foreach ($attributes as $attribute) {
         $choices[$attribute->getId()] = $attribute->getLabel();
     }
     asort($choices);
     return $choices;
 }
 /**
  * {@inheritdoc}
  */
 public function denormalize($data, $class, $format = null, array $context = [])
 {
     $values = new ArrayCollection();
     foreach ($data as $attributeCode => $valuesData) {
         $attribute = $this->attributeRepository->findOneByIdentifier($attributeCode);
         foreach ($valuesData as $valueData) {
             $value = $this->denormalizer->denormalize($valueData, $this->valueClass, 'json', ['attribute' => $attribute] + $context);
             $values->add($value);
         }
     }
     return $values;
 }
 /**
  * @return FamilyInterface
  */
 public function createFamily()
 {
     $family = new $this->familyClass();
     $identifier = $this->attributeRepository->getIdentifier();
     $family->addAttribute($identifier);
     $family->setAttributeAsLabel($identifier);
     foreach ($this->getChannels() as $channel) {
         $requirement = $this->factory->createAttributeRequirement($identifier, $channel, true);
         $family->addAttributeRequirement($requirement);
     }
     return $family;
 }
 /**
  * {@inheritdoc}
  */
 public function process($family)
 {
     $actions = $this->getConfiguredActions();
     foreach ($actions as $action) {
         $attribute = $this->attributeRepository->findOneByIdentifier($action['attribute_code']);
         $channel = $this->channelRepository->findOneByIdentifier($action['channel_code']);
         $isRequired = $action['is_required'];
         $family->addAttribute($attribute);
         $family->addAttributeRequirement($this->factory->createAttributeRequirement($attribute, $channel, $isRequired));
     }
     return $family;
 }
 /**
  * {@inheritdoc}
  */
 public function getPresenterByAttributeCode($code)
 {
     $attribute = $this->attributeRepository->findOneByIdentifier($code);
     if (null === $attribute) {
         return null;
     }
     $attributeType = $attribute->getAttributeType();
     if (null === $attributeType) {
         return null;
     }
     return $this->getPresenter($attributeType, self::TYPE_PRODUCT_VALUE);
 }
 function it_denormalizes_product_values_from_json($denormalizer, $registry, AttributeRepositoryInterface $attributeRepository, ProductValueInterface $nameValue, ProductValueInterface $colorValue, AttributeInterface $name, AttributeInterface $color)
 {
     $data = ['name' => [['locale' => null, 'scope' => null, 'value' => 'foo']], 'color' => [['locale' => 'en_US', 'scope' => 'ecommerce', 'value' => 'red']]];
     $attributeRepository->findOneByIdentifier('name')->willReturn($name);
     $attributeRepository->findOneByIdentifier('color')->willReturn($color);
     $registry->getRepository('Attribute')->willReturn($attributeRepository);
     $denormalizer->denormalize($data['name'][0], 'ProductValue', 'json', ['attribute' => $name])->shouldBeCalled()->willReturn($nameValue);
     $denormalizer->denormalize($data['color'][0], 'ProductValue', 'json', ['attribute' => $color])->shouldBeCalled()->willReturn($colorValue);
     $values = $this->denormalize($data, 'ProductValue[]', 'json');
     $values->shouldHaveCount(2);
     $values[0]->shouldBe($nameValue);
     $values[1]->shouldBe($colorValue);
 }
 /**
  * {@inheritdoc}
  */
 public function validate($attributes, Constraint $constraint)
 {
     if (null === $attributes || !count($attributes)) {
         return;
     }
     $errorCount = 0;
     foreach ($attributes as $attributeCode) {
         $attribute = $this->attributeRepository->findOneByIdentifier($attributeCode);
         if (null === $attribute) {
             $this->context->buildViolation($constraint->message)->setParameter('%attributeCode%', $attributeCode)->atPath(sprintf('[%d]', $errorCount))->addViolation();
             $errorCount++;
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function dump(OutputInterface $output, HelperSet $helperSet)
 {
     $output->writeln("<info>Useable attributes filters...</info>");
     $attributeFilters = $this->getAttributeFilters();
     $attributes = $this->repository->findAll();
     $rows = [];
     foreach ($attributes as $attribute) {
         $rows = array_merge($rows, $this->getFilterInformationForAttribute($attribute, $attributeFilters));
     }
     $table = $helperSet->get('table');
     $headers = ['attribute', 'localizable', 'scopable', 'attribute type', 'operators', 'filter_class'];
     $table->setHeaders($headers)->setRows($rows);
     $table->render($output);
 }
 /**
  * @param FamilyInterface $family
  *
  * @return string[]
  */
 protected function getMissingChannelCodes(FamilyInterface $family)
 {
     $requirements = $family->getAttributeRequirements();
     $identifierCode = $this->attributeRepository->getIdentifierCode();
     $currentChannelCodes = [];
     foreach ($requirements as $requirement) {
         if ($requirement->getAttributeCode() === $identifierCode) {
             $currentChannelCodes[] = $requirement->getChannelCode();
         }
     }
     $expectedChannelCodes = $this->channelRepository->getChannelCodes();
     $missingChannelCodes = array_diff($expectedChannelCodes, $currentChannelCodes);
     return $missingChannelCodes;
 }
 /**
  * Get the attribute collection
  *
  * @return JsonResponse
  */
 public function indexAction(Request $request)
 {
     $criteria = [];
     if ($request->query->has('identifiers')) {
         $criteria['code'] = explode(',', $request->query->get('identifiers'));
     }
     if ($request->query->has('types')) {
         $criteria['attributeType'] = explode(',', $request->query->get('types'));
     }
     $attributes = $this->attributeRepository->findBy($criteria);
     $filteredAttributes = $this->collectionFilter->filterCollection($attributes, 'pim.internal_api.attribute.view');
     $normalizedAttributes = $this->normalizer->normalize($filteredAttributes, 'internal_api');
     return new JsonResponse($normalizedAttributes);
 }
 /**
  * @param GroupInterface $group
  * @param array          $data
  */
 protected function setAxis(GroupInterface $group, $data)
 {
     if (isset($data['axis']) && !empty($data['axis'])) {
         $axisCodes = explode(',', $data['axis']);
         $attributes = [];
         foreach ($axisCodes as $code) {
             $attribute = $this->attributeRepository->findOneByIdentifier($code);
             if (!$attribute) {
                 throw new \LogicException(sprintf('Attribute with identifier "%s" not found', $code));
             }
             $attributes[] = $attribute;
         }
         $group->setAxisAttributes($attributes);
     }
 }
 /**
  * Transforms a relative path to absolute. Data must be provided in the pivot format.
  *
  * $item exemple:
  * [
  *   'side_view' => [
  *     [
  *       'locale' => null,
  *       'scope'  => null,
  *       'data'   => [
  *         'filePath'         => 'cat_003.png',
  *         'originalFilename' => 'cat_003.png'
  *       ]
  *     ]
  *   ]
  * ]
  *
  * @param array  $attributeValues An associative array (attribute_code => values)
  * @param string $filePath        The absolute path
  *
  * @return array
  */
 public function transform(array $attributeValues, $filePath)
 {
     $mediaAttributes = $this->attributeRepository->findMediaAttributeCodes();
     foreach ($attributeValues as $code => $values) {
         if (in_array($code, $mediaAttributes)) {
             foreach ($values as $index => $value) {
                 if (isset($value['data']) && isset($value['data']['filePath'])) {
                     $dataFilePath = $value['data']['filePath'];
                     $attributeValues[$code][$index]['data']['filePath'] = sprintf('%s%s%s', $filePath, DIRECTORY_SEPARATOR, $dataFilePath);
                 }
             }
         }
     }
     return $attributeValues;
 }
 /**
  * {@inheritdoc}
  */
 public function convertDefaultToLocalizedValue($code, $data, $options = [])
 {
     $attribute = $this->attributeRepository->findOneBy(['code' => $code]);
     if (null === $attribute) {
         return $data;
     }
     $attributeType = $attribute->getAttributeType();
     if (null === $attributeType) {
         return $data;
     }
     $localizer = $this->localizerRegistry->getLocalizer($attributeType);
     if (null === $localizer) {
         return $data;
     }
     return $localizer->localize($data, $options);
 }
 /**
  * - Add the media to the $this->writtenFiles to be archive later
  * - Update the value of each media in the standard format to add the final path of media in archive.
  *
  * The standard format for a media contains only the filePath (which is the unique key of the media):
  * {
  *     "values": {
  *         "picture": [
  *              {
  *                  "locale": "en_US",
  *                  "scope": "ecommerce",
  *                  "data": [
  *                      "filePath": "a/b/c/d/e/it_s_my_filename.jpg"
  *                  ]
  *              }
  *          ]
  *     }
  * }
  *
  * In exported files, we don't want to see the key, but the original filename. As the standard format does not
  * contain this information, we use the Finder() to find the media in the temporary directory created in processor.
  *
  * After:
  * {
  *     "values": {
  *         "picture": [
  *              {
  *                  "locale": "en_US",
  *                  "scope": "ecommerce",
  *                  "data": [
  *                      "filePath": "files/item_identifier/picture/en_US/ecommerce/it's my filename.jpg"
  *                  ]
  *              }
  *          ]
  *     }
  * }
  *
  * @param array  $item          standard format of an item
  * @param string $tmpDirectory  directory where media have been copied before to be exported
  *
  * @return array
  */
 protected function resolveMediaPaths(array $item, $tmpDirectory)
 {
     $attributeTypes = $this->attributeRepository->getAttributeTypeByCodes(array_keys($item['values']));
     $mediaAttributeTypes = array_filter($attributeTypes, function ($attributeCode) {
         return in_array($attributeCode, $this->mediaAttributeTypes);
     });
     $identifier = $this->getItemIdentifier($item);
     foreach ($mediaAttributeTypes as $attributeCode => $attributeType) {
         foreach ($item['values'][$attributeCode] as $index => $value) {
             if (null !== $value['data']) {
                 $exportDirectory = $this->fileExporterPath->generate($value, ['identifier' => $identifier, 'code' => $attributeCode]);
                 $finder = new Finder();
                 if (is_dir($tmpDirectory . $exportDirectory)) {
                     $files = iterator_to_array($finder->files()->in($tmpDirectory . $exportDirectory));
                     if (!empty($files)) {
                         $path = $exportDirectory . current($files)->getFilename();
                         $this->writtenFiles[$tmpDirectory . $path] = $path;
                         $item['values'][$attributeCode][$index]['data']['filePath'] = $path;
                     }
                 }
             }
         }
     }
     return $item;
 }
 /**
  * Remove an attribute
  *
  * @param int $familyId
  * @param int $attributeId
  *
  * @AclAncestor("pim_enrich_family_edit_attributes")
  *
  * @throws DeleteException
  *
  * @return \Symfony\Component\HttpFoundation\RedirectResponse
  */
 public function removeAttributeAction($familyId, $attributeId)
 {
     $family = $this->familyRepository->find($familyId);
     if (null === $family) {
         throw new NotFoundHttpException(sprintf('%s entity not found', $this->familyClass));
     }
     $attribute = $this->attributeRepo->find($attributeId);
     if (null === $attribute) {
         throw new NotFoundHttpException(sprintf('%s entity not found', $this->attributeClass));
     }
     if (false === $family->hasAttribute($attribute)) {
         throw new DeleteException($this->translator->trans('flash.family.attribute not found'));
     } elseif (AttributeTypes::IDENTIFIER === $attribute->getAttributeType()) {
         throw new DeleteException($this->translator->trans('flash.family.identifier not removable'));
     } elseif ($attribute === $family->getAttributeAsLabel()) {
         throw new DeleteException($this->translator->trans('flash.family.label attribute not removable'));
     } else {
         $family->removeAttribute($attribute);
         foreach ($family->getAttributeRequirements() as $requirement) {
             if ($requirement->getAttribute() === $attribute) {
                 $family->removeAttributeRequirement($requirement);
                 $this->doctrine->getManagerForClass(ClassUtils::getClass($requirement))->remove($requirement);
             }
         }
         $this->familySaver->save($family);
     }
     if ($this->request->isXmlHttpRequest()) {
         return new Response('', 204);
     } else {
         return new RedirectResponse($this->router->generate('pim_enrich_family_edit', ['id' => $family->getId()]));
     }
 }
 /**
  * {@inheritdoc}
  */
 public function process($family)
 {
     $configuration = $this->getJobConfiguration();
     if (!array_key_exists('actions', $configuration)) {
         throw new InvalidArgumentException('Missing configuration for \'actions\'.');
     }
     $actions = $configuration['actions'];
     foreach ($actions as $action) {
         $attribute = $this->attributeRepository->findOneByIdentifier($action['attribute_code']);
         $channel = $this->channelRepository->findOneByIdentifier($action['channel_code']);
         $isRequired = $action['is_required'];
         $family->addAttribute($attribute);
         $family->addAttributeRequirement($this->factory->createAttributeRequirement($attribute, $channel, $isRequired));
     }
     return $family;
 }
 /**
  * @param string $code
  *
  * @return AttributeInterface
  */
 protected function getAttribute($code)
 {
     if (!array_key_exists($code, $this->attributes)) {
         $this->attributes[$code] = $this->attributeRepository->findOneByIdentifier($code);
     }
     return $this->attributes[$code];
 }
 /**
  * {@inheritdoc}
  */
 public function convertLocalizedToDefaultValues(array $items, array $options = [])
 {
     $this->violations = new ConstraintViolationList();
     $attributeTypes = $this->attributeRepository->getAttributeTypeByCodes(array_keys($items));
     foreach ($items as $code => $item) {
         if (isset($attributeTypes[$code])) {
             $localizer = $this->localizerRegistry->getLocalizer($attributeTypes[$code]);
             if (null !== $localizer) {
                 foreach ($item as $index => $data) {
                     $items[$code][$index] = $this->convertLocalizedToDefaultValue($localizer, $data, $options, $this->buildPropertyPath($data, $code));
                 }
             }
         }
     }
     return $items;
 }
 /**
  * Find an attribute by its id or return a 404 response
  *
  * @param int $id the attribute id
  *
  * @throws NotFoundHttpException
  *
  * @return AttributeInterface
  */
 protected function findAttributeOr404($id)
 {
     $attribute = $this->attributeRepository->find($id);
     if (!$attribute) {
         throw new NotFoundHttpException(sprintf('Attribute with id %d could not be found.', $id));
     }
     return $attribute;
 }
 /**
  * @param int $id
  *
  * @return AttributeInterface
  */
 protected function findAttributeOr404($id)
 {
     $result = $this->attributeRepo->find($id);
     if (!$result) {
         throw new NotFoundHttpException('Attribute not found');
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function createProduct($identifier = null, $familyCode = null)
 {
     $product = new $this->productClass();
     $identifierAttribute = $this->attributeRepository->getIdentifier();
     $productValue = $this->createProductValue($identifierAttribute);
     $product->addValue($productValue);
     if (null !== $identifier) {
         $productValue->setData($identifier);
     }
     if (null !== $familyCode) {
         $family = $this->familyRepository->findOneByIdentifier($familyCode);
         $product->setFamily($family);
     }
     $event = new GenericEvent($product);
     $this->eventDispatcher->dispatch(ProductEvents::CREATE, $event);
     return $product;
 }