Skip to content

Commit 8cc94c9

Browse files
Merge pull request #183 from synolia/fix/various-fixes
Clean removed product assets from Akeneo
2 parents 8169ee8 + ccbae74 commit 8cc94c9

19 files changed

+169
-62
lines changed

src/Checker/Product/IsProductProcessableChecker.php

+32-50
Original file line numberDiff line numberDiff line change
@@ -5,81 +5,63 @@
55
namespace Synolia\SyliusAkeneoPlugin\Checker\Product;
66

77
use Psr\Log\LoggerInterface;
8-
use Synolia\SyliusAkeneoPlugin\Client\ClientFactoryInterface;
98
use Synolia\SyliusAkeneoPlugin\Config\AkeneoAxesEnum;
9+
use Synolia\SyliusAkeneoPlugin\Exceptions\Retriever\FamilyVariantNotFountException;
1010
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;
11+
use Synolia\SyliusAkeneoPlugin\Retriever\FamilyVariantRetrieverInterface;
1112

1213
final class IsProductProcessableChecker implements IsProductProcessableCheckerInterface
1314
{
1415
private const ONE_VARIATION_AXIS = 1;
1516

16-
private array $familyVariants;
17-
1817
public function __construct(
19-
private ClientFactoryInterface $clientFactory,
2018
private LoggerInterface $logger,
2119
private ApiConnectionProviderInterface $apiConnectionProvider,
20+
private FamilyVariantRetrieverInterface $familyVariantRetriever,
2221
) {
23-
$this->familyVariants = [];
2422
}
2523

2624
public function check(array $resource): bool
2725
{
28-
if ('' === $resource['code'] || null === $resource['code']) {
29-
$this->logger->warning('Skipping product import because the code is missing.', ['resource' => $resource]);
30-
31-
return false;
32-
}
26+
try {
27+
if ('' === $resource['code'] || null === $resource['code']) {
28+
$this->logger->warning('Skipping product import because the code is missing.', ['resource' => $resource]);
3329

34-
if (!isset($resource['family'])) {
35-
$this->logger->warning('Skipping product import because the family is missing.', ['resource' => $resource]);
30+
return false;
31+
}
3632

37-
return false;
38-
}
33+
if (!isset($resource['family'])) {
34+
$this->logger->warning('Skipping product import because the family is missing.', ['resource' => $resource]);
3935

40-
$familyVariantPayload = $this->getFamilyVariant((string) $resource['family'], (string) $resource['family_variant']);
36+
return false;
37+
}
4138

42-
$numberOfVariationAxis = isset($familyVariantPayload['variant_attribute_sets']) ? \count($familyVariantPayload['variant_attribute_sets']) : 0;
39+
$familyVariantPayload = $this->familyVariantRetriever->getVariant((string) $resource['family'], (string) $resource['family_variant']);
4340

44-
if (null === $resource['parent'] &&
45-
$numberOfVariationAxis > self::ONE_VARIATION_AXIS &&
46-
$this->apiConnectionProvider->get()->getAxeAsModel() === AkeneoAxesEnum::FIRST
47-
) {
48-
$this->logger->warning('Skipping product import because the parent is null and it has more than one variation axis.', ['resource' => $resource]);
41+
$numberOfVariationAxis = isset($familyVariantPayload['variant_attribute_sets']) ? \count($familyVariantPayload['variant_attribute_sets']) : 0;
4942

50-
return false;
51-
}
43+
if (null === $resource['parent'] &&
44+
$numberOfVariationAxis > self::ONE_VARIATION_AXIS &&
45+
$this->apiConnectionProvider->get()->getAxeAsModel() === AkeneoAxesEnum::FIRST
46+
) {
47+
$this->logger->debug('Skipping product import because the parent is null and it has more than one variation axis.', ['resource' => $resource]);
5248

53-
// The common model will not be imported. The first axe on akeneo will become the product on sylius and the next axe on akeneo will become an option for the product variant
54-
if (null !== $resource['parent'] &&
55-
$numberOfVariationAxis === 2 &&
56-
$this->apiConnectionProvider->get()->getAxeAsModel() !== AkeneoAxesEnum::FIRST
57-
) {
58-
$this->logger->warning('Skipping product import because the parent is null, and it has more than one variation axis.', ['resource' => $resource]);
49+
return false;
50+
}
5951

60-
return false;
61-
}
52+
// The common model will not be imported. The first axe on akeneo will become the product on sylius and the next axe on akeneo will become an option for the product variant
53+
if (null !== $resource['parent'] &&
54+
$numberOfVariationAxis === 2 &&
55+
$this->apiConnectionProvider->get()->getAxeAsModel() !== AkeneoAxesEnum::FIRST
56+
) {
57+
$this->logger->debug('Skipping product import because the parent is null, and it has more than one variation axis.', ['resource' => $resource]);
6258

63-
return true;
64-
}
59+
return false;
60+
}
6561

66-
private function getFamilyVariant(string $family, string $familyVariant): array
67-
{
68-
if (isset($this->familyVariants[$family][$familyVariant])) {
69-
return $this->familyVariants[$family][$familyVariant];
62+
return true;
63+
} catch (FamilyVariantNotFountException) {
64+
return false;
7065
}
71-
72-
$familyVariantPayload = $this->clientFactory
73-
->createFromApiCredentials()
74-
->getFamilyVariantApi()
75-
->get(
76-
$family,
77-
$familyVariant,
78-
)
79-
;
80-
81-
$this->familyVariants[$family][$familyVariant] = $familyVariantPayload;
82-
83-
return $familyVariantPayload;
8466
}
8567
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Synolia\SyliusAkeneoPlugin\Exceptions\Retriever;
6+
7+
class FamilyVariantNotFountException extends \Exception
8+
{
9+
}

src/Form/Type/LocalesChoiceType.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ public function __construct(private SyliusAkeneoLocaleCodeProvider $syliusAkeneo
1717

1818
public function configureOptions(OptionsResolver $resolver): void
1919
{
20+
$usedLocalesOnBothPlatforms = $this->syliusAkeneoLocaleCodeProvider->getUsedLocalesOnBothPlatforms();
21+
22+
$usedLocalesOnBothPlatforms = array_map(function ($locale) {
23+
return $this->syliusAkeneoLocaleCodeProvider->getAkeneoLocale($locale);
24+
}, $usedLocalesOnBothPlatforms);
25+
2026
$resolver->setDefaults([
21-
'choices' => $this->syliusAkeneoLocaleCodeProvider->getUsedLocalesOnBothPlatforms(),
27+
'choices' => array_combine($usedLocalesOnBothPlatforms, $usedLocalesOnBothPlatforms),
2228
'multiple' => true,
2329
'required' => false,
2430
]);
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Synolia\SyliusAkeneoPlugin\Processor\Product;
6+
7+
use Sylius\Component\Core\Model\ProductInterface;
8+
use Synolia\SyliusAkeneoPlugin\Checker\EditionCheckerInterface;
9+
use Synolia\SyliusAkeneoPlugin\Repository\AssetRepository;
10+
11+
final class AssetProcessor implements AssetProcessorInterface
12+
{
13+
public static function getDefaultPriority(): int
14+
{
15+
return 850;
16+
}
17+
18+
public function __construct(
19+
private EditionCheckerInterface $editionChecker,
20+
private AssetRepository $assetRepository,
21+
) {
22+
}
23+
24+
public function process(ProductInterface $product, array $resource): void
25+
{
26+
/*
27+
* I need to clean the product-assets association to clean removed product asset from akeneo but
28+
* I couldn't clean assets using $product->getAssets()->clear() before re-importing them as the unit of work still
29+
* thinks that the assets are to be deleted and I didn't want to use the entity manager flush as we don't want
30+
* to import an empty product.
31+
*/
32+
$this->assetRepository->cleanAssetsForProduct($product);
33+
}
34+
35+
public function support(ProductInterface $product, array $resource): bool
36+
{
37+
$isEnterprise = $this->editionChecker->isEnterprise() || $this->editionChecker->isSerenityEdition();
38+
39+
if (!$isEnterprise) {
40+
return false;
41+
}
42+
43+
if (!\method_exists($product, 'getAssets')) {
44+
return false;
45+
}
46+
47+
return true;
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Synolia\SyliusAkeneoPlugin\Processor\Product;
6+
7+
interface AssetProcessorInterface extends ProductProcessorInterface
8+
{
9+
}

src/Processor/Product/ImagesProcessor.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ public function support(ProductInterface $product, array $resource): bool
3131
$imageAttributes = $this->getProductConfiguration()->getAkeneoImageAttributes();
3232

3333
if (null === $imageAttributes || 0 === \count($imageAttributes)) {
34-
$this->logger->warning(Messages::noConfigurationSet('at least one Akeneo image attribute', 'Import image'));
34+
$this->logger->debug(Messages::noConfigurationSet('at least one Akeneo image attribute', 'Import image'));
3535

3636
return false;
3737
}
3838

3939
return true;
4040
} catch (\Throwable $throwable) {
41+
$this->logger->warning($throwable->getMessage());
42+
4143
return false;
4244
}
4345
}

src/Processor/ProductAttribute/AssetAttributeProcessor.php

+10-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Synolia\SyliusAkeneoPlugin\Provider\AkeneoAttributeDataProviderInterface;
2222
use Synolia\SyliusAkeneoPlugin\Provider\SyliusAkeneoLocaleCodeProvider;
2323
use Synolia\SyliusAkeneoPlugin\Transformer\AkeneoAttributeToSyliusAttributeTransformerInterface;
24+
use Webmozart\Assert\Assert;
2425

2526
/**
2627
* @SuppressWarnings(PHPMD.NPathComplexity)
@@ -54,6 +55,14 @@ public function support(string $attributeCode, array $context = []): bool
5455
return false;
5556
}
5657

58+
if (!$context['model'] instanceof ProductInterface) {
59+
return false;
60+
}
61+
62+
if (!\method_exists($context['model'], 'getAssets')) {
63+
return false;
64+
}
65+
5766
$transformedAttributeCode = $this->akeneoAttributeToSyliusAttributeTransformer->transform($attributeCode);
5867

5968
/** @var AttributeInterface $attribute */
@@ -74,9 +83,7 @@ public function process(string $attributeCode, array $context = []): void
7483
static::class,
7584
));
7685

77-
if (!$context['model'] instanceof ProductInterface) {
78-
return;
79-
}
86+
Assert::isInstanceOf($context['model'], ProductInterface::class);
8087

8188
$transformedAttributeCode = $this->akeneoAttributeToSyliusAttributeTransformer->transform($attributeCode);
8289

src/Processor/ProductAttribute/ProductAttributeAkeneoAttributeProcessor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public function process(string $attributeCode, array $context = []): void
8989
$context['scope'],
9090
);
9191
} catch (MissingLocaleTranslationException | MissingLocaleTranslationOrScopeException|MissingScopeException|TranslationNotFoundException $error) {
92-
$this->logger->warning('Attribute translation error', [
92+
$this->logger->debug('Attribute translation error', [
9393
'attribute_code' => $attributeCode,
9494
'sylius_locale' => $syliusLocale,
9595
'context' => $context,

src/Processor/ProductGroup/ProductGroupProcessor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ private function createGroupForCodeAndFamily(
4444
if ($productGroup instanceof ProductGroupInterface) {
4545
$this->productGroupsMapping[$code] = $productGroup;
4646

47-
$this->logger->info(sprintf(
47+
$this->logger->debug(sprintf(
4848
'Skipping ProductGroup "%s" for family "%s" as it already exists.',
4949
$code,
5050
$family,

src/Provider/Asset/AssetValueBuilderProvider.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function hasSupportedBuilder(string $assetFamilyCode, string $assetCode):
7171
return true;
7272
}
7373
} catch (UnsupportedAttributeTypeException $throwable) {
74-
$this->akeneoLogger->warning('Unsupported AssetAttributeType', [
74+
$this->akeneoLogger->info('Unsupported AssetAttributeType', [
7575
'family_code' => $assetFamilyCode,
7676
'asset_code' => $assetCode,
7777
]);

src/Repository/AssetRepository.php

+14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Synolia\SyliusAkeneoPlugin\Repository;
66

7+
use Doctrine\ORM\Query\ResultSetMapping;
78
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
9+
use Sylius\Component\Core\Model\ProductInterface;
810
use Synolia\SyliusAkeneoPlugin\Entity\Asset;
911

1012
/**
@@ -15,4 +17,16 @@
1517
*/
1618
final class AssetRepository extends EntityRepository
1719
{
20+
public function cleanAssetsForProduct(ProductInterface $product): void
21+
{
22+
$query = $this->_em
23+
->createNativeQuery(
24+
'DELETE FROM akeneo_assets_products WHERE owner_id = :product_id',
25+
new ResultSetMapping(),
26+
)
27+
->setParameter('product_id', $product->getId())
28+
;
29+
30+
$query->execute();
31+
}
1832
}

src/Retriever/FamilyVariantRetriever.php

+19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Psr\Log\LoggerInterface;
99
use Symfony\Contracts\Cache\CacheInterface;
1010
use Synolia\SyliusAkeneoPlugin\Component\Cache\CacheKey;
11+
use Synolia\SyliusAkeneoPlugin\Exceptions\Retriever\FamilyVariantNotFountException;
1112
use Synolia\SyliusAkeneoPlugin\Provider\Configuration\Api\ApiConnectionProviderInterface;
1213

1314
final class FamilyVariantRetriever implements FamilyVariantRetrieverInterface
@@ -44,4 +45,22 @@ public function getVariants(string $familyCode): array
4445
return $familyVariants;
4546
});
4647
}
48+
49+
/**
50+
* @throws FamilyVariantNotFountException
51+
*/
52+
public function getVariant(string $familyCode, string $familyVariantCode): array
53+
{
54+
$familyVariants = $this->getVariants($familyCode);
55+
56+
foreach ($familyVariants as $familyVariant) {
57+
if ($familyVariant['code'] !== $familyVariantCode) {
58+
continue;
59+
}
60+
61+
return $familyVariant;
62+
}
63+
64+
throw new FamilyVariantNotFountException('Could not determine variant');
65+
}
4766
}

src/Retriever/FamilyVariantRetrieverInterface.php

+2
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
interface FamilyVariantRetrieverInterface
88
{
99
public function getVariants(string $familyCode): array;
10+
11+
public function getVariant(string $familyCode, string $familyVariantCode): array;
1012
}

src/Task/AssociationType/ProcessAssociationTypeTask.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public function __invoke(PipelinePayloadInterface $payload): PipelinePayloadInte
4949

5050
$queryParameters['search'] = $event->getFilters();
5151
} catch (CommandContextIsNullException) {
52-
$queryParameters = [];
52+
} finally {
53+
$this->logger->notice('Filters', $queryParameters);
5354
}
5455

5556
$page = $payload->getAkeneoPimClient()->getAssociationTypeApi()->listPerPage(

src/Task/Attribute/ProcessAttributeTask.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public function __invoke(PipelinePayloadInterface $payload): PipelinePayloadInte
5050
$queryParameters['search'] = $event->getFilters();
5151
$queryParameters['with_table_select_options'] = true;
5252
} catch (CommandContextIsNullException) {
53-
$queryParameters = [];
53+
} finally {
54+
$this->logger->notice('Filters', $queryParameters);
5455
}
5556

5657
$queryParameters = \array_merge_recursive($queryParameters, $payload->getCustomFilters());

src/Task/Category/RetrieveCategoriesTask.php

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public function __invoke(PipelinePayloadInterface $payload): PipelinePayloadInte
5353
}
5454

5555
$queryParameters = \array_merge_recursive($queryParameters, $payload->getCustomFilters());
56+
$this->logger->notice('Filters', $queryParameters);
5657

5758
$resources = $payload->getAkeneoPimClient()->getCategoryApi()->all(
5859
$this->apiConnectionProvider->get()->getPaginationSize(),

src/Task/Product/ProcessProductsTask.php

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function __invoke(PipelinePayloadInterface $payload): PipelinePayloadInte
6767
}
6868

6969
$queryParameters = array_merge_recursive($queryParameters, $payload->getCustomFilters());
70+
$this->logger->notice('Filters', $queryParameters);
7071

7172
/** @var \Akeneo\Pim\ApiClient\Pagination\PageInterface|null $resources */
7273
$resources = $payload->getAkeneoPimClient()->getProductApi()->listPerPage(

0 commit comments

Comments
 (0)