<?php declare(strict_types=1); namespace Synolia\SyliusAkeneoPlugin\Processor\ProductAttribute; use Akeneo\Pim\ApiClient\AkeneoPimClientInterface; use Psr\Log\LoggerInterface; use Sylius\Component\Attribute\Model\AttributeInterface; use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Product\Model\ProductAttributeValueInterface; use Sylius\Component\Resource\Factory\FactoryInterface; use Sylius\Component\Resource\Repository\RepositoryInterface; use Synolia\SyliusAkeneoPlugin\Checker\EditionCheckerInterface; use Synolia\SyliusAkeneoPlugin\Component\Attribute\AttributeType\AssetAttributeType; use Synolia\SyliusAkeneoPlugin\Exceptions\Attribute\MissingLocaleTranslationException; use Synolia\SyliusAkeneoPlugin\Exceptions\Attribute\MissingLocaleTranslationOrScopeException; use Synolia\SyliusAkeneoPlugin\Exceptions\Attribute\MissingScopeException; use Synolia\SyliusAkeneoPlugin\Exceptions\Attribute\TranslationNotFoundException; use Synolia\SyliusAkeneoPlugin\Exceptions\UnsupportedAttributeTypeException; use Synolia\SyliusAkeneoPlugin\Provider\AkeneoAttributeDataProviderInterface; use Synolia\SyliusAkeneoPlugin\Provider\SyliusAkeneoLocaleCodeProvider; use Synolia\SyliusAkeneoPlugin\Transformer\AkeneoAttributeToSyliusAttributeTransformerInterface; use Webmozart\Assert\Assert; /** * @SuppressWarnings(PHPMD.NPathComplexity) */ final class AssetAttributeProcessor implements AkeneoAttributeProcessorInterface { public function __construct( private SyliusAkeneoLocaleCodeProvider $syliusAkeneoLocaleCodeProvider, private AkeneoAttributeToSyliusAttributeTransformerInterface $akeneoAttributeToSyliusAttributeTransformer, private RepositoryInterface $productAttributeRepository, private LoggerInterface $logger, private RepositoryInterface $productAttributeValueRepository, private FactoryInterface $productAttributeValueFactory, private AkeneoAttributeDataProviderInterface $akeneoAttributeDataProvider, private AkeneoPimClientInterface $akeneoPimClient, private AssetProductAttributeProcessorInterface $akeneoAssetProductAttributeProcessor, private EditionCheckerInterface $editionChecker, ) { } public static function getDefaultPriority(): int { return 100; } public function support(string $attributeCode, array $context = []): bool { $isEnterprise = $this->editionChecker->isEnterprise() || $this->editionChecker->isSerenityEdition(); if (!$isEnterprise) { return false; } if (!$context['model'] instanceof ProductInterface) { return false; } if (!\method_exists($context['model'], 'getAssets')) { return false; } $transformedAttributeCode = $this->akeneoAttributeToSyliusAttributeTransformer->transform($attributeCode); /** @var AttributeInterface $attribute */ $attribute = $this->productAttributeRepository->findOneBy(['code' => $transformedAttributeCode]); if ($attribute instanceof AttributeInterface && $attribute->getType() === AssetAttributeType::TYPE) { return true; } return false; } public function process(string $attributeCode, array $context = []): void { $this->logger->debug(\sprintf( 'Attribute "%s" is being processed by "%s"', $attributeCode, static::class, )); Assert::isInstanceOf($context['model'], ProductInterface::class); $transformedAttributeCode = $this->akeneoAttributeToSyliusAttributeTransformer->transform($attributeCode); /** @var AttributeInterface $attribute */ $attribute = $this->productAttributeRepository->findOneBy(['code' => $transformedAttributeCode]); foreach ($context['data'] as $translation) { if (null !== $translation['locale'] && false === $this->syliusAkeneoLocaleCodeProvider->isActiveLocale($translation['locale'])) { continue; } if (null === $translation['locale']) { foreach ($this->syliusAkeneoLocaleCodeProvider->getUsedLocalesOnBothPlatforms() as $syliusLocale) { try { $this->setAttributeTranslation( $context['model'], $attribute, $context['data'], $syliusLocale, $attributeCode, $context['scope'], ); } catch (TranslationNotFoundException|MissingScopeException|MissingLocaleTranslationOrScopeException|MissingLocaleTranslationException) { } } continue; } try { $this->setAttributeTranslation( $context['model'], $attribute, $context['data'], $translation['locale'], $attributeCode, $context['scope'], ); } catch (TranslationNotFoundException|MissingScopeException|MissingLocaleTranslationOrScopeException|MissingLocaleTranslationException) { } } foreach ($context['data'] as $assetCodes) { foreach ($assetCodes['data'] as $assetCode) { $assetResource = $this->akeneoPimClient->getAssetManagerApi()->get($attributeCode, $assetCode); $this->handleAssetByFamilyResource($context['model'], $attributeCode, $assetResource); } } } private function handleAssetByFamilyResource( ProductInterface $model, string $assetFamilyCode, array $assetResource, ): void { foreach ($assetResource['values'] as $attributeCode => $assetAttributeResource) { try { $this->akeneoAssetProductAttributeProcessor->process( $model, $assetFamilyCode, $assetResource['code'], $attributeCode, $assetAttributeResource, ); } catch (UnsupportedAttributeTypeException $attributeTypeException) { $this->logger->warning('Unsupported attribute type', ['ex' => $attributeTypeException]); } } } /** * @throws MissingLocaleTranslationOrScopeException * @throws MissingLocaleTranslationException * @throws MissingScopeException * @throws TranslationNotFoundException */ private function setAttributeTranslation( ProductInterface $product, AttributeInterface $attribute, array $translations, string $locale, string $attributeCode, string $scope, ): void { $attributeValue = $this->productAttributeValueRepository->findOneBy([ 'subject' => $product, 'attribute' => $attribute, 'localeCode' => $locale, ]); if (!$attributeValue instanceof ProductAttributeValueInterface) { /** @var ProductAttributeValueInterface $attributeValue */ $attributeValue = $this->productAttributeValueFactory->createNew(); } $attributeValue->setLocaleCode($locale); $attributeValue->setAttribute($attribute); $attributeValueValue = $this->akeneoAttributeDataProvider->getData($attributeCode, $translations, $locale, $scope); $attributeValue->setValue($attributeValueValue); $product->addAttribute($attributeValue); } }