diff --git a/composer.json b/composer.json index 9cede4c..2ea254d 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "sylius/sylius": "dev-master", "ongr/elasticsearch-dsl": "^5.0", - "ongr/elasticsearch-bundle": "^5.0" + "ongr/elasticsearch-bundle": "^5.0", + "simple-bus/symfony-bridge": "^4.1" }, "require-dev": { "behat/behat": "^3.2", diff --git a/spec/Document/AttributeSpec.php b/spec/Document/AttributeSpec.php index 28a87bc..d98c7b2 100644 --- a/spec/Document/AttributeSpec.php +++ b/spec/Document/AttributeSpec.php @@ -2,6 +2,7 @@ namespace spec\Sylius\ElasticSearchPlugin\Document; +use ONGR\ElasticsearchBundle\Collection\Collection; use Sylius\ElasticSearchPlugin\Document\Attribute; use PhpSpec\ObjectBehavior; @@ -12,11 +13,11 @@ function it_is_initializable() $this->shouldHaveType(Attribute::class); } - function it_has_value() + function it_has_code() { - $this->setValue('red'); + $this->setCode('color'); - $this->getValue()->shouldReturn('red'); + $this->getCode()->shouldReturn('color'); } function it_has_name() diff --git a/spec/Document/AttributeValueSpec.php b/spec/Document/AttributeValueSpec.php new file mode 100644 index 0000000..8ae2ca1 --- /dev/null +++ b/spec/Document/AttributeValueSpec.php @@ -0,0 +1,38 @@ +shouldHaveType(AttributeValue::class); + } + + function it_has_value() + { + $this->setValue('Red'); + + $this->getValue()->shouldReturn('Red'); + } + + function it_has_attribute() + { + $attribute = new Attribute(); + $this->setAttribute($attribute); + + $this->getAttribute()->shouldReturn($attribute); + } + + function it_has_code() + { + $this->setCode('red'); + + $this->getCode()->shouldReturn('red'); + } +} diff --git a/spec/Document/ProductSpec.php b/spec/Document/ProductSpec.php index 31ab9d2..5124b3e 100644 --- a/spec/Document/ProductSpec.php +++ b/spec/Document/ProductSpec.php @@ -6,6 +6,7 @@ use Sylius\ElasticSearchPlugin\Document\Price; use Sylius\ElasticSearchPlugin\Document\Product; use PhpSpec\ObjectBehavior; +use Sylius\ElasticSearchPlugin\Document\TaxonCode; final class ProductSpec extends ObjectBehavior { @@ -57,18 +58,27 @@ function it_has_price() $this->getPrice()->shouldReturn($price); } - function it_has_taxon_code() + function it_has_main_taxon_code() { - $this->setTaxonCode('Tree'); + $taxonCode = new TaxonCode(); + $this->setMainTaxonCode($taxonCode); - $this->getTaxonCode()->shouldReturn('Tree'); + $this->getMainTaxonCode()->shouldReturn($taxonCode); + } + + function it_has_taxon_codes() + { + $taxonCodes = new Collection(); + $this->setTaxonCodes($taxonCodes); + + $this->getTaxonCodes()->shouldReturn($taxonCodes); } function it_has_attributes() { - $attributes = new Collection(); - $this->setAttributes($attributes); + $attributeValues = new Collection(); + $this->setAttributeValues($attributeValues); - $this->getAttributes()->shouldReturn($attributes); + $this->getAttributeValues()->shouldReturn($attributeValues); } } diff --git a/spec/Document/TaxonCodeSpec.php b/spec/Document/TaxonCodeSpec.php new file mode 100644 index 0000000..83d0f65 --- /dev/null +++ b/spec/Document/TaxonCodeSpec.php @@ -0,0 +1,22 @@ +shouldHaveType(TaxonCode::class); + } + + function it_has_value() + { + $this->setValue('mug'); + + $this->getValue()->shouldReturn('mug'); + } +} diff --git a/spec/EventListener/ProductPublisherSpec.php b/spec/EventListener/ProductPublisherSpec.php new file mode 100644 index 0000000..2bf64a8 --- /dev/null +++ b/spec/EventListener/ProductPublisherSpec.php @@ -0,0 +1,42 @@ +beConstructedWith($eventBus); + } + + function it_is_initializable() + { + $this->shouldHaveType(ProductPublisher::class); + } + + function it_publishes_product_event(MessageBus $eventBus, LifecycleEventArgs $event, ProductInterface $product) + { + $event->getEntity()->willReturn($product); + + $eventBus->handle(ProductCreated::occur($product->getWrappedObject()))->shouldBeCalled(); + + $this->postPersist($event); + } + + function it_does_not_publish_product_event_if_entity_is_not_a_product(MessageBus $eventBus, LifecycleEventArgs $event) + { + $event->getEntity()->willReturn(new \stdClass()); + + $eventBus->handle(Argument::any())->shouldNotBeCalled(); + + $this->postPersist($event); + } +} diff --git a/spec/Projection/ProductProjectorSpec.php b/spec/Projection/ProductProjectorSpec.php new file mode 100644 index 0000000..ba2597a --- /dev/null +++ b/spec/Projection/ProductProjectorSpec.php @@ -0,0 +1,78 @@ +beConstructedWith($manager, $factory); + } + + function it_is_initializable() + { + $this->shouldHaveType(ProductProjector::class); + } + + function it_saves_product_document_if_product_has_channel_defined( + Manager $manager, + ProductFactoryInterface $factory, + ProductInterface $product, + LocaleInterface $locale, + ChannelInterface $channel + ) { + $channel->getLocales()->willReturn(new ArrayCollection([$locale->getWrappedObject()])); + $product->getChannels()->willReturn(new ArrayCollection([$channel->getWrappedObject()])); + + $productDocument = new Product(); + $factory->createFromSyliusSimpleProductModel($product, $locale, $channel)->willReturn($productDocument); + + $manager->persist($productDocument)->shouldBeCalled(); + $manager->commit()->shouldBeCalled(); + + $this->handleProductCreated(ProductCreated::occur($product->getWrappedObject())); + } + + function it_does_not_save_product_document_if_product_has_not_channel_defined( + Manager $manager, + ProductFactoryInterface $factory, + ProductInterface $product + ) { + $product->getChannels()->willReturn(new ArrayCollection([])); + $factory->createFromSyliusSimpleProductModel(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); + + $manager->persist(Argument::any())->shouldNotBeCalled(); + $manager->commit()->shouldBeCalled(); + + $this->handleProductCreated(ProductCreated::occur($product->getWrappedObject())); + } + + function it_does_not_save_product_document_if_channel_has_not_locales_defined( + Manager $manager, + ProductFactoryInterface $factory, + ProductInterface $product, + ChannelInterface $channel + ) { + $channel->getLocales()->willReturn(new ArrayCollection([])); + $product->getChannels()->willReturn(new ArrayCollection([$channel->getWrappedObject()])); + + $factory->createFromSyliusSimpleProductModel(Argument::any(), Argument::any(), Argument::any())->shouldNotBeCalled(); + + $manager->persist(Argument::any())->shouldNotBeCalled(); + $manager->commit()->shouldBeCalled(); + + $this->handleProductCreated(ProductCreated::occur($product->getWrappedObject())); + } +} diff --git a/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php b/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php index 4284b5e..acba83f 100644 --- a/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php +++ b/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php @@ -25,7 +25,7 @@ function it_is_query_factory() function it_creates_query() { - $this->create(['taxon_code' => 'mugs'])->shouldBeLike(new TermQuery('taxon_code', 'mugs')); + $this->create(['taxon_code' => 'mugs'])->shouldBeLike(new TermQuery('main_taxon_code.value', 'mugs')); } function it_cannot_create_query_if_there_is_no_required_parameters() diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php index 40e09e1..32b8e91 100644 --- a/src/Controller/SearchController.php +++ b/src/Controller/SearchController.php @@ -12,8 +12,12 @@ namespace Sylius\ElasticSearchPlugin\Controller; use FOS\RestBundle\View\ConfigurableViewHandlerInterface; +use FOS\RestBundle\View\View; +use Sylius\ElasticSearchPlugin\Document\Product; +use Sylius\ElasticSearchPlugin\Search\Criteria\Criteria; use Sylius\ElasticSearchPlugin\Search\SearchEngineInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; /** * @author Arkadiusz Krakowiak @@ -42,9 +46,18 @@ public function __construct(ConfigurableViewHandlerInterface $restViewHandler, S /** * @param Request $request + * + * @return Response */ public function searchAction(Request $request) { + $content = $request->getContent(); + $criteria = Criteria::fromQueryParameters(Product::class, json_decode($content, true)); + $result = $this->searchEngine->match($criteria); + + $view = View::create($result); + + return $this->restViewHandler->handle($view); } } diff --git a/src/Document/Attribute.php b/src/Document/Attribute.php index 181af6b..c3bc094 100644 --- a/src/Document/Attribute.php +++ b/src/Document/Attribute.php @@ -23,13 +23,6 @@ final class Attribute */ private $name; - /** - * @var string - * - * @ElasticSearch\Property(type="text") - */ - private $value; - /** * @return string */ @@ -61,20 +54,4 @@ public function setName($name) { $this->name = $name; } - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * @param string $value - */ - public function setValue($value) - { - $this->value = $value; - } } diff --git a/src/Document/AttributeValue.php b/src/Document/AttributeValue.php new file mode 100644 index 0000000..75c4dc1 --- /dev/null +++ b/src/Document/AttributeValue.php @@ -0,0 +1,80 @@ +code; + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } + + /** + * @return Attribute + */ + public function getAttribute() + { + return $this->attribute; + } + + /** + * @param Attribute $attribute + */ + public function setAttribute(Attribute $attribute) + { + $this->attribute = $attribute; + } +} diff --git a/src/Document/Product.php b/src/Document/Product.php index 04a7c30..eb435b3 100644 --- a/src/Document/Product.php +++ b/src/Document/Product.php @@ -63,18 +63,25 @@ final class Product private $price; /** - * @var string + * @var TaxonCode * - * @ElasticSearch\Property(type="keyword") + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:TaxonCode") + */ + private $mainTaxonCode; + + /** + * @var Collection + * + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:TaxonCode", multiple=true) */ - private $taxonCode; + private $taxonCodes; /** * @var Collection * - * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:Attribute", multiple=true) + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:AttributeValue", multiple=true) */ - private $attributes; + private $attributeValues; /** * @var \DateTime @@ -85,7 +92,8 @@ final class Product public function __construct() { - $this->attributes = new Collection(); + $this->attributeValues = new Collection(); + $this->taxonCodes = new Collection(); } /** @@ -185,35 +193,51 @@ public function setPrice(Price $price) } /** - * @return string + * @return TaxonCode + */ + public function getMainTaxonCode() + { + return $this->mainTaxonCode; + } + + /** + * @param TaxonCode $mainTaxonCode + */ + public function setMainTaxonCode(TaxonCode $mainTaxonCode) + { + $this->mainTaxonCode = $mainTaxonCode; + } + + /** + * @return Collection */ - public function getTaxonCode() + public function getTaxonCodes() { - return $this->taxonCode; + return $this->taxonCodes; } /** - * @param string $taxonCode + * @param Collection $taxonCodes */ - public function setTaxonCode($taxonCode) + public function setTaxonCodes(Collection $taxonCodes) { - $this->taxonCode = $taxonCode; + $this->taxonCodes = $taxonCodes; } /** * @return Collection */ - public function getAttributes() + public function getAttributeValues() { - return $this->attributes; + return $this->attributeValues; } /** - * @param Collection $attributes + * @param Collection $attributeValues */ - public function setAttributes(Collection $attributes) + public function setAttributeValues(Collection $attributeValues) { - $this->attributes = $attributes; + $this->attributeValues = $attributeValues; } /** diff --git a/src/Document/TaxonCode.php b/src/Document/TaxonCode.php new file mode 100644 index 0000000..744a16d --- /dev/null +++ b/src/Document/TaxonCode.php @@ -0,0 +1,34 @@ +value = $value; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } +} diff --git a/src/Event/ProductCreated.php b/src/Event/ProductCreated.php new file mode 100644 index 0000000..d395d97 --- /dev/null +++ b/src/Event/ProductCreated.php @@ -0,0 +1,39 @@ +product = $product; + } + + /** + * @param ProductInterface $product + * + * @return self + */ + public static function occur(ProductInterface $product) + { + return new self($product); + } + + /** + * @return ProductInterface + */ + public function product() + { + return $this->product; + } +} diff --git a/src/EventListener/ProductPublisher.php b/src/EventListener/ProductPublisher.php new file mode 100644 index 0000000..7b6b5ce --- /dev/null +++ b/src/EventListener/ProductPublisher.php @@ -0,0 +1,35 @@ +eventBus = $eventBus; + } + + /** + * @param LifecycleEventArgs $event + */ + public function postPersist(LifecycleEventArgs $event) + { + $product = $event->getEntity(); + if ($product instanceof ProductInterface) { + $this->eventBus->handle(ProductCreated::occur($product)); + } + } +} diff --git a/src/Factory/ProductFactory.php b/src/Factory/ProductFactory.php new file mode 100644 index 0000000..65fc4c6 --- /dev/null +++ b/src/Factory/ProductFactory.php @@ -0,0 +1,99 @@ +isSimple()) { + throw new \InvalidArgumentException(sprintf( + 'Cannot create elastic search model from configurable product "%s" via this method.', + $syliusProduct->getCode() + )); + } + + /** @var ProductVariantInterface $productVariant */ + $productVariant = $syliusProduct->getVariants()->first(); + + /** @var ProductTranslationInterface|TranslationInterface $productTranslation */ + $productTranslation = $syliusProduct->getTranslation($locale->getCode()); + $channelPrice = $productVariant->getChannelPricingForChannel($channel); + $syliusProductAttributes = $syliusProduct->getAttributesByLocale( + $locale->getCode(), + $channel->getDefaultLocale()->getCode() + ); + $syliusProductTaxons = $syliusProduct->getProductTaxons(); + + $product = new Product(); + $price = new Price(); + $taxonCode = new TaxonCode(); + $taxonCode->setValue($syliusProduct->getMainTaxon()->getCode()); + + $price->setAmount($channelPrice->getPrice()); + $price->setCurrency($channel->getBaseCurrency()->getCode()); + + $product->setLocaleCode($locale->getCode()); + $product->setName($productTranslation->getName()); + $product->setDescription($productTranslation->getDescription()); + $product->setChannelCode($channel->getCode()); + $product->setPrice($price); + $product->setCode($syliusProduct->getCode()); + $product->setCreatedAt($syliusProduct->getCreatedAt()); + $product->setMainTaxonCode($taxonCode); + + $productTaxonCodes = []; + foreach ($syliusProductTaxons as $syliusProductTaxon) { + $productTaxonCode = new TaxonCode(); + $productTaxonCode->setValue($syliusProductTaxon->getTaxon()->getCode()); + $productTaxonCodes[] = $productTaxonCode; + } + $product->setTaxonCodes(new Collection($productTaxonCodes)); + + $productAttributeValues = []; + foreach ($syliusProductAttributes as $syliusProductAttributeValue) { + $productAttributeValue = new AttributeValue(); + $productAttributeValue->setCode($syliusProductAttributeValue->getCode()); + $productAttributeValue->setValue($syliusProductAttributeValue->getValue()); + + $attribute = new Attribute(); + $attribute->setCode($syliusProductAttributeValue->getAttribute()->getCode()); + $attribute->setName($syliusProductAttributeValue->getAttribute()->getName()); + $productAttributeValue->setAttribute($attribute); + + $productAttributeValues[] = $productAttributeValue; + } + $productAttributeValues = new Collection($productAttributeValues); + $product->setAttributeValues($productAttributeValues); + + return $product; + } +} diff --git a/src/Factory/ProductFactoryInterface.php b/src/Factory/ProductFactoryInterface.php new file mode 100644 index 0000000..01281ec --- /dev/null +++ b/src/Factory/ProductFactoryInterface.php @@ -0,0 +1,29 @@ +manager = $manager; + $this->productDocumentFactory = $productDocumentFactory; + } + + /** + * @param ProductCreated $event + */ + public function handleProductCreated(ProductCreated $event) + { + $product = $event->product(); + $channels = $product->getChannels(); + + /** @var ChannelInterface $channel */ + foreach ($channels as $channel) { + $locales = $channel->getLocales(); + foreach ($locales as $locale) { + $productDocument = $this->productDocumentFactory->createFromSyliusSimpleProductModel( + $product, + $locale, + $channel + ); + + $this->manager->persist($productDocument); + } + } + + $this->manager->commit(); + } +} diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index baffc93..f7c4c70 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -13,5 +13,16 @@ + + + + + + + + + + + diff --git a/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php b/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php index f029e9c..326348a 100644 --- a/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php +++ b/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php @@ -19,6 +19,6 @@ public function create(array $parameters = []) throw new MissingQueryParameterException('taxon_code', get_class($this)); } - return new TermQuery('taxon_code', strtolower($parameters['taxon_code'])); + return new TermQuery('main_taxon_code.value', strtolower($parameters['taxon_code'])); } } diff --git a/tests/Application/app/AppKernel.php b/tests/Application/app/AppKernel.php index 1abd685..60c2617 100644 --- a/tests/Application/app/AppKernel.php +++ b/tests/Application/app/AppKernel.php @@ -19,6 +19,8 @@ public function registerBundles() new \FOS\OAuthServerBundle\FOSOAuthServerBundle(), // Required by SyliusAdminApiBundle new \Sylius\Bundle\AdminApiBundle\SyliusAdminApiBundle(), new \ONGR\ElasticsearchBundle\ONGRElasticsearchBundle(), + new \SimpleBus\SymfonyBridge\SimpleBusCommandBusBundle(), + new \SimpleBus\SymfonyBridge\SimpleBusEventBusBundle(), ]); } diff --git a/tests/Behat/Context/Setup/ProductContext.php b/tests/Behat/Context/Setup/ProductContext.php index c62c6f1..6c5512a 100644 --- a/tests/Behat/Context/Setup/ProductContext.php +++ b/tests/Behat/Context/Setup/ProductContext.php @@ -16,6 +16,7 @@ use ONGR\ElasticsearchBundle\Service\Manager; use Sylius\ElasticSearchPlugin\Document\Price; use Sylius\ElasticSearchPlugin\Document\Product; +use Sylius\ElasticSearchPlugin\Document\TaxonCode; final class ProductContext implements Context { @@ -37,9 +38,18 @@ public function __construct(Manager $manager) */ public function theStoreHasAboutMugsAndStickers($mugsNumber, $stickersNumber, $booksNumber) { - $this->generateProductsInTaxon($mugsNumber, 'mugs'); - $this->generateProductsInTaxon($stickersNumber, 'stickers'); - $this->generateProductsInTaxon($booksNumber, 'books'); + $mugsTaxonCode = new TaxonCode(); + $mugsTaxonCode->setValue('mugs'); + + $stickersTaxonCode = new TaxonCode(); + $stickersTaxonCode->setValue('stickers'); + + $booksTaxonCode = new TaxonCode(); + $booksTaxonCode->setValue('books'); + + $this->generateProductsInTaxon($mugsNumber, $mugsTaxonCode); + $this->generateProductsInTaxon($stickersNumber, $stickersTaxonCode); + $this->generateProductsInTaxon($booksNumber, $booksTaxonCode); } /** @@ -57,13 +67,13 @@ public function storeHasAProductPricedAt($productName, $price = 100, $channelCod /** * @param int $howMany - * @param string $taxonCode + * @param TaxonCode $taxonCode */ - private function generateProductsInTaxon($howMany, $taxonCode) + private function generateProductsInTaxon($howMany, TaxonCode $taxonCode) { for ($i = 0; $i < $howMany; $i++) { $product = new Product(); - $product->setTaxonCode($taxonCode); + $product->setMainTaxonCode($taxonCode); $product->setCode(uniqid()); $this->manager->persist($product); } diff --git a/tests/Event/ProductCreatedTest.php b/tests/Event/ProductCreatedTest.php new file mode 100644 index 0000000..65246e8 --- /dev/null +++ b/tests/Event/ProductCreatedTest.php @@ -0,0 +1,21 @@ +prophesize(ProductInterface::class); + $event = ProductCreated::occur($product->reveal()); + + $this->assertEquals($product->reveal(), $event->product()); + } +} diff --git a/tests/Factory/ProductFactoryTest.php b/tests/Factory/ProductFactoryTest.php new file mode 100644 index 0000000..f0b2668 --- /dev/null +++ b/tests/Factory/ProductFactoryTest.php @@ -0,0 +1,158 @@ +create(); + + $this->assertEquals(null, $product->getCode()); + $this->assertEquals(null, $product->getName()); + $this->assertEquals(null, $product->getLocaleCode()); + $this->assertEquals(new Collection, $product->getAttributeValues()); + $this->assertEquals(null, $product->getPrice()); + $this->assertEquals(null, $product->getChannelCode()); + $this->assertEquals(null, $product->getCreatedAt()); + $this->assertEquals(null, $product->getDescription()); + $this->assertEquals(new Collection, $product->getTaxonCodes()); + } + + /** + * @test + */ + public function it_creates_product_document_from_sylius_product_model() + { + $createdAt = \DateTime::createFromFormat(\DateTime::W3C, '2017-04-18T16:12:55+02:00'); + $syliusProductAttributeValue = new ProductAttributeValue(); + $syliusProductAttribute = new ProductAttribute(); + $syliusProductAttribute->setCurrentLocale('en_US'); + $syliusProductAttribute->setCode('red'); + $syliusProductAttribute->setName('Color red'); + $syliusProductAttributeValue->setLocaleCode('en_US'); + $syliusProductAttribute->setType(TextAttributeType::TYPE); + $syliusProductAttribute->setStorageType(TextAttributeType::TYPE); + $syliusProductAttributeValue->setAttribute($syliusProductAttribute); + $syliusProductAttributeValue->setValue('red'); + + $syliusTaxon = new Taxon(); + $syliusTaxon->setCode('tree'); + $syliusProductTaxon = new ProductTaxon(); + + $syliusLocale = new Locale(); + $syliusLocale->setCode('en_US'); + + $syliusProduct = new SyliusProduct(); + $syliusProductVariant = new ProductVariant(); + $channelPrice = new ChannelPricing(); + $syliusChannel = new Channel(); + $currency = new Currency(); + $currency->setCode('USD'); + + $syliusProductTaxon->setProduct($syliusProduct); + $syliusProductTaxon->setTaxon($syliusTaxon); + $channelPrice->setPrice(1000); + $channelPrice->setChannelCode('mobile'); + + $syliusChannel->setCode('mobile'); + $syliusChannel->setDefaultLocale($syliusLocale); + $syliusChannel->addLocale($syliusLocale); + $syliusChannel->addCurrency($currency); + $syliusChannel->setBaseCurrency($currency); + + $syliusProductVariant->addChannelPricing($channelPrice); + $syliusProduct->addVariant($syliusProductVariant); + $syliusProduct->addChannel($syliusChannel); + $syliusProduct->setMainTaxon($syliusTaxon); + $syliusProduct->addProductTaxon($syliusProductTaxon); + $syliusProduct->setCreatedAt($createdAt); + $syliusProduct->setCurrentLocale('en_US'); + $syliusProduct->setName('Banana'); + $syliusProduct->setDescription('Lorem ipsum'); + $syliusProduct->setCode('banana'); + $syliusProduct->addAttribute($syliusProductAttributeValue); + + $factory = new ProductFactory(); + /** @var Product $product */ + $product = $factory->createFromSyliusSimpleProductModel( + $syliusProduct, + $syliusLocale, + $syliusChannel + ); + + $taxonCode = new TaxonCode(); + $taxonCode->setValue('tree'); + + $productTaxonCode = new TaxonCode(); + $productTaxonCode->setValue('tree'); + + $productAttribute = new Attribute(); + $productAttribute->setCode('red'); + $productAttribute->setName('Color red'); + + $productAttributeValue = new AttributeValue(); + $productAttributeValue->setValue('red'); + $productAttributeValue->setCode('red'); + $productAttributeValue->setAttribute($productAttribute); + + $this->assertEquals('banana', $product->getCode()); + $this->assertEquals('Banana', $product->getName()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals( + new Collection([ + $productAttributeValue + ]), + $product->getAttributeValues() + ); + $this->assertEquals(1000, $product->getPrice()->getAmount()); + $this->assertEquals('USD', $product->getPrice()->getCurrency()); + $this->assertEquals('en_US', $product->getLocaleCode()); + $this->assertEquals('mobile', $product->getChannelCode()); + $this->assertEquals($createdAt, $product->getCreatedAt()); + $this->assertEquals('Lorem ipsum', $product->getDescription()); + $this->assertEquals($taxonCode, $product->getMainTaxonCode()); + $this->assertEquals(new Collection([$productTaxonCode]), $product->getTaxonCodes()); + } + + /** + * @test + * + * @expectedException \InvalidArgumentException + */ + public function it_cannot_create_product_document_from_configurable_product() + { + $factory = new ProductFactory(); + + $syliusProduct = new SyliusProduct(); + $syliusProduct->addVariant(new ProductVariant()); + $syliusProduct->addVariant(new ProductVariant()); + $syliusLocale = new Locale(); + $syliusChannel = new Channel(); + + $factory->createFromSyliusSimpleProductModel($syliusProduct, $syliusLocale, $syliusChannel); + } +}