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

Skip locales not used in any product channels #138

Merged
merged 2 commits into from
Aug 4, 2022
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
35 changes: 34 additions & 1 deletion spec/ValueHandler/ImmutableSlugValueHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
namespace spec\Webgriffe\SyliusAkeneoPlugin\ValueHandler;

use Cocur\Slugify\SlugifyInterface;
use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductTranslationInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\Component\Resource\Translation\Provider\TranslationLocaleProviderInterface;
Expand All @@ -28,12 +31,28 @@ function let(
SlugifyInterface $slugify,
FactoryInterface $productTranslationFactory,
TranslationLocaleProviderInterface $translationLocaleProvider,
RepositoryInterface $productTranslationRepository
RepositoryInterface $productTranslationRepository,
LocaleInterface $italianLocale,
LocaleInterface $englishLocale,
ChannelInterface $commerceChannel,
ChannelInterface $supportChannel,
ProductInterface $product
) {
$slugify->slugify(self::VALUE_TO_SLUGIFY)->willReturn(self::SLUGIFIED_VALUE);
$translationLocaleProvider->getDefinedLocalesCodes()->willReturn(['en_US', 'it_IT']);
$productTranslationRepository->findOneBy(['slug' => self::SLUGIFIED_VALUE, 'locale' => 'en_US'])->willReturn(null);
$productTranslationRepository->findOneBy(['slug' => self::SLUGIFIED_VALUE, 'locale' => 'it_IT'])->willReturn(null);

$italianLocale->getCode()->willReturn('it_IT');
$englishLocale->getCode()->willReturn('en_US');

$commerceChannel->getCode()->willReturn('ecommerce');
$commerceChannel->getLocales()->willReturn(new ArrayCollection([$italianLocale->getWrappedObject()]));
$supportChannel->getCode()->willReturn('support');
$supportChannel->getLocales()->willReturn(new ArrayCollection([$italianLocale->getWrappedObject(), $englishLocale->getWrappedObject()]));

$product->getChannels()->willReturn(new ArrayCollection([$commerceChannel->getWrappedObject(), $supportChannel->getWrappedObject()]));

$this->beConstructedWith(
$slugify,
$productTranslationFactory,
Expand Down Expand Up @@ -204,4 +223,18 @@ function it_skips_locales_not_specified_in_sylius(

$productTranslation->setSlug(Argument::type('string'))->shouldNotHaveBeenCalled();
}

public function it_skips_locales_not_used_in_any_product_channels(
ProductVariantInterface $productVariant,
ProductInterface $product,
ProductTranslationInterface $productTranslation,
ChannelInterface $commerceChannel
): void {
$product->getChannels()->willReturn(new ArrayCollection([$commerceChannel->getWrappedObject()]));
$productVariant->getProduct()->willReturn($product);

$this->handle($productVariant, self::AKENEO_ATTRIBUTE, [['locale' => 'en_US', 'scope' => null, 'data' => 'New value']]);

$productTranslation->setSlug(Argument::type('string'))->shouldNotHaveBeenCalled();
}
}
51 changes: 37 additions & 14 deletions spec/ValueHandler/TranslatablePropertyValueHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
use Prophecy\Argument;
use RuntimeException;
use stdClass;
use Sylius\Component\Core\Model\Channel;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductTranslationInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Locale\Provider\LocaleProviderInterface;
use Sylius\Component\Product\Model\ProductVariantTranslationInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Translation\Provider\TranslationLocaleProviderInterface;
Expand All @@ -36,35 +38,41 @@ public function let(
ProductVariantTranslationInterface $italianProductVariantTranslation,
ProductInterface $product,
ProductTranslationInterface $englishProductTranslation,
ProductTranslationInterface $italianProductTranslation
ProductTranslationInterface $italianProductTranslation,
LocaleInterface $italianLocale,
LocaleInterface $englishLocale,
ChannelInterface $commerceChannel,
ChannelInterface $supportChannel
): void {
$propertyAccessor->isWritable($englishProductVariantTranslation, self::TRANSLATION_PROPERTY_PATH)->willReturn(true);
$propertyAccessor->isWritable($italianProductVariantTranslation, self::TRANSLATION_PROPERTY_PATH)->willReturn(true);
$propertyAccessor->isWritable($englishProductTranslation, self::TRANSLATION_PROPERTY_PATH)->willReturn(true);
$propertyAccessor->isWritable($italianProductTranslation, self::TRANSLATION_PROPERTY_PATH)->willReturn(true);

$localeProvider->getDefinedLocalesCodes()->willReturn(['en_US', 'it_IT']);
$italianLocale->getCode()->willReturn('it_IT');
$englishLocale->getCode()->willReturn('en_US');

$productVariant->getProduct()->willReturn($product);
$commerceChannel = new Channel();
$commerceChannel->setCode('ecommerce');
$supportChannel = new Channel();
$supportChannel->setCode('support');
$product->getChannels()->willReturn(new ArrayCollection([$commerceChannel, $supportChannel]));
$localeProvider->getDefinedLocalesCodes()->willReturn(['en_US', 'it_IT']);
$commerceChannel->getCode()->willReturn('ecommerce');
$commerceChannel->getLocales()->willReturn(new ArrayCollection([$italianLocale->getWrappedObject(), $englishLocale->getWrappedObject()]));
$supportChannel->getCode()->willReturn('support');
$supportChannel->getLocales()->willReturn(new ArrayCollection([$italianLocale->getWrappedObject(), $englishLocale->getWrappedObject()]));

$productVariant->getProduct()->willReturn($product);
$englishProductVariantTranslation->getLocale()->willReturn('en_US');
$italianProductVariantTranslation->getLocale()->willReturn('it_IT');
$englishProductVariantTranslation->getTranslatable()->willReturn($productVariant);
$italianProductVariantTranslation->getTranslatable()->willReturn($productVariant);
$productVariant->getTranslation('en_US')->willReturn($englishProductVariantTranslation);
$productVariant->getTranslation('it_IT')->willReturn($italianProductVariantTranslation);
$englishProductTranslation->getLocale()->willReturn('en_US');
$italianProductTranslation->getLocale()->willReturn('it_IT');

$product->getChannels()->willReturn(new ArrayCollection([$commerceChannel->getWrappedObject(), $supportChannel->getWrappedObject()]));
$product->getTranslation('en_US')->willReturn($englishProductTranslation);
$product->getTranslation('it_IT')->willReturn($italianProductTranslation);

$productVariant->getProduct()->willReturn($product);
$productVariant->getTranslation('en_US')->willReturn($englishProductVariantTranslation);
$productVariant->getTranslation('it_IT')->willReturn($italianProductVariantTranslation);

$this->beConstructedWith(
$propertyAccessor,
$productTranslationFactory,
Expand Down Expand Up @@ -182,6 +190,21 @@ public function it_skips_locales_not_specified_in_sylius(
$propertyAccessor->setValue($productTranslation, self::TRANSLATION_PROPERTY_PATH, 'New value')->shouldNotHaveBeenCalled();
}

public function it_skips_locales_not_used_in_any_product_channels(
ProductVariantInterface $productVariant,
ProductVariantTranslationInterface $productVariantTranslation,
ProductTranslationInterface $productTranslation,
PropertyAccessorInterface $propertyAccessor,
LocaleProviderInterface $localeProvider
): void {
$localeProvider->getDefinedLocalesCodes()->willReturn(['en_US', 'it_IT', 'es_ES']);

$this->handle($productVariant, self::AKENEO_ATTRIBUTE_CODE, [['locale' => 'es_ES', 'scope' => null, 'data' => 'New value']]);

$propertyAccessor->setValue($productVariantTranslation, self::TRANSLATION_PROPERTY_PATH, 'New value')->shouldNotHaveBeenCalled();
$propertyAccessor->setValue($productTranslation, self::TRANSLATION_PROPERTY_PATH, 'New value')->shouldNotHaveBeenCalled();
}

public function it_sets_value_on_all_product_translations_when_locale_not_specified(
ProductVariantInterface $productVariant,
ProductVariantTranslationInterface $englishProductVariantTranslation,
Expand Down Expand Up @@ -321,14 +344,14 @@ public function it_skips_values_related_to_channels_that_are_not_associated_to_t
public function it_throws_when_data_is_not_an_array(ProductVariantInterface $productVariant): void
{
$this
->shouldThrow(new \InvalidArgumentException('Invalid Akeneo value data: expected an array, "NULL" given.',))
->shouldThrow(new InvalidArgumentException('Invalid Akeneo value data: expected an array, "NULL" given.',))
->during('handle', [$productVariant, self::AKENEO_ATTRIBUTE_CODE, [null]]);
}

public function it_throws_when_data_doesnt_contain_scope_info(ProductVariantInterface $productVariant): void
{
$this
->shouldThrow(new \InvalidArgumentException('Invalid Akeneo value data: required "scope" information was not found.',))
->shouldThrow(new InvalidArgumentException('Invalid Akeneo value data: required "scope" information was not found.',))
->during(
'handle',
[
Expand Down
18 changes: 18 additions & 0 deletions src/ValueHandler/ImmutableSlugValueHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Webgriffe\SyliusAkeneoPlugin\ValueHandler;

use Cocur\Slugify\SlugifyInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductTranslationInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
Expand Down Expand Up @@ -85,6 +86,9 @@ public function handle($subject, string $attribute, array $value): void
if (!in_array($localeCode, $this->translationLocaleProvider->getDefinedLocalesCodes(), true)) {
continue;
}
if (!$this->isLocaleUsedInAtLeastOneChannelForTheProduct($product, $localeCode)) {
continue;
}

$productTranslation = $this->getOrCreateNewProductTranslation($product, $localeCode);
if ($productTranslation->getSlug() !== null) {
Expand Down Expand Up @@ -150,4 +154,18 @@ private function getDeduplicatedSlug(

return $deduplicatedSlug;
}

private function isLocaleUsedInAtLeastOneChannelForTheProduct(ProductInterface $product, string $localeCode): bool
{
foreach ($product->getChannels() as $channel) {
Assert::isInstanceOf($channel, ChannelInterface::class);
foreach ($channel->getLocales() as $locale) {
if ($locale->getCode() === $localeCode) {
return true;
}
}
}

return false;
}
}
17 changes: 17 additions & 0 deletions src/ValueHandler/TranslatablePropertyValueHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public function handle($subject, string $attribute, array $value): void
if (!in_array($localeCode, $availableLocalesCodes, true)) {
continue;
}
if (!$this->isLocaleUsedInAtLeastOneChannelForTheProduct($product, $localeCode)) {
continue;
}

$this->setValueOnProductVariantAndProductTranslation($subject, $localeCode, $valueData['data']);
}
Expand Down Expand Up @@ -217,4 +220,18 @@ private function setNullOnExistingProductVariantAndProductTranslation(
}
}
}

private function isLocaleUsedInAtLeastOneChannelForTheProduct(ProductInterface $product, string $localeCode): bool
{
foreach ($product->getChannels() as $channel) {
Assert::isInstanceOf($channel, \Sylius\Component\Core\Model\ChannelInterface::class);
foreach ($channel->getLocales() as $locale) {
if ($locale->getCode() === $localeCode) {
return true;
}
}
}

return false;
}
}
2 changes: 2 additions & 0 deletions tests/Integration/Product/ImporterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -681,8 +681,10 @@ public function it_does_not_fail_with_empty_translations()
{
$this->fixtureLoader->load(
[
__DIR__ . '/../DataFixtures/ORM/resources/Currency/USD.yaml',
__DIR__ . '/../DataFixtures/ORM/resources/Locale/en_US.yaml',
__DIR__ . '/../DataFixtures/ORM/resources/Locale/it_IT.yaml',
__DIR__ . '/../DataFixtures/ORM/resources/Channel/usa.yaml',
],
[],
[],
Expand Down