Skip to content

Commit

Permalink
Product Group processing deported to product models import
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGrimmChester committed Nov 1, 2023
1 parent c4917ac commit 88c5c03
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 73 deletions.
18 changes: 18 additions & 0 deletions src/Component/Cache/CacheKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Synolia\SyliusAkeneoPlugin\Component\Cache;

class CacheKey
{
public const FAMILIES = 'akeneo:families';

public const FAMILY = 'akeneo:family:%s';

public const FAMILY_BY_VARIANT_CODE = 'akeneo:family_by_variant_code:%s';

public const FAMILY_VARIANTS = 'akeneo:family_variants:%s';

public const ATTRIBUTES = 'akeneo:attributes';
}
88 changes: 88 additions & 0 deletions src/Processor/ProductGroup/ProductGroupProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace Synolia\SyliusAkeneoPlugin\Processor\ProductGroup;

use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Synolia\SyliusAkeneoPlugin\Entity\ProductGroupInterface;

class ProductGroupProcessor
{
public function __construct(
private EntityManagerInterface $entityManager,
private LoggerInterface $logger,
private FamilyVariationAxeProcessor $familyVariationAxeProcessor,
private EntityRepository $productGroupRepository,
private FactoryInterface $productGroupFactory,
) {
}

public function process(array $resource): void
{
$this->createProductGroups($resource);
$this->familyVariationAxeProcessor->process($resource);
}

private function createGroupForCodeAndFamily(
string $code,
string $family,
string $familyVariant,
?string $parent = null,
): ProductGroupInterface {
if (isset($this->productGroupsMapping[$code])) {

Check failure on line 36 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 36 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 36 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 36 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.
return $this->productGroupsMapping[$code];
}

$productGroup = $this->productGroupRepository->findOneBy(['model' => $code]);

if ($productGroup instanceof ProductGroupInterface) {
$this->productGroupsMapping[$code] = $productGroup;

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 43 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

$this->logger->info(sprintf(
'Skipping ProductGroup "%s" for family "%s" as it already exists.',
$code,
$family,
));

$productGroup->setParent($this->productGroupsMapping[$parent] ?? null);
$productGroup->setModel($code);
$productGroup->setFamily($family);
$productGroup->setFamilyVariant($familyVariant);
$this->entityManager->persist($productGroup);

return $productGroup;
}

$this->logger->info(sprintf(
'Creating ProductGroup "%s" for family "%s"',
$code,
$family,
));

/** @var ProductGroupInterface $productGroup */
$productGroup = $this->productGroupFactory->createNew();
$productGroup->setParent($this->productGroupsMapping[$parent] ?? null);

Check failure on line 68 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 68 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 68 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 68 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.
$productGroup->setModel($code);
$productGroup->setFamily($family);
$productGroup->setFamilyVariant($familyVariant);
$this->entityManager->persist($productGroup);
$this->productGroupsMapping[$code] = $productGroup;

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 5.4.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

Check failure on line 73 in src/Processor/ProductGroup/ProductGroupProcessor.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Symfony 6.2.*

Access to an undefined property Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor::$productGroupsMapping.

return $productGroup;
}

private function createProductGroups(array $resource): void
{
if (null !== $resource['parent']) {
$this->createGroupForCodeAndFamily($resource['parent'], $resource['family'], $resource['family_variant']);
}

if (null !== $resource['code']) {
$this->createGroupForCodeAndFamily($resource['code'], $resource['family'], $resource['family_variant'], $resource['parent']);
}
}
}
97 changes: 54 additions & 43 deletions src/Retriever/FamilyRetriever.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,88 @@

use Akeneo\Pim\ApiClient\AkeneoPimClientInterface;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Synolia\SyliusAkeneoPlugin\Component\Cache\CacheKey;
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;

