src/V4/Controller/CustomAction/CustomActionAction.php line 27

Open in your IDE?
  1. <?php
  2. namespace App\V4\Controller\CustomAction;
  3. use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
  4. use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
  5. use App\V4\CustomAction\Builder\CustomActionBuilder;
  6. use App\V4\Entity\CustomAction;
  7. use App\V4\Logger\SentryLogger;
  8. use App\V4\Model\Contact\Contact;
  9. use App\V4\Model\CustomActionResponse\CustomActionResponse;
  10. use App\V4\Model\CustomActionResponse\CustomActionResponseMessage;
  11. use App\V4\Model\Prospect\Prospect;
  12. use App\V4\Model\Quote\Quote;
  13. use App\V4\Model\Task\Task;
  14. use App\V4\Transformer\FQCNToShortNameTransformer;
  15. use Psr\Log\LogLevel;
  16. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  21. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  22. use Symfony\Component\Serializer\Serializer;
  23. use Throwable;
  24. class CustomActionAction extends AbstractController
  25. {
  26.     public const CUSTOM_ACTION_ACTIONS 'actions';
  27.     public const CUSTOM_ACTION_TOKEN_PROSPECT_ID '%prospectId%';
  28.     public const CUSTOM_ACTION_TOKEN_ID '%id%';
  29.     public const CUSTOM_ACTION_TOKEN_NEW_ID '%newId%';
  30.     public const CUSTOM_ACTION_TOKEN_CONTACT_ID '%contactId%';
  31.     public const CUSTOM_ACTION_TOKEN_TASK_ID '%taskId%';
  32.     public const CUSTOM_ACTION_TOKEN_QUOTE_ID '%quoteId%';
  33.     public const CUSTOM_ACTION_TOKEN_CONTACT_IDS '%contactIds%';
  34.     /**
  35.      * @var ItemDataProviderInterface
  36.      */
  37.     private $itemDataProvider;
  38.     /**
  39.      * @var CustomActionBuilder
  40.      */
  41.     private $customActionBuilder;
  42.     /**
  43.      * @var SentryLogger
  44.      */
  45.     private $sentryLogger;
  46.     public function __construct(
  47.         ItemDataProviderInterface $itemDataProvider,
  48.         CustomActionBuilder $customActionBuilder,
  49.         SentryLogger $sentryLogger
  50.     ) {
  51.         $this->itemDataProvider $itemDataProvider;
  52.         $this->customActionBuilder $customActionBuilder;
  53.         $this->sentryLogger $sentryLogger;
  54.     }
  55.     /**
  56.      * @param Request      $request
  57.      * @param CustomAction $customAction
  58.      *
  59.      * @return JsonResponse
  60.      *
  61.      * @throws ResourceClassNotSupportedException
  62.      * @throws ExceptionInterface
  63.      */
  64.     public function __invoke(Request $requestCustomAction $customAction): JsonResponse
  65.     {
  66.         $class = (new FQCNToShortNameTransformer())->reverseTransform($customAction->getEntity());
  67.         $content json_decode($request->getContent(), true);
  68.         $config json_decode($customAction->getConfig(), true);
  69.         if (empty($content['id'])) {
  70.             return new JsonResponse(
  71.                 ['error' => 'error_custom_action_config'],
  72.                 Response::HTTP_INTERNAL_SERVER_ERROR
  73.             );
  74.         }
  75.         $entity $this->itemDataProvider->getItem($class$content['id']);
  76.         if (null === $entity) {
  77.             return new JsonResponse(
  78.                 ['error' => 'error_custom_action_not_found'],
  79.                 Response::HTTP_NOT_FOUND
  80.             );
  81.         }
  82.         $config[self::CUSTOM_ACTION_ACTIONS] = $config[self::CUSTOM_ACTION_ACTIONS] ?? [];
  83.         try {
  84.             foreach ($config[self::CUSTOM_ACTION_ACTIONS] as $action) {
  85.                 $entity $this->customActionBuilder->getBuilder($entity$action)->apply($entity$action);
  86.             }
  87.         } catch (Throwable $e) {
  88.             $this->sentryLogger->captureException(
  89.                 SentryLogger::CHANNEL_CUSTOMER_ACTION,
  90.                 $e,
  91.                 [
  92.                     'config' => $config,
  93.                     'action' => $action,
  94.                 ]
  95.             );
  96.             return new JsonResponse(
  97.                 ['error' => $config['error_message'] ?? 'error_custom_action_config'],
  98.                 Response::HTTP_INTERNAL_SERVER_ERROR
  99.             );
  100.         }
  101.         $response = new CustomActionResponse();
  102.         if (!empty($config['confirm_message'])) {
  103.             $response->addMessage(
  104.                 (new CustomActionResponseMessage())
  105.                     ->setType('success')
  106.                     ->setMessage($config['confirm_message'])
  107.             );
  108.         }
  109.         if (isset($config[CustomActionResponse::CUSTOM_ACTION_NEED_REFRESH_LIST])
  110.             && true === $config[CustomActionResponse::CUSTOM_ACTION_NEED_REFRESH_LIST]
  111.         ) {
  112.             $response->addEffect([CustomActionResponse::CUSTOM_ACTION_NEED_REFRESH_LIST => true]);
  113.         }
  114.         if (!empty($config[CustomActionResponse::CUSTOM_ACTION_REDIRECT_TO])) {
  115.             $response->addEffect(
  116.                 [
  117.                     CustomActionResponse::CUSTOM_ACTION_REDIRECT_TO => $this->replaceTokens(
  118.                         $config[CustomActionResponse::CUSTOM_ACTION_REDIRECT_TO],
  119.                         $content['id'],
  120.                         $entity
  121.                     ),
  122.                 ]
  123.             );
  124.         }
  125.         $normalizers = [new ObjectNormalizer()];
  126.         $serializer = new Serializer($normalizers);
  127.         return new JsonResponse($serializer->normalize($response), Response::HTTP_OK);
  128.     }
  129.     /**
  130.      * @param string $url
  131.      * @param string $lineId
  132.      * @param mixed  $entity
  133.      *
  134.      * @return string
  135.      */
  136.     private function replaceTokens(string $urlstring $lineId$entity): string
  137.     {
  138.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_PROSPECT_ID)) {
  139.             $prospectId null;
  140.             if (method_exists($entity'getProspectId') && null !== $entity->getProspectId()) {
  141.                 $prospectId $entity->getProspectId();
  142.             }
  143.             if (method_exists($entity'getProspect') && $entity->getProspect() instanceof Prospect && null !== $entity->getProspect()->getId()) {
  144.                 $prospectId $entity->getProspect()->getId();
  145.             }
  146.             if (null === $prospectId) {
  147.                 $this->sentryLogger->captureMessage(
  148.                     SentryLogger::CHANNEL_CUSTOMER_ACTION,
  149.                     self::CUSTOM_ACTION_TOKEN_PROSPECT_ID." token was present in URL, yet no prospect id could be determined. URL: $url",
  150.                     [
  151.                         'args' => [
  152.                             'url' => $url,
  153.                             'entity' => $entity,
  154.                             'lineId' => $lineId,
  155.                         ],
  156.                     ],
  157.                     LogLevel::ERROR
  158.                 );
  159.             }
  160.             $url str_replace(self::CUSTOM_ACTION_TOKEN_PROSPECT_ID$prospectId$url);
  161.         }
  162.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_ID)) {
  163.             $url str_replace(self::CUSTOM_ACTION_TOKEN_ID$lineId$url);
  164.         }
  165.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_NEW_ID) && method_exists($entity'getId')) {
  166.             $url str_replace(self::CUSTOM_ACTION_TOKEN_ID$entity->getId(), $url);
  167.         }
  168.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_CONTACT_ID) && method_exists($entity'getContactId')) {
  169.             $url str_replace(self::CUSTOM_ACTION_TOKEN_CONTACT_ID$entity->getContactId(), $url);
  170.         }
  171.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_CONTACT_IDS) && method_exists($entity'getContacts')) {
  172.             $contactIds = [];
  173.             /** @var Contact $contact */
  174.             foreach ($entity->getContacts() as $contact) {
  175.                 $contactIds[] = $contact->getId();
  176.             }
  177.             $url str_replace(self::CUSTOM_ACTION_TOKEN_CONTACT_IDSimplode(','$contactIds), $url);
  178.         }
  179.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_TASK_ID) && $entity instanceof Task) {
  180.             $url str_replace(self::CUSTOM_ACTION_TOKEN_TASK_ID$entity->getId(), $url);
  181.         }
  182.         if (str_contains($urlself::CUSTOM_ACTION_TOKEN_QUOTE_ID) && $entity instanceof Quote) {
  183.             $url str_replace(self::CUSTOM_ACTION_TOKEN_QUOTE_ID$entity->getId(), $url);
  184.         }
  185.         return $url;
  186.     }
  187. }