src/DataProvider/AbstractCollectionDataProvider.php line 252

Open in your IDE?
  1. <?php
  2. namespace App\DataProvider;
  3. use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
  4. use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
  5. use App\Listing\Transformer\ListingResponseTransformerInterface;
  6. use App\Service\ApiWebService;
  7. use App\Service\ApiWebServiceFilterBuilder\AllIdsFilterBuilder;
  8. use App\Service\ApiWebServiceFilterBuilder\Crm\Traits\FieldNameConvertorTrait;
  9. use App\Service\ApiWebServiceFilterBuilder\FilterBuildersChain;
  10. use App\Service\ApiWebServiceFilterBuilder\PaginationFilterBuilder;
  11. use App\Service\Cache\CacheManager;
  12. use App\Service\Cache\Exception\UnableToSaveKeyException;
  13. use App\Service\Provider\ApiProviderInterface;
  14. use Psr\Cache\CacheException;
  15. use Psr\Cache\InvalidArgumentException;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  18. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  19. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  20. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  21. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  22. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  23. abstract class AbstractCollectionDataProvider implements ContextAwareCollectionDataProviderInterfaceRestrictedDataProviderInterface
  24. {
  25.     public const CONTEXT_TAB 'tab';
  26.     public const DISABLE_CUSTOMER_FILTER 'disableCustomerFilter';
  27.     public const DISABLE_AUTHENTICATION 'disableAuthentication';
  28.     public const FETCH_CUSTOMER_FILES 'fetchCustomerFiles';
  29.     protected const ENTITY null;
  30.     protected const ENDPOINT '/';
  31.     protected const METHOD Request::METHOD_GET;
  32.     protected const IGNORE_FALSE_VALUE_FOR = [
  33.         'myContacts',
  34.         'unSubscribedOfMailing',
  35.         'myQuotes',
  36.         'isMaintenance',
  37.         'myTasks',
  38.     ];
  39.     use FieldNameConvertorTrait;
  40.     /**
  41.      * @var FilterBuildersChain
  42.      */
  43.     protected $filterBuildersChain;
  44.     /**
  45.      * @var ApiWebService
  46.      */
  47.     protected $apiWebService;
  48.     /**
  49.      * @var ApiProviderInterface
  50.      */
  51.     protected $apiProvider;
  52.     /**
  53.      * @var CacheManager
  54.      */
  55.     private $cacheManager;
  56.     /**
  57.      * @var ListingResponseTransformerInterface
  58.      */
  59.     private $listingResponseTransformer;
  60.     /**
  61.      * @param FilterBuildersChain                 $filterBuildersChain
  62.      * @param ApiWebService                       $apiWebService
  63.      * @param ApiProviderInterface                $apiProvider
  64.      * @param CacheManager                        $cacheManager
  65.      * @param ListingResponseTransformerInterface $listingResponseTransformer
  66.      */
  67.     public function __construct(
  68.         FilterBuildersChain $filterBuildersChain,
  69.         ApiWebService $apiWebService,
  70.         ApiProviderInterface $apiProvider,
  71.         CacheManager $cacheManager,
  72.         ListingResponseTransformerInterface $listingResponseTransformer
  73.     ) {
  74.         $this->filterBuildersChain $filterBuildersChain;
  75.         $this->apiWebService $apiWebService;
  76.         $this->apiProvider $apiProvider;
  77.         $this->cacheManager $cacheManager;
  78.         $this->listingResponseTransformer $listingResponseTransformer;
  79.     }
  80.     /**
  81.      * @param string      $resourceClass
  82.      * @param string|null $operationName
  83.      * @param array       $context
  84.      *
  85.      * @return bool
  86.      */
  87.     public function supports(string $resourceClassstring $operationName null, array $context = []): bool
  88.     {
  89.         $entity $this::ENTITY;
  90.         return $entity === $resourceClass
  91.             && (null === $operationName || 'get' === $operationName)
  92.             ;
  93.     }
  94.     /**
  95.      * @param string      $resourceClass
  96.      * @param string|null $operationName
  97.      * @param array       $context
  98.      *
  99.      * @return iterable
  100.      *
  101.      * @throws CacheException
  102.      * @throws ClientExceptionInterface
  103.      * @throws DecodingExceptionInterface
  104.      * @throws ExceptionInterface
  105.      * @throws InvalidArgumentException
  106.      * @throws RedirectionExceptionInterface
  107.      * @throws ServerExceptionInterface
  108.      * @throws TransportExceptionInterface
  109.      * @throws UnableToSaveKeyException
  110.      */
  111.     public function getCollection(string $resourceClassstring $operationName null, array $context = []): iterable
  112.     {
  113.         $response $this->getRawCollection($context['filters'] ?? [], $context);
  114.         if (isset($context['filters'][AllIdsFilterBuilder::DATA_FILTER_KEY])) {
  115.             foreach ($response['hydra:member'] as $key => $responseContent) {
  116.                 // @todo voir si on laisse les info comme ça depuis crm => [ [0] => "monObjet", "autre_champ" => "valeur"]
  117.                 //valable pour Prospect et contact et devis
  118.                 if (isset($responseContent[0])) {
  119.                     $response['hydra:member'][$key] = $responseContent[0];
  120.                 }
  121.                 // @todo refacto : voir si l'on ne pas renvoyer directement prospectId directement depuis business
  122.                 if (isset($response['hydra:member'][$key]['prospect.id'])) {
  123.                     $response['hydra:member'][$key]['prospectId'] = $response['hydra:member'][$key]['prospect.id'];
  124.                     unset($response['hydra:member'][$key]['prospect.id']);
  125.                 }
  126.             }
  127.             return $response;
  128.         }
  129.         $entities = [];
  130.         foreach ($response['hydra:member'] as $responseContent) {
  131.             // @todo voir si on laisse les info comme ça depuis crm => [ [0] => "monObjet", "autre_champ" => "valeur"]
  132.             //valable pour Prospect et contact et devis
  133.             if (isset($responseContent[0])) {
  134.                 // Do not change order of array_merge parameters
  135.                 // Otherwise, the first element of the array will be overwritten by the second one
  136.                 // We'll loose createdByRealName, managedByRealName and updatedByRealName
  137.                 //
  138.                 // The array_filter method is used to remove null values
  139.                 $responseContent array_merge($responseContent[0], array_filter($responseContent));
  140.                 unset($responseContent[0]);
  141.             }
  142.             // @todo refacto : voir si l'on ne pas renvoyer directement prospectId directement depuis business
  143.             if (isset($responseContent['prospect.id'])) {
  144.                 $responseContent['prospectId'] = $responseContent['prospect.id'];
  145.                 unset($responseContent['prospect.id']);
  146.             }
  147.             $class $this::ENTITY;
  148.             $entity = new $class();
  149.             $entity->importFromData($responseContent);
  150.             $entities[] = $entity;
  151.         }
  152.         if (isset($context['transformResponse']) && $context['transformResponse']) {
  153.             $response['hydra:member'] = $this->listingResponseTransformer->transform($this::ENTITY$entities$context);
  154.             return $response;
  155.         }
  156.         return $entities;
  157.     }
  158.     /**
  159.      * @param array $searchBody
  160.      * @param array $context
  161.      *
  162.      * @return array
  163.      *
  164.      * @throws CacheException
  165.      * @throws ClientExceptionInterface
  166.      * @throws DecodingExceptionInterface
  167.      * @throws InvalidArgumentException
  168.      * @throws RedirectionExceptionInterface
  169.      * @throws ServerExceptionInterface
  170.      * @throws TransportExceptionInterface
  171.      * @throws UnableToSaveKeyException
  172.      */
  173.     public function getRawCollection(array $searchBody, array $context = []): array
  174.     {
  175.         $processedQueries = [];
  176.         $searchBodyWithCorrectCrmKeys = [];
  177.         foreach ($searchBody as $key => $value) {
  178.             if ((empty($value) && '0' !== $value && false !== $value) || (isset($value['equal']) && !isset($value['begin']) && !isset($value['end']))) {
  179.                 continue;
  180.             }
  181.             /*@todo refacto V4: voir si possible de modifier les checkboxType des champs de IGNORE_FALSE_VALUE_FOR en Radio
  182.             ou select pour obtenir une valeur a null si le champs n'est pas nécessaire plutôt que de recourir à cette condition */
  183.             if (false === $value && in_array($keyself::IGNORE_FALSE_VALUE_FORtrue)) {
  184.                 continue;
  185.             }
  186.             $searchBodyWithCorrectCrmKeys[$this->getCrmSearchKey($key$this::ENTITY)] = $value;
  187.         }
  188.         // STEP 1: On vérifie si il y a des builders spécifiques pour chaque filtres
  189.         foreach ($this->filterBuildersChain->getFilterBuilders() as $filterBuilder) {
  190.             if ($filterBuilder->supports($this::ENTITY$searchBodyWithCorrectCrmKeys)) {
  191.                 $processedQueries array_merge($processedQueries$filterBuilder->addFilter($this::ENTITY$this->apiWebService$searchBodyWithCorrectCrmKeys));
  192.             }
  193.         }
  194.         // STEP 2: On ajoute les filtres restants
  195.         foreach ($searchBodyWithCorrectCrmKeys as $searchKey => $searchValue) {
  196.             if (in_array($searchKey$processedQueriestrue)) {
  197.                 continue;
  198.             }
  199.             $this->apiWebService->addFilter($searchKey$searchValue);
  200.             $processedQueries[] = $searchKey;
  201.         }
  202.         if (!($context[self::DISABLE_CUSTOMER_FILTER] ?? false) && !isset($this->apiWebService->getFilters()['customerId'])) {
  203.             $this->apiWebService->addFilterCustomer();
  204.         }
  205.         if ($context[self::DISABLE_AUTHENTICATION] ?? false) {
  206.             $this->apiWebService->disableAuth();
  207.         }
  208.         $action 'list_'.base64_encode(json_encode($this->apiWebService->getFilters()));
  209.         $response $this->cacheManager->get($this::ENTITY$action);
  210.         if (null !== $response && isset($_SERVER['REDIS_ENABLE_V4']) && 'true' === $_SERVER['REDIS_ENABLE_V4']) {
  211.             $this->apiWebService->reset();
  212.             return $response;
  213.         }
  214.         $response $this
  215.             ->apiWebService
  216.             ->send($this->apiProvider$this::METHOD$this::ENDPOINT)
  217.             ->toArray()
  218.         ;
  219.         $this->cacheManager->set($this::ENTITY$action$response);
  220.         return $response;
  221.     }
  222.     /**
  223.      * @param array $searchBody
  224.      *
  225.      * @return bool
  226.      */
  227.     protected function isAllIds(array $searchBody): bool
  228.     {
  229.         return isset($searchBody[AllIdsFilterBuilder::DATA_FILTER_KEY]) && $searchBody[AllIdsFilterBuilder::DATA_FILTER_KEY];
  230.     }
  231.     /**
  232.      * @param array $searchBody
  233.      *
  234.      * @return bool
  235.      */
  236.     protected function isPaginationDisabled(array $searchBody): bool
  237.     {
  238.         return (isset($searchBody[PaginationFilterBuilder::ACTIVATE_PAGNIATION_KEY]) && 'false' === $searchBody[PaginationFilterBuilder::ACTIVATE_PAGNIATION_KEY])
  239.             || $this->isAllIds($searchBody);
  240.     }
  241. }