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