diff --git a/src/Entity/ProductConfiguration.php b/src/Entity/ProductConfiguration.php index 4e1cbf86..c7d1a0ff 100644 --- a/src/Entity/ProductConfiguration.php +++ b/src/Entity/ProductConfiguration.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Sylius\Component\Core\Model\ChannelInterface; use Sylius\Component\Resource\Model\ResourceInterface; /** @@ -75,10 +76,27 @@ class ProductConfiguration implements ResourceInterface */ private $regenerateUrlRewrites; + /** + * @var bool + * @ORM\Column(name="enable_imported_products", type="boolean", options={"default" = 0}) + */ + private $enableImportedProducts = false; + + /** + * @var ChannelInterface[]|Collection + * @ORM\ManyToMany (targetEntity=ChannelInterface::class) + * @ORM\JoinTable(name="akeneo_product_configuration_channels", + * joinColumns={@ORM\JoinColumn(name="product_configuration_id", referencedColumnName="id")}, + * inverseJoinColumns={@ORM\JoinColumn(name="channel_id", referencedColumnName="id", unique=true)} + * ) + */ + private $channelsToEnable; + public function __construct() { $this->akeneoImageAttributes = new ArrayCollection(); $this->productImagesMapping = new ArrayCollection(); + $this->channelsToEnable = new ArrayCollection(); } public function getId(): ?int @@ -205,4 +223,28 @@ public function setAkeneoEnabledChannelsAttribute(?string $akeneoEnabledChannels return $this; } + + public function getEnableImportedProducts(): bool + { + return $this->enableImportedProducts; + } + + public function setEnableImportedProducts(bool $enableImportedProducts): self + { + $this->enableImportedProducts = $enableImportedProducts; + + return $this; + } + + public function getChannelsToEnable(): Collection + { + return $this->channelsToEnable; + } + + public function setChannelsToEnable(Collection $channelsToEnable): self + { + $this->channelsToEnable = $channelsToEnable; + + return $this; + } } diff --git a/src/Form/Type/ProductConfigurationType.php b/src/Form/Type/ProductConfigurationType.php index 5eb7dcf2..41661ec9 100644 --- a/src/Form/Type/ProductConfigurationType.php +++ b/src/Form/Type/ProductConfigurationType.php @@ -22,6 +22,16 @@ final class ProductConfigurationType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder + ->add('enableImportedProducts', CheckboxType::class, [ + 'label' => 'sylius.ui.admin.akeneo.products.enable_imported_products', + 'required' => false, + ]) + ->add('channelsToEnable', \Sylius\Bundle\ChannelBundle\Form\Type\ChannelChoiceType::class, [ + 'label' => 'sylius.ui.admin.akeneo.products.enable_imported_products_channels', + 'required' => false, + 'multiple' => true, + 'expanded' => true, + ]) ->add('akeneoPriceAttribute', AttributeCodeChoiceType::class, [ 'label' => 'sylius.ui.admin.akeneo.products.akeneo_price_attribute', ]) diff --git a/src/Migrations/Version20210506132536.php b/src/Migrations/Version20210506132536.php new file mode 100644 index 00000000..89a9abd5 --- /dev/null +++ b/src/Migrations/Version20210506132536.php @@ -0,0 +1,52 @@ +addSql('CREATE TABLE akeneo_product_configuration_channels ( + product_configuration_id INT NOT NULL, + channel_id INT NOT NULL, + INDEX IDX_E6A56A05FD7F4924 (product_configuration_id), + UNIQUE INDEX UNIQ_E6A56A0572F5A1AA (channel_id), + PRIMARY KEY( + product_configuration_id, channel_id + ) + ) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE + akeneo_product_configuration_channels + ADD + CONSTRAINT FK_E6A56A05FD7F4924 FOREIGN KEY (product_configuration_id) REFERENCES akeneo_api_configuration_product (id)'); + $this->addSql('ALTER TABLE + akeneo_product_configuration_channels + ADD + CONSTRAINT FK_E6A56A0572F5A1AA FOREIGN KEY (channel_id) REFERENCES sylius_channel (id)'); + $this->addSql('ALTER TABLE + akeneo_api_configuration_product + ADD + enable_imported_products TINYINT(1) DEFAULT \'0\' NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE akeneo_product_configuration_channels'); + $this->addSql('ALTER TABLE akeneo_api_configuration_product DROP enable_imported_products'); + } +} diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index 0ed007c3..e4b0c0aa 100644 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -77,12 +77,16 @@ sylius: sylius_attribute: Sylius attributes akeneo_attribute: Akeneo attributes regenerate_url_rewrites: Regenerate url rewrites + enable_imported_products: Enable all imported products for all channels + enable_imported_products_help: Checking this box overrides the configuration "Akeneo enabled channels attribute" + enable_imported_products_channels: Channels on which imported products will be enabled attributes: title: Attributes subtitle: Attributes configuration medias: medias: Medias reference_entity: 'Reference Entity' + akeneo: ui: attribute_type_mappings: 'Akeneo Attribute Type Mappings' diff --git a/src/Resources/translations/messages.fr.yml b/src/Resources/translations/messages.fr.yml index bd8f6f3a..59f09775 100644 --- a/src/Resources/translations/messages.fr.yml +++ b/src/Resources/translations/messages.fr.yml @@ -77,6 +77,9 @@ sylius: sylius_attribute: Attribut Sylius akeneo_attribute: Attribut Akeneo regenerate_url_rewrites: Regenerate url rewrites + enable_imported_products: Activer les produits sur tous les canaux à l'import + enable_imported_products_help: Cocher cette case écrasera la configuration "Attribut Akeneo des channels actifs". + enable_imported_products_channels: Canaux sur lesquelles les produits importés seront activés attributes: title: Attributs subtitle: Configuration des attributs diff --git a/src/Resources/views/Admin/AkeneoConnector/products_configuration.html.twig b/src/Resources/views/Admin/AkeneoConnector/products_configuration.html.twig index c2ddad9c..967ff025 100644 --- a/src/Resources/views/Admin/AkeneoConnector/products_configuration.html.twig +++ b/src/Resources/views/Admin/AkeneoConnector/products_configuration.html.twig @@ -18,8 +18,18 @@ {% endblock %}
{{ form_start(form, {'attr': {'class': 'ui loadable form', 'novalidate': 'novalidate'}}) }} +
+
+ {{ 'sylius.ui.admin.akeneo.products.enable_imported_products_help'|trans }} + {{ form_row(form.enableImportedProducts) }} +
+
+ {{ form_row(form.channelsToEnable) }} +
+ {{ form_row(form.akeneoEnabledChannelsAttribute) }} +
+
{{ form_row(form.akeneoPriceAttribute) }} - {{ form_row(form.akeneoEnabledChannelsAttribute) }}
{{ form_row(form.importMediaFiles) }}
diff --git a/src/Service/ProductChannelEnabler.php b/src/Service/ProductChannelEnabler.php index 474b9057..8afbb1ef 100644 --- a/src/Service/ProductChannelEnabler.php +++ b/src/Service/ProductChannelEnabler.php @@ -14,7 +14,7 @@ use Synolia\SyliusAkeneoPlugin\Repository\ChannelRepository; use Synolia\SyliusAkeneoPlugin\Repository\ProductConfigurationRepository; -final class ProductChannelEnabler +final class ProductChannelEnabler implements ProductChannelEnablerInterface { /** @var \Synolia\SyliusAkeneoPlugin\Repository\ChannelRepository */ private $channelRepository; @@ -32,7 +32,7 @@ public function __construct( ChannelRepository $channelRepository, ProductConfigurationRepository $productConfigurationRepository, LoggerInterface $akeneoLogger, - EntityManagerInterface $entityManager + EntityManagerInterface $entityManager ) { $this->channelRepository = $channelRepository; $this->productConfigurationRepository = $productConfigurationRepository; @@ -43,32 +43,21 @@ public function __construct( public function enableChannelForProduct(ProductInterface $product, array $resource): void { try { - $enabledChannels = $this->getEnabledChannelsAttributeData($product, $resource); + $productConfiguration = $this->getProductConfiguration(); $this->entityManager->beginTransaction(); //Disable the product for all channels $product->getChannels()->clear(); - foreach ($enabledChannels as $enabledChannel) { - $channel = $this->channelRepository->findOneBy(['code' => $enabledChannel]); - if (!$channel instanceof ChannelInterface) { - $this->logger->warning(\sprintf( - 'Channel "%s" could not be activated for product "%s" because the channel was not found in the database.', - $enabledChannel, - $product->getCode() - )); - - continue; - } - - $product->addChannel($channel); - $this->logger->info(\sprintf( - 'Enabled channel "%s" for product "%s"', - $channel->getCode(), - $product->getCode() - )); + if ($productConfiguration->getEnableImportedProducts()) { + $this->handleBySyliusConfiguration($productConfiguration, $product); + + return; } + + $this->handleByAkeneoEnabledChannelsAttribute($productConfiguration, $product, $resource); + $this->entityManager->flush(); $this->entityManager->commit(); } catch (\Throwable $throwable) { @@ -80,7 +69,17 @@ public function enableChannelForProduct(ProductInterface $product, array $resour } } - public function getEnabledChannelsAttributeData(ProductInterface $product, array $resource): array + private function addProductToChannel(ProductInterface $product, ChannelInterface $channel): void + { + $product->addChannel($channel); + $this->logger->info(\sprintf( + 'Enabled channel "%s" for product "%s"', + $channel->getCode(), + $product->getCode() + )); + } + + private function getProductConfiguration(): ProductConfiguration { /** @var \Synolia\SyliusAkeneoPlugin\Entity\ProductConfiguration|null $productConfiguration */ $productConfiguration = $this->productConfigurationRepository->findOneBy([]); @@ -89,6 +88,14 @@ public function getEnabledChannelsAttributeData(ProductInterface $product, array throw new NoProductConfigurationException('Product Configuration is not configured in BO.'); } + return $productConfiguration; + } + + private function getEnabledChannelsAttributeData( + ProductConfiguration $productConfiguration, + ProductInterface $product, + array $resource + ): array { if (null === $productConfiguration->getAkeneoEnabledChannelsAttribute()) { throw new NoProductConfigurationException('Product configuration -> Enabled channels is not configured in BO.'); } @@ -107,4 +114,45 @@ public function getEnabledChannelsAttributeData(ProductInterface $product, array throw new NoAttributeResourcesException(\sprintf('Enabled channels attribute not found for product "%s".', $product->getCode())); } + + private function handleByAkeneoEnabledChannelsAttribute( + ProductConfiguration $productConfiguration, + ProductInterface $product, + array $resource + ): void { + $enabledChannels = $this->getEnabledChannelsAttributeData($productConfiguration, $product, $resource); + + foreach ($enabledChannels as $enabledChannel) { + $channel = $this->channelRepository->findOneBy(['code' => $enabledChannel]); + if (!$channel instanceof ChannelInterface) { + $this->logger->warning(\sprintf( + 'Channel "%s" could not be activated for product "%s" because the channel was not found in the database.', + $enabledChannel, + $product->getCode() + )); + + continue; + } + + $this->addProductToChannel($product, $channel); + } + } + + private function handleBySyliusConfiguration(ProductConfiguration $productConfiguration, ProductInterface $product): void + { + $channels = $productConfiguration->getChannelsToEnable(); + + if (0 < $channels->count()) { + $channels = $this->channelRepository->findAll(); + } + + $this->addProductToChannels($product, $channels); + } + + private function addProductToChannels(ProductInterface $product, iterable $channels): void + { + foreach ($channels as $channel) { + $this->addProductToChannel($product, $channel); + } + } } diff --git a/src/Service/ProductChannelEnablerInterface.php b/src/Service/ProductChannelEnablerInterface.php new file mode 100644 index 00000000..8026db1f --- /dev/null +++ b/src/Service/ProductChannelEnablerInterface.php @@ -0,0 +1,12 @@ +productRepository = $productRepository; diff --git a/src/Task/ProductModel/EnableDisableProductModelsTask.php b/src/Task/ProductModel/EnableDisableProductModelsTask.php index 4d179292..840ae71e 100644 --- a/src/Task/ProductModel/EnableDisableProductModelsTask.php +++ b/src/Task/ProductModel/EnableDisableProductModelsTask.php @@ -13,7 +13,7 @@ use Synolia\SyliusAkeneoPlugin\Payload\Product\ProductPayload; use Synolia\SyliusAkeneoPlugin\Payload\ProductModel\ProductModelPayload; use Synolia\SyliusAkeneoPlugin\Repository\ProductRepository; -use Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnabler; +use Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnablerInterface; use Synolia\SyliusAkeneoPlugin\Task\AkeneoTaskInterface; final class EnableDisableProductModelsTask implements AkeneoTaskInterface @@ -24,7 +24,7 @@ final class EnableDisableProductModelsTask implements AkeneoTaskInterface /** @var \Psr\Log\LoggerInterface */ private $logger; - /** @var \Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnabler */ + /** @var ProductChannelEnablerInterface */ private $productChannelEnabler; /** @var \Doctrine\ORM\EntityManagerInterface */ @@ -33,7 +33,7 @@ final class EnableDisableProductModelsTask implements AkeneoTaskInterface public function __construct( ProductRepository $productRepository, LoggerInterface $akeneoLogger, - ProductChannelEnabler $productChannelEnabler, + ProductChannelEnablerInterface $productChannelEnabler, EntityManagerInterface $entityManager ) { $this->productRepository = $productRepository;