src/EventSubscriber/ProspectFieldsResponseSubscriber.php line 61

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Service\Prospect\ProspectHttpService;
  4. use App\Service\TenantPerson\TenantPersonService;
  5. use App\Util\Arr;
  6. use Psr\Cache\CacheException;
  7. use Psr\Cache\InvalidArgumentException;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. use Symfony\Component\HttpFoundation\JsonResponse;
  10. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  11. use Symfony\Component\HttpKernel\KernelEvents;
  12. class ProspectFieldsResponseSubscriber implements EventSubscriberInterface
  13. {
  14.     private const FIELD_TENANT 'prospectTenantId';
  15.     private const FIELD_TENANT_PERSON 'prospectTenantPersonId';
  16.     private const FIELD_CONTACT 'prospectContactId';
  17.     private const FIELD_ORDER 'prospectOrderId';
  18.     private const FIELD_WORK_SCHEDULE 'prospectWorkScheduleId';
  19.     private const FIELDS_REPLACE_MAPPING
  20.         = [
  21.             self::FIELD_TENANT => 'prospectTenant',
  22.             self::FIELD_TENANT_PERSON => 'prospectTenantPerson',
  23.             self::FIELD_CONTACT => 'prospectContact',
  24.             self::FIELD_ORDER => 'prospectOrder',
  25.             self::FIELD_WORK_SCHEDULE => 'prospectWorkSchedule',
  26.         ];
  27.     private $tenantPersonService;
  28.     private $prospectHttp;
  29.     public function __construct(TenantPersonService $tenantPersonServiceProspectHttpService $prospectHttp)
  30.     {
  31.         $this->tenantPersonService $tenantPersonService;
  32.         $this->prospectHttp $prospectHttp;
  33.     }
  34.     /**
  35.      * {@inheritDoc}
  36.      */
  37.     public static function getSubscribedEvents(): array
  38.     {
  39.         return [
  40.             // The second value of the array defines priority of the subscriber.
  41.             KernelEvents::RESPONSE => ['onKernelResponse'100],
  42.         ];
  43.     }
  44.     /**
  45.      * @throws InvalidArgumentException
  46.      * @throws CacheException
  47.      */
  48.     public function onKernelResponse(ResponseEvent $event)
  49.     {
  50.         if (!$this->tenantPersonService->isInitialized()) {
  51.             return;
  52.         }
  53.         $response $event->getResponse();
  54.         if (!$response->isSuccessful()) {
  55.             return;
  56.         }
  57.         $contentType $response->headers->get('Content-Type');
  58.         if (false === strpos($contentType'json')) {
  59.             return;
  60.         }
  61.         $content json_decode($response->getContent(), true);
  62.         if (\JSON_ERROR_NONE !== json_last_error()) {
  63.             return;
  64.         }
  65.         if (null === $content) {
  66.             return;
  67.         }
  68.         if ('' === $content) {
  69.             return;
  70.         }
  71.         $prospectColumns Arr::array_column_recursive($contentarray_keys(self::FIELDS_REPLACE_MAPPING));
  72.         $prospectColumns $this->fetchProspectColumns($prospectColumns);
  73.         $content $this->findAndReplace($content$prospectColumns);
  74.         $jsonResponse = new JsonResponse($content$response->getStatusCode(), $response->headers->all());
  75.         $event->setResponse($jsonResponse);
  76.     }
  77.     /**
  78.      * @throws InvalidArgumentException
  79.      * @throws \Exception
  80.      */
  81.     private function fetchProspectColumns(array $prospectColumns): array
  82.     {
  83.         $return array_fill_keys(array_keys($prospectColumns), []);
  84.         $authProspectTenantId $this->tenantPersonService->getTenant()->getProspectTenantId();
  85.         if (array_key_exists(self::FIELD_TENANT$prospectColumns)) {
  86.             $key self::FIELD_TENANT;
  87.             // Filtering an array of ids to keep only numeric values. Prevents unnecessary requests with invalid values.
  88.             $prospectColumns[$key] = array_filter($prospectColumns[$key], 'is_numeric');
  89.             if (count($prospectColumns[$key]) > 0) {
  90.                 // Only one tenant can be fetched at once.
  91.                 $prospectTenant $this->prospectHttp->fetchTenant($prospectColumns[$key][0]);
  92.                 $return[$key][$prospectColumns[$key][0]] = $prospectTenant;
  93.             }
  94.         }
  95.         if (array_key_exists(self::FIELD_TENANT_PERSON$prospectColumns)) {
  96.             $key self::FIELD_TENANT_PERSON;
  97.             $prospectColumns[$key] = array_filter($prospectColumns[$key], 'is_numeric');
  98.             if (count($prospectColumns[$key]) > 0) {
  99.                 $prospectTenantPeople $this->prospectHttp->fetchTenantPeople($authProspectTenantId$prospectColumns[$key]);
  100.                 // Replacing array indexes with corresponding ids
  101.                 $return[$key] = array_combine(array_column($prospectTenantPeople'id'), $prospectTenantPeople);
  102.             }
  103.         }
  104.         if (array_key_exists(self::FIELD_CONTACT$prospectColumns)) {
  105.             $key self::FIELD_CONTACT;
  106.             $prospectColumns[$key] = array_filter($prospectColumns[$key], 'is_numeric');
  107.             if (count($prospectColumns[$key]) > 0) {
  108.                 $prospectContacts $this->prospectHttp->fetchContacts($authProspectTenantId$prospectColumns[$key]);
  109.                 $return[$key] = array_combine(array_column($prospectContacts'id'), $prospectContacts);
  110.             }
  111.         }
  112.         if (array_key_exists(self::FIELD_ORDER$prospectColumns)) {
  113.             $key self::FIELD_ORDER;
  114.             $prospectColumns[$key] = array_filter($prospectColumns[$key], 'is_numeric');
  115.             if (count($prospectColumns[$key]) > 0) {
  116.                 $prospectOrders $this->prospectHttp->fetchOrders($authProspectTenantId$prospectColumns[$key]);
  117.                 $return[$key] = array_combine(array_column($prospectOrders'id'), $prospectOrders);
  118.             }
  119.         }
  120.         if (array_key_exists(self::FIELD_WORK_SCHEDULE$prospectColumns)) {
  121.             $key self::FIELD_WORK_SCHEDULE;
  122.             $prospectColumns[$key] = array_filter($prospectColumns[$key], 'is_numeric');
  123.             if (count($prospectColumns[$key]) > 0) {
  124.                 $prospectWorkSchedules $this->prospectHttp->fetchWorkSchedules($authProspectTenantId$prospectColumns[$key]);
  125.                 $return[$key] = array_combine(array_column($prospectWorkSchedules'id'), $prospectWorkSchedules);
  126.             }
  127.         }
  128.         return $return;
  129.     }
  130.     /**
  131.      * Finds Prospect fields and replaces them with a new key and value from Prospect API.
  132.      *
  133.      * For example:
  134.      * ['prospectContactId' => 1] will be replaced with ['prospectContact' => ['id' => 1, 'name' => 'Foo', ...]]
  135.      *
  136.      * @param array $content      An input array
  137.      * @param array $replacements Fetched Prospect data.
  138.      *                            Format: ['prospectContactId' => [1 => ['id' => 1, 'name' => 'Contact', ...], ...], ...]
  139.      *
  140.      * @throws InvalidArgumentException
  141.      */
  142.     private function findAndReplace(array $content, array $replacements): array
  143.     {
  144.         $return = [];
  145.         foreach ($content as $key => $value) {
  146.             if (is_array($value)) {
  147.                 $return[$key] = $this->findAndReplace($value$replacements);
  148.                 continue;
  149.             }
  150.             if (in_array($keyarray_keys(self::FIELDS_REPLACE_MAPPING), true)) {
  151.                 if (null !== $value) {
  152.                     // Change data with corresponding replacement. If the replacement not found, keep the original value.
  153.                     $value $replacements[$key][$value] ?? $value;
  154.                 }
  155.                 $key self::FIELDS_REPLACE_MAPPING[$key];
  156.             }
  157.             $return[$key] = $value;
  158.         }
  159.         return $return;
  160.     }
  161. }