Skip to content

Commit

Permalink
allow channel selection to enabled them on product import
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGrimmChester committed Jul 23, 2021
1 parent 98537de commit 94a52a0
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 29 deletions.
42 changes: 42 additions & 0 deletions src/Entity/ProductConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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<int, ChannelInterface>
* @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
Expand Down Expand Up @@ -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;
}
}
10 changes: 10 additions & 0 deletions src/Form/Type/ProductConfigurationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
])
Expand Down
52 changes: 52 additions & 0 deletions src/Migrations/Version20210506132536.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Synolia\SyliusAkeneoPlugin\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210506132536 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add settings table to configure the channels to be enabled on products when importing them.';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->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');
}
}
6 changes: 6 additions & 0 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ sylius:
sylius_attribute: Sylius attributes
akeneo_attribute: Akeneo attributes
regenerate_url_rewrites: Regenerate url rewrites
enable_imported_products: Enable products at import
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
channels_checkboxes_priority: If at least one box is checked, this will overwrite the attribute information defined in the "Akeneo enabled channels attribute" section.
akeneo_enabled_channels_attribute_priority: If this field is filled in, do not check any channels in the section above.
enabled_at_import_help: If unchecked, the products will not be automatically activated on import.
attributes:
title: Attributes
subtitle: Attributes configuration
Expand Down
6 changes: 6 additions & 0 deletions src/Resources/translations/messages.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ sylius:
sylius_attribute: Attribut Sylius
akeneo_attribute: Attribut Akeneo
regenerate_url_rewrites: Regenerate url rewrites
enable_imported_products: Activer les produits à 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
channels_checkboxes_priority: Si au moins une case est cochée, cela écrasera les informations de l'attribut défini dans la section "Attribut Akeneo des channels actifs".
akeneo_enabled_channels_attribute_priority: Si ce champs est rempli, ne cochez pas de canaux dans la section du dessus.
enabled_at_import_help: Si décoché, les produits ne seront pas activés automatiquement à l'import.
attributes:
title: Attributs
subtitle: Configuration des attributs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@
{% endblock %}
<div class="ui segment">
{{ form_start(form, {'attr': {'class': 'ui loadable form', 'novalidate': 'novalidate'}}) }}
<div class="ui one column stackable grid segment">
<div class="column">
<span class="ui pointing below label">{{ 'sylius.ui.admin.akeneo.products.enabled_at_import_help'|trans }}</span>
{{ form_row(form.enableImportedProducts) }}
<span class="ui pointing below label">{{ 'sylius.ui.admin.akeneo.products.channels_checkboxes_priority'|trans }}</span>
{{ form_row(form.channelsToEnable) }}
<hr />
<span class="ui pointing below label">{{ 'sylius.ui.admin.akeneo.products.akeneo_enabled_channels_attribute_priority'|trans }}</span>
{{ form_row(form.akeneoEnabledChannelsAttribute) }}
</div>
</div>
{{ form_row(form.akeneoPriceAttribute) }}
{{ form_row(form.akeneoEnabledChannelsAttribute) }}
<div class="ui field">
{{ form_row(form.importMediaFiles) }}
</div>
Expand Down
97 changes: 75 additions & 22 deletions src/Service/ProductChannelEnabler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,32 +43,20 @@ public function __construct(
public function enableChannelForProduct(ProductInterface $product, array $resource): void
{
try {
$enabledChannels = $this->getEnabledChannelsAttributeData($product, $resource);
$productConfiguration = $this->getProductConfiguration();

if (!$productConfiguration->getEnableImportedProducts()) {
return;
}

$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()
));
}
$this->handleByAkeneoEnabledChannelsAttribute($productConfiguration, $product, $resource);
$this->handleBySyliusConfiguration($productConfiguration, $product);

$this->entityManager->flush();
$this->entityManager->commit();
} catch (\Throwable $throwable) {
Expand All @@ -80,7 +68,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([]);
Expand All @@ -89,6 +87,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.');
}
Expand All @@ -107,4 +113,51 @@ 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 {
$channels = $productConfiguration->getChannelsToEnable();
if ($channels->count() > 0) {
//Channel configuration section as higher priority.
return;
}

$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()) {
return;
}

$this->addProductToChannels($product, $channels);
}

private function addProductToChannels(ProductInterface $product, iterable $channels): void
{
foreach ($channels as $channel) {
$this->addProductToChannel($product, $channel);
}
}
}
12 changes: 12 additions & 0 deletions src/Service/ProductChannelEnablerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Synolia\SyliusAkeneoPlugin\Service;

use Sylius\Component\Core\Model\ProductInterface;

interface ProductChannelEnablerInterface
{
public function enableChannelForProduct(ProductInterface $product, array $resource): void;
}
6 changes: 3 additions & 3 deletions src/Task/Product/EnableDisableProductsTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use Synolia\SyliusAkeneoPlugin\Payload\PipelinePayloadInterface;
use Synolia\SyliusAkeneoPlugin\Payload\Product\ProductPayload;
use Synolia\SyliusAkeneoPlugin\Repository\ProductRepository;
use Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnabler;
use Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnablerInterface;
use Synolia\SyliusAkeneoPlugin\Task\AkeneoTaskInterface;

final class EnableDisableProductsTask implements AkeneoTaskInterface
Expand All @@ -23,7 +23,7 @@ final class EnableDisableProductsTask implements AkeneoTaskInterface
/** @var \Psr\Log\LoggerInterface */
private $logger;

/** @var \Synolia\SyliusAkeneoPlugin\Service\ProductChannelEnabler */
/** @var ProductChannelEnablerInterface */
private $productChannelEnabler;

/** @var \Doctrine\ORM\EntityManagerInterface */
Expand All @@ -32,7 +32,7 @@ final class EnableDisableProductsTask implements AkeneoTaskInterface
public function __construct(
ProductRepository $productRepository,
LoggerInterface $akeneoLogger,
ProductChannelEnabler $productChannelEnabler,
ProductChannelEnablerInterface $productChannelEnabler,
EntityManagerInterface $entityManager
) {
$this->productRepository = $productRepository;
Expand Down
6 changes: 3 additions & 3 deletions src/Task/ProductModel/EnableDisableProductModelsTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
Expand All @@ -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;
Expand Down

0 comments on commit 94a52a0

Please sign in to comment.