Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
lruozzi9 committed Jul 10, 2024
1 parent 2226d60 commit e596031
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 93 deletions.
154 changes: 154 additions & 0 deletions src/Attribute/Importer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

declare(strict_types=1);

namespace Webgriffe\SyliusAkeneoPlugin\Attribute;

use Akeneo\Pim\ApiClient\AkeneoPimClientInterface;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface;
use Akeneo\Pim\ApiClient\Search\SearchBuilder;
use DateTime;
use Sylius\Component\Product\Model\ProductAttributeInterface;
use Sylius\Component\Product\Model\ProductAttributeTranslationInterface;
use Sylius\Component\Product\Model\ProductOptionInterface;
use Sylius\Component\Product\Model\ProductOptionTranslationInterface;
use Sylius\Component\Product\Repository\ProductOptionRepositoryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Webgriffe\SyliusAkeneoPlugin\Event\IdentifiersModifiedSinceSearchBuilderBuiltEvent;
use Webgriffe\SyliusAkeneoPlugin\ImporterInterface;
use Webgriffe\SyliusAkeneoPlugin\ProductAttributeHelperTrait;
use Webgriffe\SyliusAkeneoPlugin\ProductOptionHelperTrait;

/**
* @psalm-type AkeneoAttribute array{code: string, type: string, labels: array<string, ?string>}
*/
final class Importer implements ImporterInterface
{
public const SIMPLESELECT_TYPE = 'pim_catalog_simpleselect';

public const MULTISELECT_TYPE = 'pim_catalog_multiselect';

public const BOOLEAN_TYPE = 'pim_catalog_boolean';

public const METRIC_TYPE = 'pim_catalog_metric';

use ProductOptionHelperTrait, ProductAttributeHelperTrait;

public const AKENEO_ENTITY = 'Attribute';

/**
* @param FactoryInterface<ProductOptionTranslationInterface> $productOptionTranslationFactory
* @param RepositoryInterface<ProductAttributeInterface> $productAttributeRepository
* @param FactoryInterface<ProductAttributeTranslationInterface> $productAttributeTranslationFactory
*/
public function __construct(
private EventDispatcherInterface $eventDispatcher,
private AkeneoPimClientInterface $apiClient,
private ProductOptionRepositoryInterface $productOptionRepository,
private FactoryInterface $productOptionTranslationFactory,
private RepositoryInterface $productAttributeRepository,
private FactoryInterface $productAttributeTranslationFactory,
) {
}

public function getAkeneoEntity(): string
{
return self::AKENEO_ENTITY;
}

public function getIdentifiersModifiedSince(DateTime $sinceDate): array
{
$searchBuilder = new SearchBuilder();
$this->eventDispatcher->dispatch(
new IdentifiersModifiedSinceSearchBuilderBuiltEvent($this, $searchBuilder, $sinceDate),
);
/**
* @psalm-suppress TooManyTemplateParams
*
* @var ResourceCursorInterface<array-key, AkeneoAttribute> $akeneoAttributes
*/
$akeneoAttributes = $this->apiClient->getAttributeApi()->all(50, ['search' => $searchBuilder->getFilters()]);

return array_merge(
$this->filterBySyliusAttributeCodes($akeneoAttributes),
$this->filterSyliusOptionCodes($akeneoAttributes),
);
}

public function import(string $identifier): void
{
/** @var AkeneoAttribute $akeneoAttribute */
$akeneoAttribute = $this->apiClient->getAttributeApi()->get($identifier);

$syliusProductAttribute = $this->productAttributeRepository->findOneBy(['code' => $identifier]);
if ($syliusProductAttribute instanceof ProductAttributeInterface) {
$this->importAttributeData($akeneoAttribute, $syliusProductAttribute);
}

$syliusProductOption = $this->productOptionRepository->findOneBy(['code' => $identifier]);
if ($syliusProductOption instanceof ProductOptionInterface) {
$this->importOptionData($akeneoAttribute, $syliusProductOption);
}
}

/**
* @return FactoryInterface<ProductOptionTranslationInterface>
*/
private function getProductOptionTranslationFactory(): FactoryInterface
{
return $this->productOptionTranslationFactory;
}

private function getProductOptionRepository(): ProductOptionRepositoryInterface
{
return $this->productOptionRepository;
}

/**
* @return RepositoryInterface<ProductAttributeInterface>
*/
private function getProductAttributeRepository(): RepositoryInterface
{
return $this->productAttributeRepository;
}

/**
* @param AkeneoAttribute $akeneoAttribute
*/
private function importAttributeData(array $akeneoAttribute, ProductAttributeInterface $syliusProductAttribute): void
{
$this->importProductAttributeTranslations($akeneoAttribute, $syliusProductAttribute);
$this->productAttributeRepository->add($syliusProductAttribute);
}

/**
* @param AkeneoAttribute $akeneoAttribute
*/
private function importOptionData(array $akeneoAttribute, ProductOptionInterface $syliusProductOption): void
{
$this->importProductOptionTranslations($akeneoAttribute, $syliusProductOption);
$this->productOptionRepository->add($syliusProductOption);
// TODO: Update also the position of the option? The problem is that this position is on family variant entity!
}

/**
* @param AkeneoAttribute $akeneoAttribute
*/
private function importProductAttributeTranslations(array $akeneoAttribute, ProductAttributeInterface $syliusProductAttribute): void
{
foreach ($akeneoAttribute['labels'] as $locale => $label) {
$productAttributeTranslation = $syliusProductAttribute->getTranslation($locale);
if ($productAttributeTranslation->getLocale() === $locale) {
$productAttributeTranslation->setName($label);

continue;
}
$newProductAttributeTranslation = $this->productAttributeTranslationFactory->createNew();
$newProductAttributeTranslation->setLocale($locale);
$newProductAttributeTranslation->setName($label);
$syliusProductAttribute->addTranslation($newProductAttributeTranslation);
}
}
}
129 changes: 36 additions & 93 deletions src/AttributeOptions/Importer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
use Sylius\Component\Resource\Translation\Provider\TranslationLocaleProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Webgriffe\SyliusAkeneoPlugin\Attribute\Importer as AttributeImporter;
use Webgriffe\SyliusAkeneoPlugin\Event\IdentifiersModifiedSinceSearchBuilderBuiltEvent;
use Webgriffe\SyliusAkeneoPlugin\ImporterInterface;
use Webgriffe\SyliusAkeneoPlugin\ProductAttributeHelperTrait;
use Webgriffe\SyliusAkeneoPlugin\ProductOptionHelperTrait;
use Webgriffe\SyliusAkeneoPlugin\ProductOptionValueHelperTrait;
use Webmozart\Assert\Assert;
Expand All @@ -32,15 +34,9 @@
*/
final class Importer implements ImporterInterface
{
use ProductOptionHelperTrait, ProductOptionValueHelperTrait;

private const SIMPLESELECT_TYPE = 'pim_catalog_simpleselect';

private const MULTISELECT_TYPE = 'pim_catalog_multiselect';

private const BOOLEAN_TYPE = 'pim_catalog_boolean';

private const METRIC_TYPE = 'pim_catalog_metric';
use ProductOptionHelperTrait,
ProductOptionValueHelperTrait,
ProductAttributeHelperTrait;

/**
* @param RepositoryInterface<ProductAttributeInterface> $attributeRepository
Expand Down Expand Up @@ -102,28 +98,6 @@ public function getAkeneoEntity(): string
return 'AttributeOptions';
}

public function import(string $identifier): void
{
$attribute = $this->attributeRepository->findOneBy(['code' => $identifier]);
if (null !== $attribute && $attribute->getType() === SelectAttributeType::TYPE) {
$this->importAttributeConfiguration($identifier, $attribute);
}
$optionRepository = $this->optionRepository;
if (!$optionRepository instanceof ProductOptionRepositoryInterface) {
return;
}
$option = $optionRepository->findOneBy(['code' => $identifier]);
if (!$option instanceof ProductOptionInterface) {
return;
}
/** @var AkeneoAttribute $attributeResponse */
$attributeResponse = $this->apiClient->getAttributeApi()->get($identifier);

// TODO: Update also the position of the option? The problem is that this position is on family variant entity!
$this->importProductOptionTranslations($attributeResponse, $option);
$this->importOptionValues($attributeResponse, $option);
}

