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

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