custom/plugins/NetiNextStoreLocator/src/Decorator/EntityRepositoryDecorator.php line 130

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace NetInventors\NetiNextStoreLocator\Decorator;
  3. use NetInventors\NetiNextStoreLocator\Subscriber\ImportExportSubscriber;
  4. use Shopware\Core\Framework\Context;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
  6. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Write\CloneBehavior;
  14. use Shopware\Core\Framework\Uuid\Uuid;
  15. class EntityRepositoryDecorator implements EntityRepositoryInterface
  16. {
  17.     private const COUNTRY_ISOS = [
  18.         '2'  => 'DE',
  19.         '3'  => 'AE',
  20.         '4'  => 'AU',
  21.         '5'  => 'BE',
  22.         '7'  => 'DK',
  23.         '8'  => 'FI',
  24.         '9'  => 'FR',
  25.         '10' => 'GR',
  26.         '11' => 'GB',
  27.         '12' => 'IE',
  28.         '13' => 'IS',
  29.         '14' => 'IT',
  30.         '15' => 'JP',
  31.         '16' => 'CA',
  32.         '18' => 'LU',
  33.         '20' => 'NA',
  34.         '21' => 'NL',
  35.         '22' => 'NO',
  36.         '23' => 'AT',
  37.         '24' => 'PT',
  38.         '25' => 'SE',
  39.         '26' => 'CH',
  40.         '27' => 'ES',
  41.         '28' => 'US',
  42.         '29' => 'LI',
  43.         '30' => 'PL',
  44.         '31' => 'HU',
  45.         '32' => 'TR',
  46.         '33' => 'CZ',
  47.         '34' => 'SK',
  48.         '35' => 'RO',
  49.         '36' => 'BR',
  50.         '37' => 'IL',
  51.     ];
  52.     /**
  53.      * @var EntityRepositoryInterface
  54.      */
  55.     private $repository;
  56.     /**
  57.      * @var EntityRepositoryInterface
  58.      */
  59.     private $salesChannelRepository;
  60.     /**
  61.      * @var EntityRepositoryInterface
  62.      */
  63.     private $countryRepository;
  64.     /**
  65.      * @var EntityRepositoryInterface
  66.      */
  67.     private $countryStateRepository;
  68.     /** @var array<string, string> */
  69.     private array $cachedCountryIds       = [];
  70.     /** @var array<string, string> */
  71.     private array $cachedIsoCountryIds    = [];
  72.     /** @var array<string, string> */
  73.     private array $cachedSalesChannelIds  = [];
  74.     /** @var string[] */
  75.     private array $defaultSalesChannelIds = [];
  76.     /**
  77.      * EntityRepositoryDecorator constructor.
  78.      *
  79.      * @param EntityRepositoryInterface $repository
  80.      * @param EntityRepositoryInterface $salesChannelRepository
  81.      * @param EntityRepositoryInterface $countryRepository
  82.      * @param EntityRepositoryInterface $countryStateRepository
  83.      */
  84.     public function __construct(
  85.         EntityRepositoryInterface $repository,
  86.         EntityRepositoryInterface $salesChannelRepository,
  87.         EntityRepositoryInterface $countryRepository,
  88.         EntityRepositoryInterface $countryStateRepository
  89.     ) {
  90.         $this->repository             $repository;
  91.         $this->salesChannelRepository $salesChannelRepository;
  92.         $this->countryRepository      $countryRepository;
  93.         $this->countryStateRepository $countryStateRepository;
  94.     }
  95.     public function getDefinition(): EntityDefinition
  96.     {
  97.         return $this->repository->getDefinition();
  98.     }
  99.     public function aggregate(Criteria $criteriaContext $context): AggregationResultCollection
  100.     {
  101.         return $this->repository->aggregate($criteria$context);
  102.     }
  103.     public function searchIds(Criteria $criteriaContext $context): IdSearchResult
  104.     {
  105.         return $this->repository->searchIds($criteria$context);
  106.     }
  107.     public function clone(string $idContext $context, ?string $newId null, ?CloneBehavior $behavior null): EntityWrittenContainerEvent
  108.     {
  109.         return $this->repository->clone($id$context$newId$behavior);
  110.     }
  111.     public function search(Criteria $criteriaContext $context): EntitySearchResult
  112.     {
  113.         return $this->repository->search($criteria$context);
  114.     }
  115.     public function update(array $dataContext $context): EntityWrittenContainerEvent
  116.     {
  117.         return $this->repository->update($data$context);
  118.     }
  119.     public function upsert(array $dataContext $context): EntityWrittenContainerEvent
  120.     {
  121.         if ($context->hasState(ImportExportSubscriber::STATE_IMPORT)) {
  122.             $data $this->prepareDataForImport($data$context);
  123.         }
  124.         return $this->repository->upsert($data$context);
  125.     }
  126.     public function create(array $dataContext $context): EntityWrittenContainerEvent
  127.     {
  128.         return $this->repository->create($data$context);
  129.     }
  130.     public function delete(array $dataContext $context): EntityWrittenContainerEvent
  131.     {
  132.         return $this->repository->delete($data$context);
  133.     }
  134.     public function createVersion(string $idContext $context, ?string $name null, ?string $versionId null): string
  135.     {
  136.         return $this->repository->createVersion($id$context$name$versionId);
  137.     }
  138.     public function merge(string $versionIdContext $context): void
  139.     {
  140.         $this->repository->merge($versionId$context);
  141.     }
  142.     private function prepareDataForImport(array $dataContext $context): array
  143.     {
  144.         $data[0]['countryId'] = $this->getCountryId($data[0]['countryId'], $context);
  145.         $data[0]['id']        = $this->createStoreId($data[0], $context);
  146.         /**
  147.          * Due to the condition above data must be an array
  148.          *
  149.          * @psalm-suppress MixedArgument
  150.          */
  151.         $data[0]['showAlways'] = $this->setShowAlways($data[0]);
  152.         if (isset($data[0]['salesChannels'])) {
  153.             /**
  154.              * @var array $salesChannels
  155.              * @psalm-suppress MixedArrayAccess - It has to be available because it is checked by isset
  156.              */
  157.             $salesChannels $data[0]['salesChannels'];
  158.             /** @psalm-suppress MixedArrayAssignment */
  159.             $data[0]['salesChannels'] = $this->assignSalesChannel($salesChannels$context);
  160.         } else {
  161.             $salesChannelIds $this->getSalesChannelsIds($context);
  162.             unset($data[0]['salesChannels']);
  163.             foreach ($salesChannelIds as $channelId) {
  164.                 $data[0]['salesChannels'][] = [ 'id' => $channelId ];
  165.             }
  166.         }
  167.         if (isset($data[0]['countryId'])) {
  168.             $data[0]['countryId'] = $this->assignCountryIdByIso($data[0], $context);
  169.             if (isset($data[0]['country'])) {
  170.                 unset($data[0]['country']);
  171.             }
  172.             if (isset($data[0]['countryState'])) {
  173.                 $data[0]['countryStateId'] = $this->assignCountryStateByShortCode($data[0], $context);
  174.                 unset($data[0]['countryState']);
  175.             }
  176.         }
  177.         return $data;
  178.     }
  179.     private function getSalesChannelsIds(Context $context): array
  180.     {
  181.         if (empty($this->defaultSalesChannelIds)) {
  182.             /** @var string[] $ids */
  183.             $ids $this->salesChannelRepository->searchIds(new Criteria(), $context)->getIds();
  184.             $this->defaultSalesChannelIds $ids;
  185.         }
  186.         return $this->defaultSalesChannelIds;
  187.     }
  188.     /**
  189.      * @param string  $id
  190.      * @param Context $context
  191.      *
  192.      * @return string
  193.      */
  194.     private function getCountryId(string $idContext $context): ?string
  195.     {
  196.         if ($this->isMatchingCountryId($id$context)) {
  197.             return $id;
  198.         }
  199.         return $this->getCountryByIso(self::COUNTRY_ISOS[$id] ?? 'DE'$context);
  200.     }
  201.     /**
  202.      * @param array   $data
  203.      * @param Context $context
  204.      *
  205.      * @return string
  206.      */
  207.     private function createStoreId(array $dataContext $context): string
  208.     {
  209.         unset($data['salesChannels'], $data['id']);
  210.         $criteria = new Criteria();
  211.         foreach ($data as $key => $value) {
  212.             if ($key !== 'country' && !empty($value) && !is_array($value)) {
  213.                 $criteria->addFilter(new EqualsFilter($key$value));
  214.             }
  215.         }
  216.         $result $this->repository->searchIds($criteria$context)->firstId();
  217.         if (null === $result) {
  218.             $result Uuid::randomHex();
  219.         }
  220.         return $result;
  221.     }
  222.     /**
  223.      * @param array $data
  224.      *
  225.      * @return string
  226.      */
  227.     private function setShowAlways(array $data): string
  228.     {
  229.         $newDisplay 'no';
  230.         if (!isset($data['showAlways'])) {
  231.             return $newDisplay;
  232.         }
  233.         $showAlways = (string) $data['showAlways'];
  234.         switch ($showAlways) {
  235.             case '0':
  236.                 break;
  237.             case '1':
  238.                 $newDisplay 'top';
  239.                 break;
  240.             case '2':
  241.                 $newDisplay 'bottom';
  242.                 break;
  243.         }
  244.         return $newDisplay;
  245.     }
  246.     /**
  247.      * @param string  $salesChannelId
  248.      * @param Context $context
  249.      *
  250.      * @return bool
  251.      */
  252.     private function isMatchingSalesChannel(string $salesChannelIdContext $context): bool
  253.     {
  254.         if (isset($this->cachedSalesChannelIds[$salesChannelId])) {
  255.             return true;
  256.         }
  257.         $criteria = new Criteria([ $salesChannelId ]);
  258.         $result   $this->salesChannelRepository->searchIds($criteria$context)->firstId();
  259.         if (is_string($result)) {
  260.             $this->cachedSalesChannelIds[$salesChannelId] = $result;
  261.         }
  262.         return isset($this->cachedSalesChannelIds[$salesChannelId]);
  263.     }
  264.     /**
  265.      * @param array   $salesChannels
  266.      * @param Context $context
  267.      *
  268.      * @return array
  269.      */
  270.     private function assignSalesChannel(array $salesChannelsContext $context): array
  271.     {
  272.         foreach ($salesChannels as $key => $salesChannel) {
  273.             if (!$this->isMatchingSalesChannel($salesChannel['id'], $context)) {
  274.                 unset($salesChannels[$key]);
  275.             }
  276.         }
  277.         if (empty($salesChannels)) {
  278.             $defaultSalesChannelIds $this->getSalesChannelsIds($context);
  279.             foreach ($defaultSalesChannelIds as $defaultSalesChannelId) {
  280.                 $salesChannels[] = [ 'id' => $defaultSalesChannelId ];
  281.             }
  282.         }
  283.         return $salesChannels;
  284.     }
  285.     /**
  286.      * @param array   $data
  287.      * @param Context $context
  288.      *
  289.      * @return string
  290.      */
  291.     private function assignCountryIdByIso(array $dataContext $context): ?string
  292.     {
  293.         if (isset($data['countryId'], $data['country']['iso']) && !$this->isMatchingCountryId($data['countryId'], $context)) {
  294.             $data['countryId'] = $this->getCountryByIso($data['country']['iso'], $context);
  295.         }
  296.         if (!isset($data['countryId'])) {
  297.             $data['countryId'] = $this->getCountryId('deutsch'$context);
  298.         }
  299.         return $data['countryId'];
  300.     }
  301.     /**
  302.      * @param array   $data
  303.      * @param Context $context
  304.      *
  305.      * @return string
  306.      */
  307.     private function assignCountryStateByShortCode(array $dataContext $context): string
  308.     {
  309.         if (isset($data['countryStateId'], $data['countryState']['shortCode']) && !$this->isMatchingCountryStateId($data['countryStateId'], $context)) {
  310.             $data['countryStateId'] = $this->getCountryStateByShortCode($data['countryState']['shortCode'], $context);
  311.         }
  312.         return $data['countryStateId'];
  313.     }
  314.     /**
  315.      * @param string  $countryId
  316.      * @param Context $context
  317.      *
  318.      * @return bool
  319.      */
  320.     private function isMatchingCountryId(string $countryIdContext $context): bool
  321.     {
  322.         if (isset($this->cachedCountryIds[$countryId])) {
  323.             return true;
  324.         }
  325.         $criteria = new Criteria([ $countryId ]);
  326.         $result   $this->countryRepository->searchIds($criteria$context)->firstId();
  327.         if (is_string($result)) {
  328.             $this->cachedCountryIds[$result] = $result;
  329.         }
  330.         return isset($this->cachedCountryIds[$countryId]);
  331.     }
  332.     /**
  333.      * @param string  $iso
  334.      * @param Context $context
  335.      *
  336.      * @return string|null
  337.      */
  338.     private function getCountryByIso(string $isoContext $context): ?string
  339.     {
  340.         if (isset($this->cachedIsoCountryIds[$iso])) {
  341.             return $this->cachedIsoCountryIds[$iso];
  342.         }
  343.         $criteria = new Criteria();
  344.         $criteria->addFilter(new EqualsFilter('iso'$iso));
  345.         $countryId $this->countryRepository->searchIds($criteria$context)->firstId();
  346.         if (is_string($countryId)) {
  347.             $this->cachedIsoCountryIds[$iso] = $countryId;
  348.         }
  349.         return $countryId;
  350.     }
  351.     /**
  352.      * @param string  $countryStateId
  353.      * @param Context $context
  354.      *
  355.      * @return bool
  356.      */
  357.     private function isMatchingCountryStateId(string $countryStateIdContext $context): bool
  358.     {
  359.         $criteria = new Criteria([ $countryStateId]);
  360.         $result   $this->countryStateRepository->searchIds($criteria$context)->getIds();
  361.         return !empty($result);
  362.     }
  363.     /**
  364.      * @param string  $shortCode
  365.      * @param Context $context
  366.      *
  367.      * @return string|null
  368.      */
  369.     private function getCountryStateByShortCode(string $shortCodeContext $context): ?string
  370.     {
  371.         $criteria = new Criteria();
  372.         $criteria->addFilter(new EqualsFilter('shortCode'$shortCode));
  373.         return $this->countryStateRepository->searchIds($criteria$context)->firstId();
  374.     }
  375. }