Skip to content
This repository has been archived by the owner on Jan 11, 2019. It is now read-only.

Synchronize images paths #20

Merged
merged 2 commits into from
Jul 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions src/Attribute/ImageAttributeProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace Sylake\SyliusConsumerPlugin\Attribute;

use Sylake\SyliusConsumerPlugin\Model\Attribute;
use Sylius\Component\Core\Model\ProductImageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

final class ImageAttributeProcessor implements AttributeProcessorInterface
{
/** @var FactoryInterface */
private $productImageFactory;

/** @var RepositoryInterface */
private $productImageRepository;

/** @var string */
private $imageAttribute;

public function __construct(
FactoryInterface $productImageFactory,
RepositoryInterface $productImageRepository,
string $imageAttribute
) {
$this->productImageFactory = $productImageFactory;
$this->productImageRepository = $productImageRepository;
$this->imageAttribute = $imageAttribute;
}

/** {@inheritdoc} */
public function process(ProductInterface $product, Attribute $attribute): void
{
if (!$this->supports($attribute)) {
return;
}

foreach ($product->getImagesByType('akeneo') as $productImage) {
$product->removeImage($productImage);
}

if (null === $attribute->data()) {
return;
}

/** @var ProductImageInterface|null $image */
$productImage = $this->productImageRepository->findOneBy([
'owner' => $product,
'type' => 'akeneo',
'path' => $attribute->data(),
]);

if (null === $productImage) {
/** @var ProductImageInterface $productImage */
$productImage = $this->productImageFactory->createNew();
$productImage->setType('akeneo');
$productImage->setPath($attribute->data());
}

$product->addImage($productImage);
}

private function supports(Attribute $attribute): bool
{
return $this->imageAttribute === $attribute->attribute() && (null === $attribute->data() || is_string($attribute->data()));
}
}
1 change: 1 addition & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function getConfigTreeBuilder()
->scalarNode('name_attribute')->defaultValue('name')->end()
->scalarNode('description_attribute')->defaultValue('description')->end()
->scalarNode('price_attribute')->defaultValue('price')->end()
->scalarNode('image_attribute')->defaultValue('images')->end()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document this config.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted in #21

->end()
->end()
->end()
Expand Down
4 changes: 4 additions & 0 deletions src/DependencyInjection/SylakeSyliusConsumerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public function load(array $config, ContainerBuilder $container)
'sylake_sylius_consumer.denormalizer.product.price_attribute',
$config['denormalizer']['product']['price_attribute']
);
$container->setParameter(
'sylake_sylius_consumer.denormalizer.product.image_attribute',
$config['denormalizer']['product']['image_attribute']
);
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
<argument>%sylake_sylius_consumer.denormalizer.product.price_attribute%</argument>
</service>
</argument>
<argument type="service">
<service class="Sylake\SyliusConsumerPlugin\Attribute\ImageAttributeProcessor">
<argument type="service" id="sylius.factory.product_image" />
<argument type="service" id="sylius.repository.product_image" />
<argument>%sylake_sylius_consumer.denormalizer.product.image_attribute%</argument>
</service>
</argument>
<argument type="service">
<service class="Sylake\SyliusConsumerPlugin\Attribute\UnitAttributeProcessor">
<argument type="service" id="sylake_sylius_consumer.attribute.attribute_value_provider" />
Expand Down
1 change: 1 addition & 0 deletions tests/DependencyInjection/ExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function it_adds_product_denormalization_parameters_by_default()
$this->assertContainerBuilderHasParameter('sylake_sylius_consumer.denormalizer.product.name_attribute', 'name');
$this->assertContainerBuilderHasParameter('sylake_sylius_consumer.denormalizer.product.description_attribute', 'description');
$this->assertContainerBuilderHasParameter('sylake_sylius_consumer.denormalizer.product.price_attribute', 'price');
$this->assertContainerBuilderHasParameter('sylake_sylius_consumer.denormalizer.product.image_attribute', 'images');
}

