src/V4/DataPersister/AbstractWithoutRequestDataPersister.php line 193

Open in your IDE?
  1. <?php
  2. namespace App\V4\DataPersister;
  3. use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
  4. use App\Security\User;
  5. use App\Service\ApiWebService;
  6. use App\Service\Cache\CacheManager;
  7. use App\Service\DataWrapper\BasicDataWrapper;
  8. use App\Service\PreSendSerializer;
  9. use App\Service\Provider\ApiProviderInterface;
  10. use App\Service\TokenDataWrapper\TokenDataWrapper;
  11. use App\V4\Event\PostPersistEvent;
  12. use App\V4\Event\PostRemoveEvent;
  13. use App\V4\Logger\SentryLogger;
  14. use App\V4\Messenger\Message\ResynchronizeBadgesRequest;
  15. use Doctrine\Common\Annotations\AnnotationException;
  16. use Psr\Cache\InvalidArgumentException;
  17. use RuntimeException;
  18. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\Messenger\MessageBusInterface;
  22. use Symfony\Component\Security\Core\Security;
  23. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  24. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  25. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  26. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  27. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  28. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  29. use Throwable;
  30. abstract class AbstractWithoutRequestDataPersister implements ContextAwareDataPersisterInterface
  31. {
  32.     protected const ENTITY null;
  33.     protected const ENDPOINT '/';
  34.     protected const POST_SERIALIZATION_GROUPS = [];
  35.     protected const PUT_SERIALIZATION_GROUPS = [];
  36.     public const CONTEXT_IS_V4 'is_v4';
  37.     public const CONTEXT_NOT_POST_PERSIST_EVENT 'not_post_persist_event';
  38.     /**
  39.      * @var ApiWebService
  40.      */
  41.     private $apiWebService;
  42.     /**
  43.      * @var ApiProviderInterface
  44.      */
  45.     private $apiProvider;
  46.     /**
  47.      * @var TokenDataWrapper
  48.      */
  49.     private $tokenDataWrapper;
  50.     /**
  51.      * @var BasicDataWrapper
  52.      */
  53.     private $basicDataWrapper;
  54.     /**
  55.      * @var PreSendSerializer
  56.      */
  57.     private $serializer;
  58.     /**
  59.      * @var CacheManager
  60.      */
  61.     private $cacheManager;
  62.     /**
  63.      * @var MessageBusInterface
  64.      */
  65.     private $bus;
  66.     /**
  67.      * @var Security
  68.      */
  69.     private $security;
  70.     /**
  71.      * @var EventDispatcherInterface
  72.      */
  73.     private $eventDispatcher;
  74.     /**
  75.      * @var SentryLogger
  76.      */
  77.     private $sentryLogger;
  78.     /**
  79.      * @param ApiWebService            $apiWebService
  80.      * @param ApiProviderInterface     $apiProvider
  81.      * @param TokenDataWrapper         $tokenDataWrapper
  82.      * @param BasicDataWrapper         $basicDataWrapper
  83.      * @param PreSendSerializer        $serializer
  84.      * @param CacheManager             $cacheManager
  85.      * @param MessageBusInterface      $bus
  86.      * @param Security                 $security
  87.      * @param EventDispatcherInterface $eventDispatcher
  88.      * @param SentryLogger             $sentryLogger
  89.      */
  90.     public function __construct(
  91.         ApiWebService $apiWebService,
  92.         ApiProviderInterface $apiProvider,
  93.         TokenDataWrapper $tokenDataWrapper,
  94.         BasicDataWrapper $basicDataWrapper,
  95.         PreSendSerializer $serializer,
  96.         CacheManager $cacheManager,
  97.         MessageBusInterface $bus,
  98.         Security $security,
  99.         EventDispatcherInterface $eventDispatcher,
  100.         SentryLogger $sentryLogger
  101.     ) {
  102.         $this->apiWebService $apiWebService;
  103.         $this->apiProvider $apiProvider;
  104.         $this->tokenDataWrapper $tokenDataWrapper;
  105.         $this->basicDataWrapper $basicDataWrapper;
  106.         $this->serializer $serializer;
  107.         $this->cacheManager $cacheManager;
  108.         $this->bus $bus;
  109.         $this->security $security;
  110.         $this->eventDispatcher $eventDispatcher;
  111.         $this->sentryLogger $sentryLogger;
  112.     }
  113.     /**
  114.      * @param $data
  115.      * @param array $context
  116.      *
  117.      * @return bool
  118.      */
  119.     public function supports($data, array $context = []): bool
  120.     {
  121.         $entity $this::ENTITY;
  122.         return $data instanceof $entity && isset($context[self::CONTEXT_IS_V4]);
  123.     }
  124.     /**
  125.      * @param object $data
  126.      * @param array  $context
  127.      *
  128.      * @return object
  129.      *
  130.      * @throws InvalidArgumentException
  131.      * @throws AnnotationException
  132.      * @throws ExceptionInterface
  133.      * @throws ClientExceptionInterface
  134.      * @throws DecodingExceptionInterface
  135.      * @throws RedirectionExceptionInterface
  136.      * @throws ServerExceptionInterface
  137.      * @throws TransportExceptionInterface
  138.      */
  139.     public function persist($data, array $context = [])
  140.     {
  141.         $url $this::ENDPOINT;
  142.         $serializationGroups $this::POST_SERIALIZATION_GROUPS;
  143.         $method Request::METHOD_POST;
  144.         if (null !== $data->getId()) {
  145.             $method Request::METHOD_PUT;
  146.             $url sprintf('%s/%s'$this::ENDPOINT$data->getId());
  147.             $serializationGroups $this::PUT_SERIALIZATION_GROUPS;
  148.         }
  149.         $requestContent $this->serializer->serialize($data$serializationGroups);
  150.         $requestContent $this->reformatSubmittedData($requestContent);
  151.         $serializedData $this->basicDataWrapper->wrapData($requestContent);
  152.         $serializedData $this->tokenDataWrapper->wrapData($serializedData);
  153.         $response $this
  154.             ->apiWebService
  155.             ->send($this->apiProvider$method$url$serializedData)
  156.         ;
  157.         $data->setId($response->toArray()['id']);
  158.         $this->cacheManager->invalidateTag([$this->cacheManager->getCustomerPrefix().'_'.$this::ENTITY]);
  159.         if (!isset($context[self::CONTEXT_NOT_POST_PERSIST_EVENT])) {
  160.             $this->eventDispatcher->dispatch(
  161.                 (new PostPersistEvent())->setAfter($data)->setContext($context),
  162.                 PostPersistEvent::NAME
  163.             );
  164.         }
  165.         $user $this->security->getUser();
  166.         if ($user instanceof User) {
  167.             $this->bus->dispatch((new ResynchronizeBadgesRequest())
  168.                 ->setCustomerId($user->getCustomerId()));
  169.         }
  170.         return $data;
  171.     }
  172.     /**
  173.      * @param $data
  174.      * @param array $context
  175.      *
  176.      * @return void
  177.      *
  178.      * @throws TransportExceptionInterface
  179.      * @throws \Exception
  180.      */
  181.     public function remove($data, array $context = []): void
  182.     {
  183.         try {
  184.             $response $this
  185.                 ->apiWebService
  186.                 ->send($this->apiProviderRequest::METHOD_DELETEsprintf('%s/%s'$this::ENDPOINT$data->getId()))
  187.             ;
  188.             $this->cacheManager->invalidateTag([$this::ENTITY]);
  189.             if (Response::HTTP_OK === $response->getStatusCode() || Response::HTTP_NO_CONTENT === $response->getStatusCode()) {
  190.                 $this->eventDispatcher->dispatch((new PostRemoveEvent())->setAfter($data), PostRemoveEvent::NAME);
  191.             }
  192.         } catch (Throwable InvalidArgumentException $exception) {
  193.             $this->sentryLogger->captureException(
  194.                 SentryLogger::CHANNEL_DATA_PERSISTER,
  195.                 $exception,
  196.                 [
  197.                     'catchOnClass' => self::class,
  198.                     'apiCalled' => $this->apiProvider->getHost(),
  199.                     'urlCalled' => sprintf('%s/%s'self::ENDPOINT$data->getId()),
  200.                     'method' => Request::METHOD_DELETE,
  201.                     'message' => 'Unable to delete '.self::ENTITY.' with id '.$data->getId(),
  202.                 ]
  203.             );
  204.             throw new RuntimeException('Unable to delete '.$this::ENTITY.' with id '.$data->getId(), 0$exception);
  205.         }
  206.     }
  207.     /**
  208.      * @param $submittedData
  209.      *
  210.      * @return array
  211.      */
  212.     protected function reformatSubmittedData($submittedData): array
  213.     {
  214.         $submittedDataFormatted = [];
  215.         foreach ($submittedData as $fieldName => $value) {
  216.             if (str_starts_with($fieldName'sf_')) {
  217.                 $submittedDataFormatted array_merge($submittedDataFormatted, [$fieldName => $value]);
  218.                 continue;
  219.             }
  220.             $temp = &$submittedDataFormatted;
  221.             foreach (explode('_'$fieldName) as $key) {
  222.                 $temp = &$temp[$key];
  223.             }
  224.             $temp $value;
  225.         }
  226.         return $submittedDataFormatted;
  227.     }
  228. }