final class FamilyRetriever implements FamilyRetrieverInterface
{
/** @var array<string> */
private array $familiesByVariant = [];

private array $families = [];

private array $familiesByCode = [];

private array $familiesByVariantCode = [];

public function __construct(
private AkeneoPimClientInterface $akeneoPimClient,
private LoggerInterface $logger,
private ApiConnectionProviderInterface $apiConnectionProvider,
private CacheInterface $akeneoFamilies,
private CacheInterface $akeneoFamily,
private FamilyVariantRetriever $familyVariantRetriever,
) {
}

public function getFamily(string $familyCode): array
public function getFamilies(): array
{
if (\array_key_exists($familyCode, $this->families)) {
return $this->families[$familyCode];
if ($this->families !== []) {
return $this->families;
}

$paginationSize = $this->apiConnectionProvider->get()->getPaginationSize();
/** @phpstan-ignore-next-line */
return $this->families = $this->akeneoFamilies->get(CacheKey::FAMILIES, function (): array {
$families = [];

$families = $this->akeneoPimClient->getFamilyApi()->all($paginationSize);
$paginationSize = $this->apiConnectionProvider->get()->getPaginationSize();

/** @var array{code: string} $family */
foreach ($families as $family) {
$this->families[$family['code']] = $family;
}
$results = $this->akeneoPimClient->getFamilyApi()->all($paginationSize);

return $this->families[$familyCode];
/** @var array{code: string} $result */
foreach ($results as $result) {
$families[$result['code']] = $result;
}

return $families;
});
}

public function getFamilyCodeByVariantCode(string $familyVariantCode): string
public function getFamily(string $familyCode): array
{
if (\array_key_exists($familyVariantCode, $this->familiesByVariant)) {
return $this->familiesByVariant[$familyVariantCode];
if (array_key_exists($familyCode, $this->familiesByCode)) {
return $this->familiesByCode[$familyCode];
}

$paginationSize = $this->apiConnectionProvider->get()->getPaginationSize();

try {
$families = $this->akeneoPimClient->getFamilyApi()->all($paginationSize);

/** @var array{code: string} $family */
foreach ($families as $family) {
if (!\array_key_exists($family['code'], $this->families)) {
$this->families[$family['code']] = $family;
}

$familyVariants = $this->akeneoPimClient->getFamilyVariantApi()->all($family['code'], $paginationSize);
if (!$familyVariants->valid()) {
continue;
}
/** @phpstan-ignore-next-line */
return $this->familiesByCode[$familyCode] = $this->akeneoFamily->get(\sprintf(CacheKey::FAMILY, $familyCode), function () use ($familyCode): array {
return $this->getFamilies()[$familyCode];
});
}

/** @var array{code: string} $familyVariant */
foreach ($familyVariants as $familyVariant) {
$this->familiesByVariant[$familyVariant['code']] = $family['code'];
}
public function getFamilyCodeByVariantCode(string $familyVariantCode): string
{
if (array_key_exists($familyVariantCode, $this->familiesByVariantCode)) {
return $this->familiesByVariantCode[$familyVariantCode];
}

if (isset($this->familiesByVariant[$familyVariantCode])) {
return $family['code'];
/** @phpstan-ignore-next-line */
return $this->familiesByVariantCode[$familyVariantCode] = $this->akeneoFamily->get(\sprintf(CacheKey::FAMILY_BY_VARIANT_CODE, $familyVariantCode), function () use ($familyVariantCode): string {
try {
/** @var array{code: string} $family */
foreach ($this->getFamilies() as $family) {
/** @var array{code: string} $familyVariant */
foreach ($this->familyVariantRetriever->getVariants($family['code']) as $familyVariant) {
if ($familyVariant['code'] === $familyVariantCode) {
return $family['code'];
}
}
}
} catch (\Throwable $exception) {
$this->logger->warning($exception->getMessage(), [
'exception' => $exception,
]);
}
} catch (\Throwable $exception) {
$this->logger->warning($exception->getMessage(), [
'exception' => $exception,
]);
}

throw new \LogicException(sprintf('Unable to find family for variant "%s"', $familyVariantCode));
throw new \LogicException(sprintf('Unable to find family for variant "%s"', $familyVariantCode));
});
}
}
2 changes: 2 additions & 0 deletions src/Retriever/FamilyRetrieverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

interface FamilyRetrieverInterface
{
public function getFamilies(): array;

public function getFamilyCodeByVariantCode(string $familyVariantCode): string;

public function getFamily(string $familyCode): array;
Expand Down
33 changes: 18 additions & 15 deletions src/Retriever/FamilyVariantRetriever.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,42 @@

use Akeneo\Pim\ApiClient\AkeneoPimClientInterface;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Synolia\SyliusAkeneoPlugin\Component\Cache\CacheKey;
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;

final class FamilyVariantRetriever
final class FamilyVariantRetriever implements FamilyVariantRetrieverInterface
{
private array $familyVariants = [];
private array $variantsByFamily = [];

public function __construct(
private AkeneoPimClientInterface $akeneoPimClient,
private LoggerInterface $logger,
private ApiConnectionProviderInterface $apiConnectionProvider,
private CacheInterface $akeneoFamilyVariants,
) {
}

public function getVariants(string $familyCode): array
{
if (\array_key_exists($familyCode, $this->familyVariants)) {
return $this->familyVariants[$familyCode];
if ($this->variantsByFamily !== []) {
return $this->variantsByFamily[$familyCode] ?? [];
}

$paginationSize = $this->apiConnectionProvider->get()->getPaginationSize();
/** @phpstan-ignore-next-line */
return $this->variantsByFamily[$familyCode] = $this->akeneoFamilyVariants->get(\sprintf(CacheKey::FAMILY_VARIANTS, $familyCode), function () use ($familyCode): array {
$paginationSize = $this->apiConnectionProvider->get()->getPaginationSize();

try {
$familyVariants = $this->akeneoPimClient->getFamilyVariantApi()->all($familyCode, $paginationSize);
try {
$results = $this->akeneoPimClient->getFamilyVariantApi()->all($familyCode, $paginationSize);
$familyVariants = iterator_to_array($results);
} catch (\Throwable $exception) {
$this->logger->warning($exception->getMessage());

$this->familyVariants[$familyCode] = iterator_to_array($familyVariants);

if (isset($this->familyVariants[$familyCode])) {
return $this->familyVariants[$familyCode];
return [];
}
} catch (\Throwable $exception) {
$this->logger->warning($exception->getMessage());
}

throw new \LogicException(sprintf('Unable to find variants for family "%s"', $familyCode));
return $familyVariants;
});
}
}
10 changes: 10 additions & 0 deletions src/Retriever/FamilyVariantRetrieverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Synolia\SyliusAkeneoPlugin\Retriever;

interface FamilyVariantRetrieverInterface
{
public function getVariants(string $familyCode): array;
}
19 changes: 7 additions & 12 deletions src/Task/Attribute/BatchAttributesTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Synolia\SyliusAkeneoPlugin\Task\Attribute;

use Akeneo\Pim\ApiClient\Exception\NotFoundHttpException;
use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface;
use Doctrine\DBAL\Result;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
Expand All @@ -24,7 +23,8 @@
use Synolia\SyliusAkeneoPlugin\Processor\ProductAttribute\ProductAttributeChoiceProcessorInterface;
use Synolia\SyliusAkeneoPlugin\Processor\ProductAttribute\ProductAttributeTableProcessorInterface;
use Synolia\SyliusAkeneoPlugin\Processor\ProductOption\ProductOptionProcessorInterface;
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;
use Synolia\SyliusAkeneoPlugin\Retriever\FamilyRetrieverInterface;
use Synolia\SyliusAkeneoPlugin\Retriever\FamilyVariantRetrieverInterface;
use Synolia\SyliusAkeneoPlugin\Task\AbstractBatchTask;
use Webmozart\Assert\Assert;

Expand All @@ -37,8 +37,9 @@ public function __construct(
private ProductOptionProcessorInterface $productOptionProcessor,
private ProductAttributeTableProcessorInterface $productAttributeTableProcessor,
private EventDispatcherInterface $dispatcher,
private ApiConnectionProviderInterface $apiConnectionProvider,
private AttributeCreatorInterface $attributeCreator,
private FamilyRetrieverInterface $familyRetriever,
private FamilyVariantRetrieverInterface $familyVariantRetriever,
) {
parent::__construct($entityManager);
}
Expand Down Expand Up @@ -131,24 +132,18 @@ private function getVariationAxes(PipelinePayloadInterface $payload): array
{
Assert::isInstanceOf($payload, AbstractPayload::class);
$variationAxes = [];
$client = $payload->getAkeneoPimClient();
$pagination = $this->apiConnectionProvider->get()->getPaginationSize();

$families = $client->getFamilyApi()->all($pagination);
$families = $this->familyRetriever->getFamilies();

foreach ($families as $family) {
$familyVariants = $client->getFamilyVariantApi()->all(
$family['code'],
$pagination,
);
$familyVariants = $this->familyVariantRetriever->getVariants($family['code']);

$variationAxes = array_merge($variationAxes, $this->getVariationAxesForFamilies($familyVariants));
}

return $variationAxes;
}

private function getVariationAxesForFamilies(ResourceCursorInterface $familyVariants): array
private function getVariationAxesForFamilies(array $familyVariants): array
{
$variationAxes = [];

Expand Down
4 changes: 4 additions & 0 deletions src/Task/ProductGroup/ProcessProductGroupModelTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Synolia\SyliusAkeneoPlugin\Entity\ProductGroupInterface;
use Synolia\SyliusAkeneoPlugin\Payload\PipelinePayloadInterface;
use Synolia\SyliusAkeneoPlugin\Processor\ProductGroup\ProductGroupProcessor;
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;
use Synolia\SyliusAkeneoPlugin\Repository\ProductGroupRepository;
use Synolia\SyliusAkeneoPlugin\Task\AkeneoTaskInterface;
Expand All @@ -24,6 +25,7 @@ public function __construct(
private ProductRepositoryInterface $productRepository,
private LoggerInterface $logger,
private EntityManagerInterface $entityManager,
private ProductGroupProcessor $productGroupProcessor,
) {
$this->productGroups = [];
}
Expand All @@ -41,6 +43,8 @@ public function __invoke(PipelinePayloadInterface $payload): PipelinePayloadInte
* } $resource
*/
foreach ($resourceCursor as $resource) {
$this->productGroupProcessor->process($resource);

if (null === $resource['parent']) {
continue;
}
Expand Down
Loading

0 comments on commit 88c5c03

Please sign in to comment.