/**
Expand Down
118 changes: 118 additions & 0 deletions tests/Functional/ProductSynchronizationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PHPUnit\Framework\Assert;
use Sylius\Bundle\FixturesBundle\Fixture\FixtureInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductImageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Model\TaxonInterface;
Expand Down Expand Up @@ -185,6 +186,123 @@ public function it_updates_an_existing_product_with_basic_product_information()
Assert::assertFalse($product->isEnabled());
}

/**
* @test
*/
public function it_adds_a_new_product_with_images()
{
$this->consumer->execute(new AMQPMessage('{
"type": "akeneo_product_updated",
"payload": {
"identifier": "AKNTS_BPXS",
"family": "tshirts",
"groups": [],
"variant_group": "akeneo_tshirt",
"categories": ["goodies", "tshirts"],
"enabled": true,
"values": {
"sku": [{"locale": null, "scope": null, "data": "AKNTS_BPXS"}],
"clothing_size": [{"locale": null, "scope": null, "data": "xs"}],
"main_color": [{"locale": null, "scope": null, "data": "black"}],
"name": [{"locale": null, "scope": null, "data": "Akeneo T-Shirt black and purple with short sleeve"}],
"secondary_color": [{"locale": null, "scope": null, "data": "purple"}],
"tshirt_materials": [{"locale": null, "scope": null, "data": "cotton"}],
"tshirt_style": [{"locale": null, "scope": null, "data": ["crewneck", "short_sleeve"]}],
"price": [{"locale": null, "scope": null, "data": [{"amount": 10, "currency": "EUR"}, {"amount": 14, "currency": "USD"}]}],
"description": [{"locale": "en_US", "scope": "mobile", "data": "T-Shirt description"}],
"picture": [{"locale": null, "scope": null, "data": null}],
"images": [{"locale": null, "scope": null, "data": "8\/7\/5\/3\/8753d08e04e7ecdda77ef77573cd42bbfb029dcb_image.jpg"}]
},
"created": "2017-04-18T16:12:55+02:00",
"updated": "2017-04-18T16:12:55+02:00",
"associations": {"SUBSTITUTION": {"groups": [], "products": ["AKNTS_WPXS", "AKNTS_PBXS", "AKNTS_PWXS"]}}
},
"recordedOn": "2017-05-22 10:13:34"
}'));

/** @var ProductInterface|null $product */
$product = $this->productRepository->findOneBy(['code' => 'AKNTS_BPXS']);

Assert::assertNotNull($product);

$akeneoProductImages = $product->getImagesByType('akeneo')->toArray();
$akeneoProductImage = current($akeneoProductImages);

Assert::assertNotFalse($akeneoProductImage);
Assert::assertSame('8/7/5/3/8753d08e04e7ecdda77ef77573cd42bbfb029dcb_image.jpg', $akeneoProductImage->getPath());
Assert::assertSame('akeneo', $akeneoProductImage->getType());
}

/**
* @test
*/
public function it_updates_an_existing_product_with_images()
{
$this->consumer->execute(new AMQPMessage('{
"type": "akeneo_product_updated",
"payload": {
"identifier": "AKNTS_BPXS",
"family": "tshirts",
"groups": [],
"variant_group": "akeneo_tshirt",
"categories": ["goodies", "tshirts"],
"enabled": true,
"values": {
"sku": [{"locale": null, "scope": null, "data": "AKNTS_BPXS"}],
"clothing_size": [{"locale": null, "scope": null, "data": "xs"}],
"main_color": [{"locale": null, "scope": null, "data": "black"}],
"name": [{"locale": null, "scope": null, "data": "Akeneo T-Shirt black and purple with short sleeve"}],
"secondary_color": [{"locale": null, "scope": null, "data": "purple"}],
"tshirt_materials": [{"locale": null, "scope": null, "data": "cotton"}],
"tshirt_style": [{"locale": null, "scope": null, "data": ["crewneck", "short_sleeve"]}],
"price": [{"locale": null, "scope": null, "data": [{"amount": 10, "currency": "EUR"}, {"amount": 14, "currency": "USD"}]}],
"description": [{"locale": "en_US", "scope": "mobile", "data": "T-Shirt description"}],
"picture": [{"locale": null, "scope": null, "data": null}],
"images": [{"locale": null, "scope": null, "data": "8\/7\/5\/3\/8753d08e04e7ecdda77ef77573cd42bbfb029dcb_image.jpg"}]
},
"created": "2017-04-18T16:12:55+02:00",
"updated": "2017-04-18T16:12:55+02:00",
"associations": {"SUBSTITUTION": {"groups": [], "products": ["AKNTS_WPXS", "AKNTS_PBXS", "AKNTS_PWXS"]}}
},
"recordedOn": "2017-05-22 10:13:34"
}'));

$this->consumer->execute(new AMQPMessage('{
"type": "akeneo_product_updated",
"payload": {
"identifier": "AKNTS_BPXS",
"family": "tshirts",
"groups": [],
"variant_group": "akeneo_tshirt",
"categories": ["goodies", "tshirts"],
"enabled": false,
"values": {
"sku": [{"locale": null, "scope": null, "data": "AKNTS_BPXS"}],
"clothing_size": [{"locale": null, "scope": null, "data": "xs"}],
"main_color": [{"locale": null, "scope": null, "data": "black"}],
"name": [{"locale": null, "scope": null, "data": "Akeneo T-Shirt black and purple with short sleeve (updated)"}],
"secondary_color": [{"locale": null, "scope": null, "data": "purple"}],
"tshirt_materials": [{"locale": null, "scope": null, "data": "cotton"}],
"tshirt_style": [{"locale": null, "scope": null, "data": ["crewneck", "short_sleeve"]}],
"price": [{"locale": null, "scope": null, "data": [{"amount": 10, "currency": "EUR"}, {"amount": 14, "currency": "USD"}]}],
"description": [{"locale": "en_US", "scope": "mobile", "data": "T-Shirt description (updated)"}],
"picture": [{"locale": null, "scope": null, "data": null}],
"images": [{"locale": null, "scope": null, "data": null}]
},
"created": "2017-04-18T16:12:58+02:00",
"updated": "2017-04-18T16:12:55+02:00",
"associations": {"SUBSTITUTION": {"groups": [], "products": ["AKNTS_WPXS", "AKNTS_PBXS", "AKNTS_PWXS"]}}
},
"recordedOn": "2017-05-22 10:13:34"
}'));

/** @var ProductInterface|null $product */
$product = $this->productRepository->findOneBy(['code' => 'AKNTS_BPXS']);

Assert::assertNotNull($product);
Assert::assertSame([], $product->getImagesByType('akeneo')->toArray());
}

/**
* @test
*/
Expand Down