function it_hydrates_a_result_record(Builder $builder, Query $query, ProductInterface $product, Association $association, AssociationType $associationType, ProductInterface $associatedProduct1, ProductInterface $associatedProduct2, DocumentManager $documentManager, \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $metadata, Collection $collection, ArrayIterator $arrayIterator)
 {
     $options = ['locale_code' => 'en_US', 'scope_code' => 'print', 'current_group_id' => null, 'attributes_configuration' => [], 'association_type_id' => 1, 'current_product' => $product];
     $builder->getQuery()->willReturn($query);
     $builder->hydrate(false)->willReturn($builder);
     $associatedProduct1->getId()->willReturn('550ae6b98ead0ed7778b46bb');
     $associatedProduct2->getId()->willReturn('550ae6b98abd0ec8778b46bb');
     $product->getAssociations()->willReturn([$association]);
     $association->getAssociationType()->willReturn($associationType);
     $associationType->getId()->willReturn(1);
     $association->getProducts()->willReturn([$associatedProduct1, $associatedProduct2]);
     $queryDefinition = ['type' => 1, 'sort' => ['normalizedData.is_associated' => -1, '_id' => 1], 'limit' => 10, 'skip' => 0, 'query' => ['_id' => ['$ne' => \MongoId::__set_state(['$id' => '550ae6b98ead0ee8778b46bb'])]], 'newObj' => []];
     $query->getQuery()->willReturn($queryDefinition);
     $query->getDocumentManager()->willReturn($documentManager);
     $documentManager->getDocumentCollection(Argument::any())->willReturn($collection);
     $documentManager->getClassMetadata(Argument::any())->willReturn($metadata);
     $metadata->getFieldNames()->willReturn(['id', 'created', 'updated', 'locale', 'scope', 'values', 'indexedValues', 'indexedValuesOutdated', 'family', 'familyId', 'categories', 'categoryIds', 'enabled', 'groups', 'groupIds', 'associations', 'completenesses', 'normalizedData']);
     $pipeline = [['$match' => ['_id' => ['$ne' => \MongoId::__set_state(['$id' => '550ae6b98ead0ee8778b46bb'])]]], ['$project' => ['id' => 1, 'created' => 1, 'updated' => 1, 'locale' => 1, 'scope' => 1, 'values' => 1, 'indexedValues' => 1, 'indexedValuesOutdated' => 1, 'family' => 1, 'familyId' => 1, 'categories' => 1, 'categoryIds' => 1, 'enabled' => 1, 'groups' => 1, 'groupIds' => 1, 'associations' => 1, 'completenesses' => 1, 'normalizedData' => 1, 'is_associated' => ['$cond' => [['$or' => [['$eq' => ['$_id', \MongoId::__set_state(['$id' => '550ae6b98ead0ed7778b46bb'])]], ['$eq' => ['$_id', \MongoId::__set_state(['$id' => '550ae6b98abd0ec8778b46bb'])]]]], 1, 0]]]], ['$sort' => ['is_associated' => -1]], ['$skip' => 0], ['$limit' => 10]];
     $collection->aggregate($pipeline)->willReturn($arrayIterator);
     $fixture = ['_id' => \MongoId::__set_state(['$id' => '550ae6b98ead0ee8778b46bb']), 'normalizedData' => [], 'sku' => ['attribute' => ['code' => 'sku', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => null, 'scope' => null, 'value' => 'mysku'], 'name' => ['attribute' => ['code' => 'name', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => 'fr_FR', 'scope' => null], 'desc' => ['attribute' => ['code' => 'desc', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => 'fr_FR', 'scope' => 'print'], 'is_associated' => 1];
     $arrayIterator->toArray()->willReturn([$fixture]);
     $rows = $this->hydrate($builder, $options);
     $rows->shouldHaveCount(1);
     $firstResult = $rows[0];
     $firstResult->shouldBeAnInstanceOf('\\Oro\\Bundle\\DataGridBundle\\Datasource\\ResultRecord');
 }
 function it_normalizes_an_existing_product_into_mongodb_document($mongoFactory, $serializer, ProductInterface $product, \MongoId $mongoId, \MongoDate $mongoDate, Association $assoc1, Association $assoc2, CategoryInterface $category1, CategoryInterface $category2, GroupInterface $group1, GroupInterface $group2, ProductValueInterface $value1, ProductValueInterface $value2, FamilyInterface $family)
 {
     $mongoFactory->createMongoId('product1')->willReturn($mongoId);
     $mongoFactory->createMongoDate()->willReturn($mongoDate);
     $family->getId()->willReturn(36);
     $category1->getId()->willReturn(12);
     $category2->getId()->willReturn(34);
     $group1->getId()->willReturn(56);
     $group2->getId()->willReturn(78);
     $product->getId()->willReturn('product1');
     $product->getCreated()->willReturn(null);
     $product->getFamily()->willReturn($family);
     $product->isEnabled()->willReturn(true);
     $product->getGroups()->willReturn([$group1, $group2]);
     $product->getCategories()->willReturn([$category1, $category2]);
     $product->getAssociations()->willReturn([$assoc1, $assoc2]);
     $product->getValues()->willReturn([$value1, $value2]);
     $context = ['_id' => $mongoId];
     $serializer->normalize($product, 'mongodb_json')->willReturn(['data' => 'data', 'completenesses' => 'completenesses']);
     $serializer->normalize($value1, 'mongodb_document', $context)->willReturn('my_value_1');
     $serializer->normalize($value2, 'mongodb_document', $context)->willReturn('my_value_2');
     $serializer->normalize($assoc1, 'mongodb_document', $context)->willReturn('my_assoc_1');
     $serializer->normalize($assoc2, 'mongodb_document', $context)->willReturn('my_assoc_2');
     $this->normalize($product, 'mongodb_document')->shouldReturn(['_id' => $mongoId, 'created' => $mongoDate, 'updated' => $mongoDate, 'family' => 36, 'enabled' => true, 'groupIds' => [56, 78], 'categoryIds' => [12, 34], 'associations' => ['my_assoc_1', 'my_assoc_2'], 'values' => ['my_value_1', 'my_value_2'], 'normalizedData' => ['data' => 'data'], 'completenesses' => []]);
 }
 function it_massively_insert_new_products_and_update_existing_products($documentManager, $collection, $normalizer, $mongoFactory, $pendingPersister, $eventDispatcher, ProductInterface $product1, ProductInterface $product2, ProductInterface $product3, ProductInterface $product4)
 {
     $mongoFactory->createMongoId()->willReturn('my_mongo_id');
     $product1->getId()->willReturn("my_product_1");
     $product2->getId()->willReturn(null);
     $product3->getId()->willReturn("my_product_3");
     $product4->getId()->willReturn(null);
     $product1->setId(Argument::any())->shouldNotBeCalled();
     $product2->setId('my_mongo_id')->shouldBeCalled();
     $product3->setId(Argument::any())->shouldNotBeCalled();
     $product4->setId('my_mongo_id')->shouldBeCalled();
     $normalizer->normalize($product1, 'mongodb_document', ['collection_name' => 'pim_product_collection'])->willReturn(['_id' => 'my_product_1', 'normalized_product_1']);
     $normalizer->normalize($product2, 'mongodb_document', ['collection_name' => 'pim_product_collection'])->willReturn(['_id' => 'my_mongo_id', 'normalized_product_2']);
     $normalizer->normalize($product3, 'mongodb_document', ['collection_name' => 'pim_product_collection'])->willReturn(['_id' => 'my_product_3', 'normalized_product_3']);
     $normalizer->normalize($product4, 'mongodb_document', ['collection_name' => 'pim_product_collection'])->willReturn(['_id' => 'my_mongo_id', 'normalized_product_4']);
     $collection->batchInsert([['_id' => 'my_mongo_id', 'normalized_product_2'], ['_id' => 'my_mongo_id', 'normalized_product_4']])->shouldBeCalled();
     $collection->update(['_id' => 'my_product_1'], ['_id' => 'my_product_1', 'normalized_product_1'])->shouldBeCalled();
     $collection->update(['_id' => 'my_product_3'], ['_id' => 'my_product_3', 'normalized_product_3'])->shouldBeCalled();
     $pendingPersister->persistPendingVersions([$product1, $product2, $product3, $product4])->shouldBeCalled();
     $eventDispatcher->dispatch('pim_base_connector.direct_to_db_writer.pre_insert', Argument::any())->shouldBeCalled();
     $eventDispatcher->dispatch('pim_base_connector.direct_to_db_writer.pre_update', Argument::any())->shouldBeCalled();
     $eventDispatcher->dispatch('pim_base_connector.direct_to_db_writer.post_insert', Argument::any())->shouldBeCalled();
     $eventDispatcher->dispatch('pim_base_connector.direct_to_db_writer.post_update', Argument::any())->shouldBeCalled();
     $documentManager->clear()->shouldBeCalled();
     $this->write([$product1, $product2, $product3, $product4]);
 }
 function it_clears_cache(StepExecution $stepExecution, ProductInterface $product1, ProductInterface $product2)
 {
     $items = [$product1, $product2];
     $product1->getId()->willReturn('45');
     $product2->getId()->willReturn(null);
     $this->setStepExecution($stepExecution);
     $this->write($items);
 }
 function it_find_previous_and_next_products($productManager, SequentialEdit $sequentialEdit, ProductInterface $product, ProductInterface $previous, ProductInterface $next)
 {
     $sequentialEdit->getObjectSet()->willReturn([1, 6, 5, 2]);
     $sequentialEdit->countObjectSet()->willReturn(4);
     $product->getId()->willReturn(5);
     $productManager->find(6)->willReturn($previous);
     $productManager->find(2)->willReturn($next);
     $sequentialEdit->setCurrent($product)->shouldBeCalled();
     $sequentialEdit->setPrevious($previous)->shouldBeCalled();
     $sequentialEdit->setNext($next)->shouldBeCalled();
     $this->findWrap($sequentialEdit, $product);
 }
 function it_builds_pending_versions_for_a_given_entity(ProductInterface $product, $builder, $versionRepository)
 {
     $product->getId()->willReturn(1);
     $pending1 = new Version('Product', 1, 'julia');
     $pending1->setChangeset(['foo' => 'bar']);
     $pending2 = new Version('Product', 1, 'julia');
     $pending2->setChangeset(['foo' => 'fubar']);
     $versionRepository->findBy(Argument::cetera())->willReturn([$pending1, $pending2]);
     $builder->buildPendingVersion($pending1, null)->willReturn($pending1)->shouldBeCalled();
     $builder->buildPendingVersion($pending2, $pending1)->willReturn($pending2)->shouldBeCalled();
     $versions = $this->buildPendingVersions($product);
     $versions->shouldHaveCount(2);
 }
 function it_builds_versions_for_versionable_entities($normalizer, ProductInterface $product)
 {
     $product->getId()->willReturn(1);
     $normalizer->normalize($product, 'csv', ['versioning' => true])->willReturn(['bar' => 'baz']);
     $version = $this->buildVersion($product, 'foo');
     $version->shouldBeAnInstanceOf('Pim\\Bundle\\VersioningBundle\\Model\\Version');
     $version->getAuthor()->shouldReturn('foo');
     $version->isPending()->shouldReturn(false);
     $version->getVersion()->shouldReturn(1);
     $version->getResourceId()->shouldReturn(1);
     $version->getSnapshot()->shouldReturn(['bar' => 'baz']);
     $version->getChangeset()->shouldReturn(['bar' => ['old' => '', 'new' => 'baz']]);
 }
 /**
  * Update export date for the given product.
  *
  * @param ProductInterface $product
  * @param JobInstance      $jobInstance
  * @param string           $table
  */
 protected function updateExport(ProductInterface $product, JobInstance $jobInstance, $table)
 {
     $conn = $this->entityManager->getConnection();
     $sql = "\n            INSERT INTO {$table}\n            (product_id, job_instance_id, last_export)\n            VALUES (:product_id, :job_instance_id, :last_export)\n            ON DUPLICATE KEY UPDATE last_export = :last_export\n        ";
     $now = new \DateTime('now', new \DateTimeZone('UTC'));
     $formattedNow = $now->format('Y-m-d H:i:s');
     $productId = $product->getId();
     $jobInstanceId = $jobInstance->getId();
     $query = $conn->prepare($sql);
     $query->bindParam(':last_export', $formattedNow, PDO::PARAM_STR);
     $query->bindParam(':product_id', $productId, PDO::PARAM_INT);
     $query->bindParam(':job_instance_id', $jobInstanceId, PDO::PARAM_INT);
     $query->execute();
 }
 function it_massively_insert_and_update_objects($bulkSaver, $bulkDetacher, $stepExecution, ProductInterface $product1, ProductInterface $product2, AssociationInterface $association2)
 {
     $bulkSaver->saveAll([$product1, $product2]);
     $bulkDetacher->detachAll([$product1, $product2]);
     $product1->getId()->willReturn(null);
     $association1 = new Association();
     $product1->getAssociations()->willReturn(new ArrayCollection([$association1]));
     $stepExecution->incrementSummaryInfo('process')->shouldBeCalled();
     $product2->getId()->willReturn(42);
     $association2->getId()->willReturn(1);
     $product2->getAssociations()->willReturn(new ArrayCollection([$association2]));
     $stepExecution->incrementSummaryInfo('process')->shouldBeCalled();
     $this->write([$product1, $product2]);
 }
 function it_applies_a_filter_on_product_when_its_in_an_expected_association(FilterDatasourceAdapterInterface $datasource, $utility, QueryBuilder $qb, $extractor, $assocRepository, ProductManager $productManager, AssociationTypeInterface $assocType, AbstractAssociation $association, ProductInterface $productOwner, ProductInterface $productAssociatedOne, ProductInterface $productAssociatedTwo, $manager)
 {
     $extractor->getDatagridParameter('_parameters', [])->willReturn([]);
     $extractor->getDatagridParameter('associationType')->willReturn(1);
     $assocRepository->findOneBy(Argument::any())->willReturn($assocType);
     $extractor->getDatagridParameter('product')->willReturn(11);
     $manager->find(11)->willReturn($productOwner);
     $productOwner->getAssociationForType($assocType)->willReturn($association);
     $association->getProducts()->willReturn([$productAssociatedOne, $productAssociatedTwo]);
     $productAssociatedOne->getId()->willReturn(12);
     $productAssociatedTwo->getId()->willReturn(13);
     $utility->applyFilter($datasource, 'id', 'IN', [12, 13])->shouldBeCalled();
     $this->apply($datasource, ['type' => null, 'value' => 1]);
 }
 /**
  * Returns the required attribute codes for a product
  *
  * @param ProductInterface $product
  *
  * @return array
  */
 public function getRequiredAttributeCodes(ProductInterface $product)
 {
     $codes = array();
     if ($product->getFamily()) {
         $codes = $this->getFamilyAttributeCodes($product->getFamily());
     }
     foreach ($product->getGroups() as $group) {
         $codes = array_merge($codes, $this->getGroupAttributeCodes($group));
     }
     if ($product->getId()) {
         foreach ($product->getValues() as $value) {
             $codes[] = $value->getAttribute()->getCode();
         }
     }
     return array_unique($codes);
 }
 function it_hydrates_a_result_record(Builder $builder, Query $query, ProductInterface $product, Association $association, AssociationType $associationType, ProductInterface $associatedProduct1, ProductInterface $associatedProduct2, ArrayCollection $productsCollection, ArrayCollection $productIdsCollection, ArrayIterator $productsIterator, ArrayCollection $associationsCollection, ArrayIterator $associationsIterator, ArrayIterator $arrayIterator)
 {
     $product->getId()->willReturn('110ae6b98ead0ee8778b46bb');
     $options = ['locale_code' => 'en_US', 'scope_code' => 'print', 'current_group_id' => null, 'attributes_configuration' => [], 'association_type_id' => 1, 'current_product' => $product];
     $builder->find()->willReturn($builder);
     $builder->count()->willReturn($builder);
     $builder->getQuery()->willReturn($query);
     $builder->hydrate(false)->willReturn($builder);
     $builder->setQueryArray(Argument::any())->willReturn($builder);
     $builder->limit(Argument::any())->willReturn($builder);
     $builder->skip(Argument::any())->willReturn($builder);
     $product->getAssociations()->willReturn($associationsCollection);
     $associationsCollection->getIterator()->willReturn($associationsIterator);
     $associationsIterator->rewind()->shouldBeCalled();
     $associationsCount = 1;
     $associationsIterator->valid()->will(function () use(&$associationsCount) {
         return $associationsCount-- > 0;
     });
     $associationsIterator->next()->shouldBeCalled();
     $associationsIterator->current()->will(new ReturnPromise([$association]));
     $associationsCollection->filter(Argument::any())->willReturn($associationsIterator);
     $associationsIterator->first()->willReturn($association);
     $association->getAssociationType()->willReturn($associationType);
     $associationType->getId()->willReturn(1);
     $associatedProduct1->getId()->willReturn('220ae6b98ead0ed7778b46bb');
     $associatedProduct2->getId()->willReturn('330ae6b98abd0ec8778b46bb');
     $association->getProducts()->willReturn($productsCollection);
     $productsCollection->getIterator()->willReturn($productsIterator);
     $productsIterator->rewind()->shouldBeCalled();
     $productsCount = 2;
     $productsIterator->valid()->will(function () use(&$productsCount) {
         return $productsCount-- > 0;
     });
     $productsIterator->next()->shouldBeCalled();
     $productsIterator->current()->will(new ReturnPromise([$associatedProduct1, $associatedProduct2]));
     $productsCollection->map(Argument::any())->willReturn($productIdsCollection);
     $productIdsCollection->toArray()->willReturn(['220ae6b98ead0ed7778b46bb', '330ae6b98abd0ec8778b46bb']);
     $queryDefinition = ['type' => 1, 'sort' => ['normalizedData.is_associated' => -1, '_id' => 1], 'limit' => 10, 'skip' => 0, 'query' => ['_id' => ['$ne' => \MongoId::__set_state(['$id' => '110ae6b98ead0ee8778b46bb'])]], 'newObj' => []];
     $query->getQuery()->willReturn($queryDefinition);
     $fixture = ['_id' => \MongoId::__set_state(['$id' => '550ae6b98ead0ee8778b46bb']), 'normalizedData' => [], 'sku' => ['attribute' => ['code' => 'sku', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => null, 'scope' => null, 'value' => 'mysku'], 'name' => ['attribute' => ['code' => 'name', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => 'fr_FR', 'scope' => null], 'desc' => ['attribute' => ['code' => 'desc', 'attributeType' => 'text', 'backendType' => 'text'], 'locale' => 'fr_FR', 'scope' => 'print'], 'is_associated' => 1];
     $query->execute()->willReturn($arrayIterator);
     $arrayIterator->toArray()->willReturn([$fixture]);
     $rows = $this->hydrate($builder, $options);
     $rows->shouldHaveCount(1);
     $firstResult = $rows[0];
     $firstResult->shouldBeAnInstanceOf('\\Oro\\Bundle\\DataGridBundle\\Datasource\\ResultRecord');
 }
 function it_normalizes_an_association_with_products_and_groups($mongoFactory, Association $assoc, AssociationTypeInterface $assocType, \MongoId $mongoId, \MongoDBRef $ownerRef, ProductInterface $product1, \MongoDBRef $product1Ref, ProductInterface $product2, \MongoDBRef $product2Ref, GroupInterface $group1, GroupInterface $group2)
 {
     $assocType->getId()->willReturn(8);
     $assoc->getAssociationType()->willReturn($assocType);
     $context = ['_id' => '1234abc', 'collection_name' => 'product'];
     $mongoFactory->createMongoId()->willReturn($mongoId);
     $mongoFactory->createMongoDBRef('product', '1234abc')->willReturn($ownerRef);
     $mongoFactory->createMongoDBRef('product', 'product1')->willReturn($product1Ref);
     $mongoFactory->createMongoDBRef('product', 'product2')->willReturn($product2Ref);
     $product1->getId()->willReturn('product1');
     $product2->getId()->willReturn('product2');
     $assoc->getProducts()->willReturn([$product1, $product2]);
     $group1->getId()->willReturn(1);
     $group2->getId()->willReturn(2);
     $assoc->getGroups()->willReturn([$group1, $group2]);
     $this->normalize($assoc, 'mongodb_document', $context)->shouldReturn(['_id' => $mongoId, 'associationType' => 8, 'owner' => $ownerRef, 'products' => [$product1Ref, $product2Ref], 'groupIds' => [1, 2]]);
 }
 /**
  * @param array                 $result
  * @param string                $associationTypeId
  * @param ProductInterface|null $product
  *
  * @return array
  */
 public function transform(array $result, $associationTypeId, ProductInterface $product = null)
 {
     if ($product) {
         $associationTypeId = (int) $associationTypeId;
         $result['is_associated'] = false;
         $currentAssociation = $product->getAssociations()->filter(function ($association) use($associationTypeId) {
             return $association->getAssociationType()->getId() === $associationTypeId;
         })->first();
         if ($currentAssociation) {
             $associatedIds = $currentAssociation->getProducts()->map(function ($product) {
                 return $product->getId();
             })->toArray();
             if (in_array($result['id'], $associatedIds)) {
                 $result['is_associated'] = true;
             }
         }
         $result['is_checked'] = $result['is_associated'];
     }
     return $result;
 }
 /**
  * Get matching products
  *
  * @param GroupInterface   $variantGroup the variant group
  * @param ProductInterface $entity       the product
  * @param array            $criteria     query criterias
  *
  * @return ProductInterface[]
  */
 protected function getMatchingProducts(GroupInterface $variantGroup, ProductInterface $entity = null, array $criteria = [])
 {
     if (!$variantGroup->getId()) {
         return [];
     }
     $matchingProducts = $this->repository->findAllForVariantGroup($variantGroup, $criteria);
     if ($entity) {
         $matchingProducts = array_filter($matchingProducts, function ($product) use($entity) {
             return $product->getId() !== $entity->getId();
         });
     }
     return $matchingProducts;
 }
 /**
  * Schedule recalculation of completenesses for a product
  *
  * @param ProductInterface $product
  */
 public function schedule(ProductInterface $product)
 {
     if ($product->getId()) {
         $this->generator->schedule($product);
     }
 }
 /**
  * @param ProductInterface $product
  */
 protected function incrementCount(ProductInterface $product)
 {
     if ($product->getId()) {
         $this->stepExecution->incrementSummaryInfo('process');
     } else {
         $this->stepExecution->incrementSummaryInfo('create');
     }
 }
 /**
  * @param ProductInterface $product
  *
  * @return bool
  */
 protected function needsUpdate(ProductInterface $product)
 {
     $delta = $this->deltaRepository->findOneBy(['productId' => $product->getId(), 'jobInstance' => $this->stepExecution->getJobExecution()->getJobInstance()]);
     return null === $delta || $delta->getLastExport() < $product->getUpdated();
 }
 /**
  * {@inheritdoc}
  */
 public function generateMissingForProduct(ProductInterface $product)
 {
     $this->generate(array('productId' => $product->getId()));
 }
 /**
  * {@inheritdoc}
  *
  * TODO: find a way to do it efficiently
  */
 public function findByProductAndOwnerIds(ProductInterface $product, array $ownerIds)
 {
     $ownerIds = array_map(function ($id) {
         return new \MongoId($id);
     }, $ownerIds);
     // retrieve products whom associations are concerned
     $qb = $this->createQueryBuilder('p');
     $qb->select('associations')->field('_id')->in($ownerIds)->field('associations.products.$id')->equals(new \MongoId($product->getId()));
     $products = $qb->getQuery()->execute();
     $associations = [];
     // filter associations
     foreach ($products as $dummyProduct) {
         foreach ($dummyProduct->getAssociations() as $association) {
             if ($association->hasProduct($product)) {
                 $associations[] = $association;
             }
         }
     }
     return $associations;
 }
 /**
  * @param ProductInterface         $product
  * @param AssociationTypeInterface $type
  *
  * @return array
  */
 protected function getAssociatedProductIds(ProductInterface $product, AssociationTypeInterface $type)
 {
     $productIds = [];
     $association = $product->getAssociationForType($type);
     if ($association) {
         foreach ($association->getProducts() as $product) {
             $productIds[] = $product->getId();
         }
     }
     return $productIds ?: [0];
 }
 function it_skips_a_product_when_there_is_nothing_to_update_with_localized_value($arrayConverter, $productRepository, $productBuilder, $productUpdater, $productFilter, $localizedConverter, ProductInterface $product, ConstraintViolationListInterface $violationList)
 {
     $productRepository->getIdentifierProperties()->willReturn(['sku']);
     $productRepository->findOneByIdentifier('tshirt')->willReturn(false);
     $this->setDecimalSeparator(',');
     $product->getId()->willReturn(42);
     $productBuilder->createProduct('tshirt', null)->willReturn($product);
     $originalData = ['sku' => 'tshirt', 'number' => '10.45'];
     $postConvertedData = $convertedData = ['sku' => [['locale' => null, 'scope' => null, 'data' => 'tshirt']], 'number' => [['locale' => null, 'scope' => null, 'data' => '10,45']]];
     $converterOptions = ['mapping' => ['family' => 'family', 'categories' => 'categories', 'groups' => 'groups'], 'default_values' => ['enabled' => true], 'with_associations' => false];
     $arrayConverter->convert($originalData, $converterOptions)->willReturn($convertedData);
     $postConvertedData['number'][0]['data'] = '10.45';
     $localizedConverter->convertLocalizedToDefaultValues($convertedData, ['decimal_separator' => ',', 'date_format' => 'Y-m-d'])->willReturn($postConvertedData);
     $localizedConverter->getViolations()->willReturn($violationList);
     $filteredData = ['number' => [['locale' => null, 'scope' => null, 'data' => '10.45']]];
     $productFilter->filter($product, $filteredData)->willReturn([]);
     $productUpdater->update($product, $filteredData)->shouldNotBeCalled();
     $this->process($originalData)->shouldReturn(null);
 }
 function it_generates_warning_message_if_variant_group_without_common_attribute_is_skipped($groupRepository, $productMassActionRepo, CustomGroupInterface $shoes, CustomGroupInterface $glasses, ProductInterface $product1, ProductInterface $product2)
 {
     $product1->getVariantGroup()->willReturn(null);
     $product2->getVariantGroup()->willReturn(null);
     $this->setObjectsToMassEdit([$product1, $product2]);
     $product1->getId()->willReturn(1);
     $product2->getId()->willReturn(2);
     $productMassActionRepo->findCommonAttributeIds([1, 2])->willReturn([42]);
     $groupRepository->getVariantGroupsByAttributeIds([42])->willReturn([$glasses]);
     $glasses->getId()->willReturn(100);
     $groupRepository->getVariantGroupsByIds([100], false)->willReturn([$shoes]);
     $shoes->getLabel()->willReturn('Shoes');
     $shoes->getCode()->willReturn('shoes');
     $groupRepository->countVariantGroups()->willReturn(2);
     $this->getFormOptions();
     $this->getWarningMessages()->shouldReturn([['key' => 'pim_enrich.mass_edit_action.add-to-variant-group.some_variant_groups_are_skipped', 'options' => ['%groups%' => 'Shoes [shoes]']]]);
 }
 /**
  * spl_object_hash for new product and id when product exists
  *
  * @param ProductInterface $product
  *
  * @return string
  */
 protected function getProductIdentifier(ProductInterface $product)
 {
     $identifier = $product->getId() ? $product->getId() : spl_object_hash($product);
     return $identifier;
 }
 /**
  * Search the number of indexed products
  *
  * @param ProductInterface $product
  *
  * @return int
  */
 public function countEditedProducts(ProductInterface $product)
 {
     return array_search($product->getId(), $this->objectSet) + 1;
 }
 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);
 }
 function it_adds_a_violation_when_validating_product_in_groups_with_non_unique_combination_of_axis_attributes($context, $productRepository, GroupInterface $tShirtVariantGroup, ProductInterface $redTShirtProduct, AttributeInterface $sizeAttribute, AttributeInterface $colorAttribute, ProductValueInterface $sizeProductValue, ProductValueInterface $colorProductValue, ProductInterface $redTShirtProduct2, UniqueVariantAxis $uniqueVariantAxisConstraint, ConstraintViolationBuilderInterface $violation)
 {
     $redTShirtProduct->getVariantGroup()->willReturn($tShirtVariantGroup);
     $tShirtVariantGroup->getId()->willReturn(1);
     $tShirtVariantGroup->getLabel()->willReturn('TShirts');
     $tShirtVariantGroup->getAxisAttributes()->willReturn([$sizeAttribute, $colorAttribute]);
     $sizeAttribute->getCode()->willReturn('size');
     $sizeAttribute->isBackendTypeReferenceData()->willReturn(true);
     $sizeAttribute->getReferenceDataName()->willReturn('ref_size');
     $colorAttribute->getCode()->willReturn('color');
     $colorAttribute->isBackendTypeReferenceData()->willReturn(true);
     $colorAttribute->getReferenceDataName()->willReturn('ref_color');
     $redTShirtProduct->getValue('size')->willReturn($sizeProductValue);
     $redTShirtProduct->getValue('color')->willReturn($colorProductValue);
     $redTShirtProduct->getId()->willReturn(1);
     $sizeProductValue->getData()->willReturn('XL');
     $sizeProductValue->getOption()->willReturn(null);
     $colorProductValue->getData()->willReturn('Red');
     $colorProductValue->getOption()->willReturn(null);
     $criteria = [['attribute' => $sizeAttribute, 'referenceData' => ['name' => 'ref_size', 'data' => 'XL']], ['attribute' => $colorAttribute, 'referenceData' => ['name' => 'ref_color', 'data' => 'Red']]];
     $productRepository->findAllForVariantGroup($tShirtVariantGroup, $criteria)->shouldBeCalled()->willReturn([$redTShirtProduct2]);
     $context->buildViolation('Group "%variant group%" already contains another product with values "%values%"', ['%variant group%' => 'TShirts', '%values%' => 'size: XL, color: Red'])->shouldBeCalled()->willReturn($violation);
     $this->validate($redTShirtProduct, $uniqueVariantAxisConstraint);
 }
 /**
  * {@inheritdoc}
  */
 public function findByProductAndOwnerIds(ProductInterface $product, array $ownerIds)
 {
     $qb = $this->createQueryBuilder('pa');
     $qb->join('pa.products', 'pap', Join::WITH, 'pap.id = :productId')->where($qb->expr()->in('pa.owner', $ownerIds))->setParameter(':productId', $product->getId());
     return $qb->getQuery()->getResult();
 }
 /**
  * Apply the query part to search for product where the completenesses
  * are missing. Apply only to the channel or product if provided.
  *
  * @param Builder          $productsQb
  * @param ProductInterface $product
  * @param ChannelInterface $channel
  */
 protected function applyFindMissingQuery(Builder $productsQb, ProductInterface $product = null, ChannelInterface $channel = null)
 {
     if (null !== $product) {
         $productsQb->field('_id')->equals($product->getId());
     } else {
         $combinations = $this->getChannelLocaleCombinations($channel);
         if (!empty($combinations)) {
             foreach ($combinations as $combination) {
                 $expr = new Expr();
                 $expr->field('normalizedData.completenesses.' . $combination)->exists(false);
                 $productsQb->addOr($expr);
             }
         }
     }
     $productsQb->field('family')->notEqual(null);
 }
 /**
  * @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());
 }