custom/plugins/MolliePayments/src/Subscriber/SystemConfigSubscriber.php line 46

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Kiener\MolliePayments\Subscriber;
  4. use Kiener\MolliePayments\Helper\ProfileHelper;
  5. use Kiener\MolliePayments\Service\SettingsService;
  6. use Kiener\MolliePayments\Setting\MollieSettingStruct;
  7. use Kiener\MolliePayments\Struct\CustomerStruct;
  8. use Mollie\Api\MollieApiClient;
  9. use Mollie\Api\Resources\Profile;
  10. use Psr\Log\LoggerInterface;
  11. use Shopware\Core\Framework\Context;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. class SystemConfigSubscriber implements EventSubscriberInterface
  15. {
  16.     /** @var SettingsService */
  17.     private $settingsService;
  18.     /** @var LoggerInterface */
  19.     private $logger;
  20.     /** @var MollieApiClient */
  21.     private $apiClient;
  22.     /** @var array<mixed> */
  23.     private $profileIdStorage = [];
  24.     public function __construct(SettingsService $settingsServiceLoggerInterface $logger)
  25.     {
  26.         $this->settingsService $settingsService;
  27.         $this->logger $logger;
  28.         $this->apiClient = new MollieApiClient();
  29.     }
  30.     public static function getSubscribedEvents()
  31.     {
  32.         return [
  33.             'system_config.written' => 'onSystemConfigWritten',
  34.         ];
  35.     }
  36.     public function onSystemConfigWritten(EntityWrittenEvent $event): void
  37.     {
  38.         foreach ($event->getPayloads() as $payload) {
  39.             if (! isset($payload['configurationKey'])) {
  40.                 continue;
  41.             }
  42.             $this->checkSystemConfigChange(
  43.                 (string) $payload['configurationKey'],
  44.                 $payload['configurationValue'],
  45.                 $payload['salesChannelId'] ?? null,
  46.                 $event->getContext()
  47.             );
  48.         }
  49.     }
  50.     /**
  51.      * @param mixed $value
  52.      */
  53.     private function checkSystemConfigChange(string $key$value, ?string $salesChannelIdContext $context): void
  54.     {
  55.         if (in_array($key, [
  56.             SettingsService::SYSTEM_CONFIG_DOMAIN SettingsService::LIVE_PROFILE_ID,
  57.             SettingsService::SYSTEM_CONFIG_DOMAIN SettingsService::TEST_PROFILE_ID,
  58.         ])) {
  59.             $this->fixProfileIdAfterChange(
  60.                 $key,
  61.                 $value,
  62.                 $salesChannelId,
  63.                 strpos($keySettingsService::TEST_PROFILE_ID) !== false,
  64.                 $context
  65.             );
  66.         }
  67.         if (in_array($key, [
  68.             SettingsService::SYSTEM_CONFIG_DOMAIN SettingsService::LIVE_API_KEY,
  69.             SettingsService::SYSTEM_CONFIG_DOMAIN SettingsService::TEST_API_KEY,
  70.         ])) {
  71.             $this->fetchProfileIdForApiKey(
  72.                 $value,
  73.                 $salesChannelId,
  74.                 strpos($keySettingsService::TEST_API_KEY) !== false,
  75.                 $context
  76.             );
  77.         }
  78.     }
  79.     /**
  80.      * @param mixed $value
  81.      *
  82.      * @throws \Mollie\Api\Exceptions\ApiException
  83.      */
  84.     private function fetchProfileIdForApiKey($value, ?string $salesChannelIdbool $testModeContext $context): void
  85.     {
  86.         $profileKey SettingsService::SYSTEM_CONFIG_DOMAIN .
  87.             ($testMode ?
  88.                 SettingsService::TEST_PROFILE_ID :
  89.                 SettingsService::LIVE_PROFILE_ID);
  90.         if (empty($value)) {
  91.             // If this api key has been "deleted", also remove the profile ID.
  92.             $this->logger->debug(
  93.                 'API key has been removed, removing associated profile ID',
  94.                 [
  95.                     'salesChannelId' => $salesChannelId ?? 'null',
  96.                     'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  97.                 ]
  98.             );
  99.             $this->settingsService->setProfileId(null$salesChannelId$testMode);
  100.             return;
  101.         }
  102.         $this->logger->debug(
  103.             'Fetching profile ID',
  104.             [
  105.                 'salesChannelId' => $salesChannelId ?? 'null',
  106.                 'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  107.             ]
  108.         );
  109.         $this->apiClient->setApiKey($value);
  110.         $profile ProfileHelper::getProfile($this->apiClient, new MollieSettingStruct());
  111.         if (! $profile instanceof Profile) {
  112.             $this->logger->error(
  113.                 'Could not get profile using these settings',
  114.                 [
  115.                     'salesChannelId' => $salesChannelId ?? 'null',
  116.                     'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  117.                 ]
  118.             );
  119.             return;
  120.         }
  121.         $this->profileIdStorage[$salesChannelId $profileKey] = $profile->id;
  122.         $this->logger->debug(
  123.             'Saving profile ID',
  124.             [
  125.                 'salesChannelId' => $salesChannelId ?? 'null',
  126.                 'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  127.                 'profileId' => $profile->id,
  128.             ]
  129.         );
  130.         $this->settingsService->setProfileId($profile->id$salesChannelId$testMode);
  131.     }
  132.     /**
  133.      * Why do we need to fix the profile ID?
  134.      * When adding a key to the system config programmatically, even if there is no field for it in config.xml,
  135.      * when saving the configuration in the administration, Shopware will also save those keys.
  136.      * We need to fix the profile ID, because we fetch the new profile ID from Mollie and save it to the system config,
  137.      * and then Shopware overwrites it with the old one afterwards.
  138.      *
  139.      * @param mixed $value
  140.      */
  141.     private function fixProfileIdAfterChange(string $key$value, ?string $salesChannelIdbool $testModeContext $context): void
  142.     {
  143.         if (isset($this->profileIdStorage[$salesChannelId $key])) {
  144.             // If the old $value is the same as the new profile ID in storage, then dont set it again
  145.             // Will end up in an endless loop otherwise.
  146.             if ($this->profileIdStorage[$salesChannelId $key] === $value) {
  147.                 return;
  148.             }
  149.             $this->logger->debug(
  150.                 'A new profile ID was fetched, but the admin saved the old one again, correcting mistake.',
  151.                 [
  152.                     'salesChannelId' => $salesChannelId ?? 'null',
  153.                     'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  154.                     'profileId' => $value,
  155.                 ]
  156.             );
  157.             $this->settingsService->setProfileId($this->profileIdStorage[$salesChannelId $key], $salesChannelId$testMode);
  158.         } elseif ($value) {
  159.             $this->logger->debug(
  160.                 'Removing profile ID',
  161.                 [
  162.                     'salesChannelId' => $salesChannelId ?? 'null',
  163.                     'mode' => $testMode CustomerStruct::TEST_MODE CustomerStruct::LIVE_MODE,
  164.                 ]
  165.             );
  166.             $this->settingsService->setProfileId(null$salesChannelId$testMode);
  167.         }
  168.     }
  169. }