/**
* As stated at https://api.akeneo.com/documentation/filter.html#by-update-date-3:
*
Expand All @@ -145,73 +119,29 @@ public function getIdentifiersModifiedSince(DateTime $sinceDate): array
$akeneoAttributes = $this->apiClient->getAttributeApi()->all(50, ['search' => $searchBuilder->getFilters()]);

return array_merge(
$this->filterBySyliusAttributeCodes($akeneoAttributes),
$this->filterBySyliusSelectAttributeCodes($akeneoAttributes),
$this->filterSyliusOptionCodes($akeneoAttributes),
);
}

/**
* Return the list of Akeneo attribute codes whose code is used as a code for a Sylius attribute
*
* @psalm-suppress TooManyTemplateParams
*
* @param ResourceCursorInterface<array-key, AkeneoAttribute> $akeneoAttributes
*
* @return string[]
*/
private function filterBySyliusAttributeCodes(ResourceCursorInterface $akeneoAttributes): array
public function import(string $identifier): void
{
$syliusSelectAttributes = $this->attributeRepository->findBy(['type' => SelectAttributeType::TYPE]);
$syliusSelectAttributes = array_filter(
array_map(
static fn (ProductAttributeInterface $attribute): ?string => $attribute->getCode(),
$syliusSelectAttributes,
),
);
$attributeCodes = [];
/** @var AkeneoAttribute $akeneoAttribute */
foreach ($akeneoAttributes as $akeneoAttribute) {
if (!in_array($akeneoAttribute['code'], $syliusSelectAttributes, true)) {
continue;
}
if ($akeneoAttribute['type'] !== self::SIMPLESELECT_TYPE && $akeneoAttribute['type'] !== self::MULTISELECT_TYPE) {
continue;
}
$attributeCodes[] = $akeneoAttribute['code'];
$attribute = $this->attributeRepository->findOneBy(['code' => $identifier]);
if (null !== $attribute && $attribute->getType() === SelectAttributeType::TYPE) {
$this->importAttributeConfiguration($identifier, $attribute);
}

return $attributeCodes;
}

/**
* Return the list of Akeneo attribute codes whose code is used as a code for a Sylius attribute
*
* @psalm-suppress TooManyTemplateParams
*
* @param ResourceCursorInterface<array-key, AkeneoAttribute> $akeneoAttributes
*
* @return string[]
*/
private function filterSyliusOptionCodes(ResourceCursorInterface $akeneoAttributes): array
{
$productOptionRepository = $this->optionRepository;
if (!$productOptionRepository instanceof ProductOptionRepositoryInterface) {
return [];
$optionRepository = $this->optionRepository;
if (!$optionRepository instanceof ProductOptionRepositoryInterface) {
return;
}
$akeneoAttributeCodes = [];
/** @var AkeneoAttribute $akeneoAttribute */
foreach ($akeneoAttributes as $akeneoAttribute) {
if (!in_array($akeneoAttribute['type'], [self::SIMPLESELECT_TYPE, self::MULTISELECT_TYPE, self::BOOLEAN_TYPE, self::METRIC_TYPE], true)) {
continue;
}
$akeneoAttributeCodes[] = $akeneoAttribute['code'];
$option = $optionRepository->findOneBy(['code' => $identifier]);
if (!$option instanceof ProductOptionInterface) {
return;
}
$syliusOptions = $productOptionRepository->findByCodes($akeneoAttributeCodes);
/** @var AkeneoAttribute $attributeResponse */
$attributeResponse = $this->apiClient->getAttributeApi()->get($identifier);

return array_map(
static fn (ProductOptionInterface $option): string => (string) $option->getCode(),
$syliusOptions,
);
$this->importOptionValues($attributeResponse, $option);
}

private function importAttributeConfiguration(string $attributeCode, ProductAttributeInterface $attribute): void
Expand Down Expand Up @@ -250,15 +180,15 @@ private function convertAkeneoAttributeOptionsIntoSyliusChoices(array $attribute
*/
private function importOptionValues(array $akeneoAttribute, ProductOptionInterface $option): void
{
if ($akeneoAttribute['type'] !== self::SIMPLESELECT_TYPE &&
$akeneoAttribute['type'] !== self::MULTISELECT_TYPE &&
$akeneoAttribute['type'] !== self::BOOLEAN_TYPE
if ($akeneoAttribute['type'] !== AttributeImporter::SIMPLESELECT_TYPE &&
$akeneoAttribute['type'] !== AttributeImporter::MULTISELECT_TYPE &&
$akeneoAttribute['type'] !== AttributeImporter::BOOLEAN_TYPE
) {
return;
}
$attributeCode = $akeneoAttribute['code'];

if ($akeneoAttribute['type'] === self::BOOLEAN_TYPE) {
if ($akeneoAttribute['type'] === AttributeImporter::BOOLEAN_TYPE) {
foreach ([true, false] as $booleanValue) {
$optionValueCode = $this->getSyliusProductOptionValueCode($attributeCode, (string) $booleanValue);
$productOptionValue = $this->getProductOptionValueFromOption($option, $optionValueCode);
Expand Down Expand Up @@ -387,4 +317,17 @@ private function getProductOptionValueFromOption(

return $productOptionValue;
}

private function getProductOptionRepository(): ?ProductOptionRepositoryInterface
{
return $this->optionRepository;
}

/**
* @return RepositoryInterface<ProductAttributeInterface>
*/
private function getProductAttributeRepository(): RepositoryInterface
{
return $this->attributeRepository;
}
}
5 changes: 5 additions & 0 deletions src/Product/ProductOptionsResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,9 @@ private function getProductOptionTranslationFactory(): FactoryInterface
{
return $this->productOptionTranslationFactory;
}

private function getProductOptionRepository(): ProductOptionRepositoryInterface
{
return $this->productOptionRepository;
}
}
Loading

0 comments on commit e596031

Please sign in to comment.