custom/plugins/AcrisCountriesCS/src/AcrisCountriesCS.php line 20

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Acris\Countries;
  3. use Doctrine\DBAL\DBALException;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
  6. use Shopware\Core\Framework\Plugin;
  7. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  8. use Shopware\Core\Framework\Plugin\Context\InstallContext;
  9. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  10. use Shopware\Core\Framework\Context;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Doctrine\DBAL\Connection;
  15. use Shopware\Core\System\Country\CountryEntity;
  16. use Shopware\Core\System\Language\LanguageEntity;
  17. class AcrisCountriesCS extends Plugin
  18. {
  19.     const COUNTRY_LOCALES_CSV_DATA_MATCH = [
  20.         [
  21.             'locales' => [
  22.                 'en-AS''en-AU''en-BE''en-BW''en-BZ''en-CA''en-GB''en-GU''en-HK',
  23.                 'en-IE''en-IN''en-JM''en-MH''en-MP''en-MT''en-NA''en-NZ''en-PH',
  24.                 'en-PK''en-SG''en-TT''en-UM''en-US''en-VI''en-ZA''en-ZW'
  25.             ],
  26.             'name' => 4,
  27.             'acris_countries_regex_description' => 16
  28.         ],
  29.         [
  30.             'locales' => [
  31.                 'de-AT''de-BE''de-CH''de-DE''de-LI''de-LU'
  32.             ],
  33.             'name' => 1,
  34.             'acris_countries_regex_description' => 15
  35.         ],
  36.         [
  37.             'locales' => [
  38.                 'fr-BE''fr-CA''fr-CH''fr-FR''fr-LU''fr-MC''fr-SN'
  39.             ],
  40.             'name' => 17,
  41.             'acris_countries_regex_description' => 18
  42.         ],
  43.         [
  44.             'locales' => [
  45.                 'it-CH''it-IT'
  46.             ],
  47.             'name' => 19,
  48.             'acris_countries_regex_description' => 20
  49.         ],
  50.         [
  51.             'locales' => [
  52.                 'es-AR''es-BO''es-CL''es-CO''es-CR''es-DO''es-EC''es-ES''es-GT',
  53.                 'es-HN''es-MX''es-NI''es-PA''es-PE''es-PR''es-PY''es-SV''es-US',
  54.                 'es-UY''es-VE'
  55.             ],
  56.             'name' => 21,
  57.             'acris_countries_regex_description' => 22
  58.         ]
  59.     ];
  60.     private $csvData = array();
  61.     public function update(UpdateContext $context): void
  62.     {
  63.         $this->readData();
  64.         $this->insertCountryData($context->getContext());
  65.     }
  66.     public function install(InstallContext $context): void
  67.     {
  68.         $this->readData();
  69.         $this->insertCountryData($context->getContext());
  70.     }
  71.     private function getAvailableLocales(Context $context)
  72.     {
  73.         /** @var EntitySearchResult $languagesSearchResult */
  74.         $languagesSearchResult $this->container->get('language.repository')->search((new Criteria())->addAssociation('locale'), $context);
  75.         $locales = [];
  76.         /** @var LanguageEntity $languageEntity */
  77.         foreach ($languagesSearchResult->getElements() as $languageEntity) {
  78.             $locales[] = $languageEntity->getLocale()->getCode();
  79.         }
  80.         array_unique($locales);
  81.         return $locales;
  82.     }
  83.     private function readData(): void
  84.     {
  85.         $file $this->getPath() . "/Components/Resources/acris_country_list.csv";
  86.         $handle fopen($file"r");
  87.         if (empty($handle) === false) {
  88.             while (($data fgetcsv($handle1000";")) !== FALSE) {
  89.                 $this->csvData[] = $data;
  90.             }
  91.             fclose($handle);
  92.         }
  93.     }
  94.     private function insertCountryData(Context $context): void
  95.     {
  96.         /** @var EntityRepositoryInterface $countryRepository */
  97.         $countryRepository $this->container->get('country.repository');
  98.         $locales $this->getAvailableLocales($context);
  99.         $translationLocales $this->matchByAvailableLocales($locales);
  100.         $countryData = [];
  101.         for ($i 0$i sizeof($this->csvData); $i++) {
  102.             $translationsFull = [];
  103.             foreach ($translationLocales as $translationLocale) {
  104.                 $translationsFull[$translationLocale['locale']] = [
  105.                     'name' => $this->csvData[$i][$translationLocale['name']],
  106.                     'customFields' => [
  107.                         'acris_edit' => true,
  108.                         'acris_countries_regex' => $this->csvData[$i][6],
  109.                         'acris_countries_regex_description' => $this->csvData[$i][$translationLocale['acris_countries_regex_description']],
  110.                     ],
  111.                 ];
  112.             }
  113.             $countryData[] = [
  114.                 'iso' => $this->csvData[$i][2],
  115.                 'position' => 10,
  116.                 'active' => true,
  117.                 'shippingAvailable' => true,
  118.                 'iso3' => $this->csvData[$i][11],
  119.                 'translations' => $translationsFull
  120.             ];
  121.         }
  122.         foreach ($countryData as $country) {
  123.             $this->createEntityIfNotExists($countryRepository$context'iso'$country);
  124.         }
  125.     }
  126.     /**
  127.      * @param EntityRepositoryInterface $entityRepository
  128.      * @param Context $context
  129.      * @param string $identifierField
  130.      * @param array $countryDataFull
  131.      */
  132.     private function createEntityIfNotExists(EntityRepositoryInterface $entityRepositoryContext $contextstring $identifierField, array $countryDataFull): void
  133.     {
  134.         $shopwareCountries $entityRepository->search((new Criteria())->addFilter(new EqualsFilter($identifierField$countryDataFull[$identifierField]))->addAssociation('translations')->addAssociation('translations.language')->addAssociation('translations.language.locale'), $context);
  135.         if ($shopwareCountries->getTotal() === 0) {
  136.             $entityRepository->upsert([$countryDataFull], $context);
  137.         } else {
  138.             /** @var CountryEntity $country */
  139.             $country $shopwareCountries->first();
  140.             if(empty($country)) {
  141.                 return;
  142.             }
  143.             // merge translations by remove existing values
  144.             if(!empty($country->getTranslations())) {
  145.                 foreach ($country->getTranslations()->getElements() as $countryTranslationEntity) {
  146.                     if($countryTranslationEntity->getLanguage() && $countryTranslationEntity->getLanguage()->getLocale() && $countryTranslationEntity->getLanguage()->getLocale()->getCode()) {
  147.                         $code $countryTranslationEntity->getLanguage()->getLocale()->getCode();
  148.                         if(array_key_exists($code$countryDataFull['translations'])) {
  149.                             // when custom fields not empty -> remove custom fields
  150.                             if($countryTranslationEntity->getCustomFields() !== null && !empty($countryTranslationEntity->getCustomFields())) {
  151.                                 unset($countryDataFull['translations'][$code]['customFields']);
  152.                             }
  153.                             // when name not empty -> remove name
  154.                             if($countryTranslationEntity->getName() !== null && $countryTranslationEntity->getName() !== "") {
  155.                                 unset($countryDataFull['translations'][$code]['name']);
  156.                             }
  157.                             if(empty($countryDataFull['translations'][$code])) {
  158.                                 unset($countryDataFull['translations'][$code]);
  159.                             }
  160.                         }
  161.                     }
  162.                 }
  163.             }
  164.             $data = [
  165.                 'id' => $shopwareCountries->first()->getId(),
  166.                 'translations' => $countryDataFull['translations']
  167.             ];
  168.             $entityRepository->upsert([$data], $context);
  169.         }
  170.     }
  171.     public function uninstall(UninstallContext $context): void
  172.     {
  173.         if ($context->keepUserData()) {
  174.             return;
  175.         }
  176.         $this->cleanupDatabase($context->getContext());
  177.     }
  178.     private function cleanupDatabase(Context $context): void
  179.     {
  180.         /** @var EntityRepositoryInterface $countryRepository */
  181.         $countryRepository $this->container->get('country.repository');
  182.         $connection $this->container->get(Connection::class);
  183.         $acrisCountries $countryRepository->search((new Criteria())->addFilter(new ContainsFilter("customFields""\"acris_edit\":true")), $context);
  184.         foreach ($acrisCountries as $country) {
  185.             $id $country->getId();
  186.             $data = [
  187.                 'id' => $id,
  188.                 'active' => false,
  189.             ];
  190.             try {
  191.                 $connection->executeUpdate('DELETE FROM country WHERE lower(HEX(id)) LIKE "' $id '"');
  192.             } catch (DBALException $e) {
  193.                 $countryRepository->upsert([$data], $context);
  194.             }
  195.         }
  196.     }
  197.     private function matchByAvailableLocales(array $locales): array
  198.     {
  199.         $matchedLocales = [];
  200.         foreach ($locales as $locale) {
  201.             foreach (self::COUNTRY_LOCALES_CSV_DATA_MATCH as $csvMatch) {
  202.                 foreach ($csvMatch['locales'] as $availableLocale) {
  203.                     if($availableLocale === $locale) {
  204.                         $matchedLocales[] = [
  205.                             'locale' => $locale,
  206.                             'name' => $csvMatch['name'],
  207.                             'acris_countries_regex_description' => $csvMatch['acris_countries_regex_description']
  208.                         ];
  209.                         break;
  210.                     }
  211.                 }
  212.             }
  213.         }
  214.         return $matchedLocales;
  215.     }
  216. }