custom/plugins/AcrisTaxCS/src/AcrisTaxCS.php line 23

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Acris\Tax;
  3. use Acris\Tax\Components\Service\VatIdValidationService;
  4. use Doctrine\DBAL\Connection;
  5. use Shopware\Core\Content\Rule\Aggregate\RuleCondition\RuleConditionEntity;
  6. use Shopware\Core\Content\Rule\RuleEntity;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
  15. use Shopware\Core\Framework\Plugin;
  16. use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  17. use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  18. use Shopware\Core\Framework\Plugin\Context\ActivateContext;
  19. use Shopware\Core\System\Country\CountryEntity;
  20. class AcrisTaxCS extends Plugin
  21. {
  22.     const CUSTOM_FIELD_SET_NAME 'acris_tax_specific_country';
  23.     const DEFAULT_CUSTOM_CUSTOMER_HAS_VAT_ID_RULE_NAME 'ACRIS customer personal data has VAT Reg.No. (Shopware standard)';
  24.     const DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VAT_ID_RULE_NAME 'ACRIS billing address has VAT Reg.No.';
  25.     const DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VAT_ID_RULE_NAME 'ACRIS shipping address has VAT Reg.No.';
  26.     const DEFAULT_CUSTOM_CUSTOMER_HAS_VALID_VAT_ID_RULE_NAME 'ACRIS customer personal data has valid VAT Reg.No.';
  27.     const DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VALID_VAT_ID_RULE_NAME 'ACRIS billing address has valid VAT Reg.No.';
  28.     const DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VALID_VAT_ID_RULE_NAME 'ACRIS shipping address has valid VAT Reg.No.';
  29.     public function update(UpdateContext $updateContext): void
  30.     {
  31.         if(version_compare($updateContext->getCurrentPluginVersion(), '2.3.0''<')
  32.             && version_compare($updateContext->getUpdatePluginVersion(), '2.3.0''>=')) {
  33.             $this->replaceExistingRuleNames($updateContext->getContext());
  34.         }
  35.         if(version_compare($updateContext->getCurrentPluginVersion(), '6.1.0''<')
  36.             && version_compare($updateContext->getUpdatePluginVersion(), '6.1.0''>=')) {
  37.             $this->assignDefaultVatIdCheckForCountries($updateContext->getContext());
  38.         }
  39.     }
  40.     public function postUpdate(UpdateContext $context): void
  41.     {
  42.         if(version_compare($context->getCurrentPluginVersion(), '6.2.0''<')
  43.             && version_compare($context->getUpdatePluginVersion(), '6.2.0''>=')) {
  44.             $this->insertDefaultValues($context->getContext());
  45.             $this->setDefaultAdvancedTaxFreeRulesSettings($context->getContext());
  46.         }
  47.         if(version_compare($context->getCurrentPluginVersion(), '6.4.0''<')
  48.             && version_compare($context->getUpdatePluginVersion(), '6.4.0''>=')) {
  49.             $this->insertDefaultValues($context->getContext());
  50.         }
  51.     }
  52.     public function activate(ActivateContext $activateContext): void
  53.     {
  54.         $this->insertDefaultValues($activateContext->getContext());
  55.         $this->assignDefaultVatIdCheckForCountries($activateContext->getContext());
  56.         $this->setDefaultAdvancedTaxFreeRulesSettings($activateContext->getContext());
  57.     }
  58.     public function uninstall(UninstallContext $context): void
  59.     {
  60.         if ($context->keepUserData()) {
  61.             return;
  62.         }
  63.         $this->removeRules($context->getContext());
  64.         $this->cleanupDatabase();
  65.     }
  66.     private function cleanupDatabase(): void
  67.     {
  68.         $connection $this->container->get(Connection::class);
  69.         $connection->executeStatement('DROP TABLE IF EXISTS acris_tax_vat_id_validation_log');
  70.         $connection->executeStatement('DROP TABLE IF EXISTS acris_tax_customer_group_rule');
  71.         $connection->executeStatement('DROP TABLE IF EXISTS acris_tax_country_rule');
  72.         try {
  73.             $connection->executeStatement('ALTER TABLE `customer` DROP `acrisTaxVatIdValidationLogs`');
  74.             $connection->executeStatement('ALTER TABLE `customer_group` DROP `acrisRules`');
  75.             $connection->executeStatement('ALTER TABLE `country` DROP `acrisRules`');
  76.         } catch (\Exception $e) { }
  77.     }
  78.     private function replaceExistingRuleNames(Context $context)
  79.     {
  80.         $ruleConditionRepository $this->container->get('rule_condition.repository');
  81.         /** @var EntitySearchResult $existingRuleConditionSearchResult */
  82.         $existingRuleConditionSearchResult $ruleConditionRepository->search((new Criteria())->addFilter(
  83.             new MultiFilter(MultiFilter::CONNECTION_OR, [
  84.                 new EqualsFilter('type''customerHasVatIdBillingRule'),
  85.                 new EqualsFilter('type''customerHasVatIdShippingRule')
  86.             ])
  87.         ), $context);
  88.         if ($existingRuleConditionSearchResult->count() <= 0) {
  89.             return;
  90.         }
  91.         $changedRuleConditions = [];
  92.         /** @var RuleConditionEntity $ruleConditionEntity */
  93.         foreach ($existingRuleConditionSearchResult->getElements() as $ruleConditionEntity) {
  94.             $value $ruleConditionEntity->getValue();
  95.             if(!is_array($value)) {
  96.                 continue;
  97.             }
  98.             if(array_key_exists('customerHasVatIdBilling'$value)) {
  99.                 $value = ['customerHasVatId' => $value['customerHasVatIdBilling']];
  100.             } elseif(array_key_exists('customerHasVatIdShipping'$value)) {
  101.                 $value = ['customerHasVatId' => $value['customerHasVatIdShipping']];
  102.             } else {
  103.                 continue;
  104.             }
  105.             $changedRuleConditions[] = [
  106.                 'id' => $ruleConditionEntity->getId(),
  107.                 'type' => 'customerHasVatIdRule',
  108.                 'value' => $value
  109.             ];
  110.         }
  111.         if(!empty($changedRuleConditions)) {
  112.             $ruleConditionRepository->upsert($changedRuleConditions$context);
  113.         }
  114.     }
  115.     private function assignDefaultVatIdCheckForCountries(Context $context): void
  116.     {
  117.         /** @var EntityRepositoryInterface $countryRepository */
  118.         $countryRepository $this->container->get('country.repository');
  119.         $criteria = new Criteria();
  120.         $criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_AND, [
  121.             new EqualsAnyFilter('iso'VatIdValidationService::DEFAULT_SPECIFIC_COUNTRIES)
  122.         ]));
  123.         /** @var EntitySearchResult $countryIds */
  124.         $countries $countryRepository->search($criteria$context);
  125.         if ($countries->count() === || !$countries->first()) return;
  126.         $updateData = [];
  127.         /** @var CountryEntity $country */
  128.         foreach ($countries->getEntities()->getElements() as $country) {
  129.             $customFields $country->getCustomFields() ?? [];
  130.             if (array_key_exists('acris_tax_specific_country_validate_vat_id'$customFields)) continue;
  131.             $customFields['acris_tax_specific_country_validate_vat_id'] = true;
  132.             $updateData[] = [
  133.                 'id' => $country->getId(),
  134.                 'customFields' => $customFields
  135.             ];
  136.         }
  137.         if (!empty($updateData)) {
  138.             $countryRepository->update($updateData$context);
  139.         }
  140.     }
  141.     private function insertDefaultValues(Context $context): void
  142.     {
  143.         /** @var EntityRepositoryInterface $ruleRepository */
  144.         $ruleRepository $this->container->get('rule.repository');
  145.         $rules = [
  146.             [
  147.                 'name' => self::DEFAULT_CUSTOM_CUSTOMER_HAS_VAT_ID_RULE_NAME,
  148.                 'priority' => 100,
  149.                 'conditions' => [
  150.                     [
  151.                         'type' => 'customerHasVatIdRule',
  152.                         'value' => [
  153.                             'customerHasVatId' => true
  154.                         ]
  155.                     ]
  156.                 ]
  157.             ], [
  158.                 'name' => self::DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VAT_ID_RULE_NAME,
  159.                 'priority' => 100,
  160.                 'conditions' => [
  161.                     [
  162.                         'type' => 'billingAddressHasVatIdRule',
  163.                         'value' => [
  164.                             'billingAddressHasVatId' => true
  165.                         ]
  166.                     ]
  167.                 ]
  168.             ], [
  169.                 'name' => self::DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VAT_ID_RULE_NAME,
  170.                 'priority' => 100,
  171.                 'conditions' => [
  172.                     [
  173.                         'type' => 'shippingAddressHasVatIdRule',
  174.                         'value' => [
  175.                             'shippingAddressHasVatId' => true
  176.                         ]
  177.                     ]
  178.                 ]
  179.             ], [
  180.                 'name' => self::DEFAULT_CUSTOM_CUSTOMER_HAS_VALID_VAT_ID_RULE_NAME,
  181.                 'priority' => 100,
  182.                 'conditions' => [
  183.                     [
  184.                         'type' => 'customerHasVatIdValidRule',
  185.                         'value' => [
  186.                             'customerHasVatId' => true
  187.                         ]
  188.                     ]
  189.                 ]
  190.             ], [
  191.                 'name' => self::DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VALID_VAT_ID_RULE_NAME,
  192.                 'priority' => 100,
  193.                 'conditions' => [
  194.                     [
  195.                         'type' => 'billingAddressHasVatIdValidRule',
  196.                         'value' => [
  197.                             'billingAddressHasVatId' => true
  198.                         ]
  199.                     ]
  200.                 ]
  201.             ], [
  202.                 'name' => self::DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VALID_VAT_ID_RULE_NAME,
  203.                 'priority' => 100,
  204.                 'conditions' => [
  205.                     [
  206.                         'type' => 'shippingAddressHasVatIdValidRule',
  207.                         'value' => [
  208.                             'shippingAddressHasVatId' => true
  209.                         ]
  210.                     ]
  211.                 ]
  212.             ]];
  213.         foreach ($rules as $rule) {
  214.             try {
  215.                 $this->createIfNotExists($ruleRepository, [['name' => 'name''value' => $rule['name']]], $rule$context);
  216.             } catch (\Throwable $e) {
  217.                 // Do nothing - prevent a Shopware bug for deleting cache for rules
  218.                 // TODO: Fix missing rule id now!
  219.             }
  220.         }
  221.     }
  222.     private function createIfNotExists(EntityRepositoryInterface $repository, array $equalFields, array $dataContext $context): void
  223.     {
  224.         $filters = [];
  225.         foreach ($equalFields as $equalField) {
  226.             $filters[] = new EqualsFilter($equalField['name'], $equalField['value']);
  227.         }
  228.         if (sizeof($filters) > 1) {
  229.             $filter = new MultiFilter(MultiFilter::CONNECTION_OR$filters);
  230.         } else {
  231.             $filter array_shift($filters);
  232.         }
  233.         $searchResult $repository->search((new Criteria())->addFilter($filter), $context);
  234.         if (empty($searchResult->first())) {
  235.             $repository->create([$data], $context);
  236.         }
  237.     }
  238.     private function removeRules(Context $context): void
  239.     {
  240.         /** @var EntityRepositoryInterface $rulesRepository */
  241.         $rulesRepository $this->container->get('rule.repository');
  242.         /** @var EntitySearchResult $rulesResult */
  243.         $rulesResult $rulesRepository->search((new Criteria())->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
  244.             new EqualsFilter('name'self::DEFAULT_CUSTOM_CUSTOMER_HAS_VAT_ID_RULE_NAME),
  245.             new EqualsFilter('name'self::DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VAT_ID_RULE_NAME),
  246.             new EqualsFilter('name'self::DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VAT_ID_RULE_NAME),
  247.         ])), $context);
  248.         if ($rulesResult->getTotal() > && $rulesResult->first()) {
  249.             $ruleIds = [];
  250.             /** @var RuleEntity $rule */
  251.             foreach ($rulesResult->getEntities()->getElements() as $rule) {
  252.                 $ruleIds[] = ['id' => $rule->getId()];
  253.             }
  254.             $rulesRepository->delete($ruleIds$context);
  255.         }
  256.     }
  257.     private function setDefaultAdvancedTaxFreeRulesSettings(Context $context)
  258.     {
  259.         /** @var EntityRepositoryInterface $ruleRepository */
  260.         $ruleRepository $this->container->get('rule.repository');
  261.         $configService $this->container->get('Shopware\Core\System\SystemConfig\SystemConfigService');
  262.         if($configService->get('AcrisTaxCS.config.acrisAdvancedTaxRules') === null) {
  263.             /** @var IdSearchResult $idSearchResult */
  264.             $idSearchResult $ruleRepository->searchIds((new Criteria())->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
  265.                 new EqualsFilter('name'self::DEFAULT_CUSTOM_CUSTOMER_HAS_VAT_ID_RULE_NAME),
  266.                 new EqualsFilter('name'self::DEFAULT_CUSTOM_BILLING_ADDRESS_HAS_VAT_ID_RULE_NAME),
  267.                 new EqualsFilter('name'self::DEFAULT_CUSTOM_SHIPPING_ADDRESS_HAS_VAT_ID_RULE_NAME),
  268.             ])), $context);
  269.             if ($idSearchResult->getTotal() > && !empty($idSearchResult->firstId())) {
  270.                 $configService->set('AcrisTaxCS.config.acrisAdvancedTaxRules'$idSearchResult->getIds());
  271.             }
  272.         }
  273.     }
  274. }