Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow channel selection to enabled them on product import #65

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
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