瀏覽代碼

move opentalent api requests to a new service

Olivier Massot 4 年之前
父節點
當前提交
de857bbb7d

+ 31 - 142
ot_core/Classes/Domain/Repository/BaseApiRepository.php

@@ -5,12 +5,14 @@ namespace Opentalent\OtCore\Domain\Repository;
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\GuzzleException;
 use Opentalent\OtCore\Exception\ApiRequestException;
+use Opentalent\OtCore\Service\OpentalentApiService;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
 use Symfony\Component\Yaml\Exception\ParseException;
 use Symfony\Component\Yaml\Yaml;
 use TYPO3\CMS\Core\Core\ApplicationContext;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
 
 /**
@@ -21,80 +23,42 @@ abstract class BaseApiRepository implements LoggerAwareInterface
 {
     use LoggerAwareTrait;
 
-    const DEFAULT_BASE_URI = 'https://api.opentalent.fr/api/';
     const URI_TRAILING_PART = '';
     const HYDRA_TYPE = '';
-    const HTTP_METHOD = 'GET';
     const DEFAULT_ITEMS_PER_PAGE = 8;
 
-    protected string $base_uri = self::DEFAULT_BASE_URI;
-    protected array $variants_uris = [];
-    protected Client $client;
-    protected ApplicationContext $context;
+    protected $apiService;
 
     /**
      * BaseApiRepository constructor.
-     *
-     * @param ObjectManagerInterface $objectManager
-     * @param Client|null $client  [For tests only]
-     * @param ApplicationContext|null $context  [For tests only]
      */
-    public function __construct(
-        ?Client $client = null,
-        ?ApplicationContext $context = null
-    ) {
-        if ($context === null) {
-            $this->context = \TYPO3\CMS\Core\Core\Environment::getContext();
-        } else {
-            $this->context = $context;
-        }
-
-        $this->loadConf();
-
-        if ($client === null) {
-            $this->client = new Client(['base_uri' => $this->getApiUri()]);
-        } else {
-            $this->client = $client;
-        }
-    }
-
-    private function loadConf() {
-        $conf_path = $_ENV['TYPO3_PATH_ROOT'] . '/typo3conf/ext/ot_core/Configuration/ot_config.yaml';
-        $conf = Yaml::parseFile($conf_path);
-
-        // api_variant_uri: Should we set an alternative uri for the API? (dev and testing only)
-        if ($this->context->isDevelopment() || $this->context->isTesting()) {
-            $this->variants_uris = $conf['api_variant_uri'];
-        }
+    public function __construct() {
+        $this->apiService = GeneralUtility::makeInstance(OpentalentApiService::class);
     }
 
     /**
-     * Return the API URI for the current repository
-     *
-     * @param string $trailing_part
-     * @return string
+     * -- Needs to be reimplemented in subclasses --
+     * Convert response's members record to an actual Domain's object
+     * @param array $record
+     * @return object
      */
-    protected function getApiUri(string $trailing_part = null): string
-    {
-        $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['VIRTUAL_HOST'];
-
-        if (isset($this->variants_uris[$host])) {
-            $uri = $this->variants_uris[$host];
-        } else {
-            $uri = self::DEFAULT_BASE_URI;
-        }
-
-        $trailing_part = $trailing_part ?? $this::URI_TRAILING_PART;
-        $uri = rtrim($uri, '/') . '/' . ltrim($trailing_part, '/');
-        return $uri;
-    }
+    abstract protected function memberToObject(array $record);
 
     /**
-     * [FOR TESTS ONLY]
-     * @param Client $client
+     * Send a request to the API and
+     * returns the first record (member)
+     *
+     * @param array $params
+     * @param string|null $forceUri
+     * @return object
+     * @throws ApiRequestException
      */
-    protected function injectClient(Client $client) {
-        $this->client = $client;
+    protected function getApiFirstRecord($params = [], ?string $forceUri = null)
+    {
+        $params['page'] = '1';
+        $params['totalItems'] = '1';
+        $collection = $this->getApiRecords($params, $forceUri);
+        return $collection->getMembers()[0];
     }
 
     /**
@@ -108,9 +72,15 @@ abstract class BaseApiRepository implements LoggerAwareInterface
      */
     protected function getApiRecords(array $params = [], ?string $forceUri = null): ApiPagedCollection
     {
-        $uri = $forceUri ?? $this->getApiUri();
+        if(!isset($params['itemsPerPage'])) {
+            $params['itemsPerPage'] = (string)self::DEFAULT_ITEMS_PER_PAGE;
+        }
 
-        $body = $this->getJsonDecoded($uri, $params);
+        $uri = ltrim($this::URI_TRAILING_PART, '/');
+        if ($forceUri !== null) {
+            $uri = trim($forceUri, '/') . '/' . $uri;
+        }
+        $body = $this->apiService->getJsonDecoded($uri, $params);
 
         $page = (int)($params['page'] ?? 1);
 
@@ -133,85 +103,4 @@ abstract class BaseApiRepository implements LoggerAwareInterface
             $members
         );
     }
-
-    /**
-     * -- Needs to be reimplemented in subclasses --
-     * Convert response's members record to an actual Domain's object
-     * @param array $record
-     * @return object
-     */
-    abstract protected function memberToObject(array $record);
-
-    /**
-     * Send a request to the API and
-     * returns the first record (member)
-     *
-     * @param array $params
-     * @param string|null $forceUri
-     * @return object
-     * @throws ApiRequestException
-     */
-    protected function getApiFirstRecord($params = [], ?string $forceUri = null)
-    {
-        $params['page'] = '1';
-        $params['totalItems'] = '1';
-        $collection = $this->getApiRecords($params, $forceUri);
-        return $collection->getMembers()[0];
-    }
-
-    /**
-     * Send a request to the API and
-     * returns the Json response as an array
-     *
-     * @param string $uri
-     * @param array $params
-     * @return array
-     * @throws ApiRequestException
-     */
-    protected function getJsonDecoded(string $uri, $params = []): array
-    {
-        return json_decode($this->getBody($uri, $params),true);
-    }
-
-    /**
-     * Send a request to the API and returns
-     * the response's body as a string
-     *
-     * @param string $uri
-     * @param array $params
-     * @return string
-     * @throws ApiRequestException
-     */
-    protected function getBody(string $uri, $params = [])
-    {
-        return (string)$this->getResponse($uri, $params)->getBody();
-    }
-
-    /**
-     * Send a request to the API and returns
-     * the result as a Response object
-     *
-     * @param string $uri
-     * @param array $params
-     * @return ResponseInterface
-     * @throws ApiRequestException
-     */
-    protected function getResponse(string $uri, $params = []): ResponseInterface
-    {
-        $uri = $uri . '?_format=json';
-        if(!isset($params['itemsPerPage'])) {
-            $params['itemsPerPage'] = (string)self::DEFAULT_ITEMS_PER_PAGE;
-        }
-        if (!empty($params)) {
-            $uri = $uri . '&' . http_build_query($params);
-        }
-        try {
-            if ($this->context->isDevelopment()) {
-                $this->logger->info('API Call: ' . $uri);
-            }
-            return $this->client->request(static::HTTP_METHOD, $uri);
-        } catch (GuzzleException $e) {
-            throw ApiRequestException::from_exception($e);
-        }
-    }
 }

+ 1 - 1
ot_core/Classes/Domain/Repository/DonorRepository.php

@@ -7,7 +7,7 @@ use Opentalent\OtCore\Exception\ApiRequestException;
 
 class DonorRepository extends BaseApiRepository
 {
-    const URI_TRAILING_PART = 'public/donors';
+    const URI_TRAILING_PART = '/api/public/donors';
     const HYDRA_TYPE = 'PortailDonor';
 
     /**

+ 1 - 1
ot_core/Classes/Domain/Repository/EventRepository.php

@@ -8,7 +8,7 @@ use Opentalent\OtCore\Exception\ApiRequestException;
 
 class EventRepository extends BaseApiRepository
 {
-    const URI_TRAILING_PART = 'public/events';
+    const URI_TRAILING_PART = '/api/public/events';
     const HYDRA_TYPE = 'PortailEvent';
 
     /**

+ 2 - 2
ot_core/Classes/Domain/Repository/MemberRepository.php

@@ -9,8 +9,8 @@ use Opentalent\OtCore\Exception\ApiRequestException;
 
 class MemberRepository extends BaseApiRepository
 {
-    const URI_TRAILING_PART = 'public/members';
-    const URI_TRAILING_PART_CA = 'public/members_ca';
+    const URI_TRAILING_PART = '/api/public/members';
+    const URI_TRAILING_PART_CA = '/api/public/members_ca';
     const HYDRA_TYPE = 'PortailMemberBySpeciality';
     const HYDRA_TYPE_CA = 'PortailMemberByRole';
 

+ 1 - 1
ot_core/Classes/Domain/Repository/OrganizationRepository.php

@@ -8,7 +8,7 @@ use Opentalent\OtCore\Exception\ApiRequestException;
 
 class OrganizationRepository extends BaseApiRepository
 {
-    const URI_TRAILING_PART = 'public/organizations';
+    const URI_TRAILING_PART = '/api/public/organizations';
     const HYDRA_TYPE = 'PortailOrganization';
 
     /**

+ 164 - 0
ot_core/Classes/Service/OpentalentApiService.php

@@ -0,0 +1,164 @@
+<?php
+
+namespace Opentalent\OtCore\Service;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\GuzzleException;
+use Opentalent\OtCore\Exception\ApiRequestException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use TYPO3\CMS\Core\Core\ApplicationContext;
+use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
+
+class OpentalentApiService implements LoggerAwareInterface
+{
+    use LoggerAwareTrait;
+
+    const DEFAULT_BASE_URI = 'https://api.opentalent.fr';
+    protected array $variants_uris = [
+          "preprod.opentalent.fr" => "https://api.preprod.opentalent.fr",
+          "local.sub.opentalent.fr" => "http://nginx",
+          "typo3" => "http://nginx"
+    ];
+
+    protected Client $client;
+    protected ApplicationContext $context;
+
+    /**
+     * @param ObjectManagerInterface $objectManager
+     * @param Client|null $client  [For tests only]
+     * @param ApplicationContext|null $context  [For tests only]
+     */
+    public function __construct(
+        ?Client $client = null,
+        ?ApplicationContext $context = null
+    ) {
+        // Get the current context (prod, dev...)
+        if ($context === null) {
+            $this->context = \TYPO3\CMS\Core\Core\Environment::getContext();
+        } else {
+            $this->context = $context;
+        }
+
+        if ($client === null) {
+            $this->client = new Client(['base_uri' => $this->getApiUri()]);
+        } else {
+            $this->client = $client;
+        }
+    }
+
+    /**
+     * [FOR TESTS ONLY]
+     * @param Client $client
+     */
+    protected function injectClient(Client $client) {
+        $this->client = $client;
+    }
+
+    /**
+     * Return the API URI for the current repository
+     *
+     * @param string $trailing_part
+     * @return string
+     */
+    protected function getApiUri(string $trailing_part = ""): string
+    {
+        $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['VIRTUAL_HOST'];
+
+        if (isset($this->variants_uris[$host])) {
+            $uri = $this->variants_uris[$host];
+        } else {
+            $uri = self::DEFAULT_BASE_URI;
+        }
+
+        return rtrim($uri, '/') . '/' . ltrim($trailing_part, '/');
+    }
+
+    /**
+     * Send a request to the API and
+     * returns the Json response as an array
+     *
+     * @param string $uri
+     * @param array $params
+     * @return array
+     * @throws ApiRequestException
+     */
+    public function getJsonDecoded(
+        string $uri,
+        array $params = []
+    ): array
+    {
+        return json_decode($this->getBody($uri, $params),true);
+    }
+
+    /**
+     * Send a request to the API and returns
+     * the response's body as a string
+     *
+     * @param string $uri
+     * @param array $params
+     * @return string
+     * @throws ApiRequestException
+     */
+    public function getBody(
+        string $uri,
+        array $params = []
+    ): string
+    {
+        return (string)$this->get($uri, $params)->getBody();
+    }
+
+    /**
+     * Send a GET request to the API and returns
+     * the result as a Response object
+     *
+     * @param string $uri
+     * @param array $params
+     * @return ResponseInterface
+     * @throws ApiRequestException
+     */
+    public function get(
+        string $uri,
+        array $params = []
+    ): ResponseInterface
+    {
+        return $this->request('GET', $uri, $params);
+    }
+
+    /**
+     * Send a request to the API and returns
+     * the result as a Response object
+     *
+     * @param string $uri
+     * @param array $params
+     * @param string $httpMethod
+     * @return ResponseInterface
+     * @throws ApiRequestException
+     */
+    public function request(
+        string $httpMethod,
+        string $uri,
+        array $params = []
+    ): ResponseInterface
+    {
+        $parsedUrl = parse_url($uri);
+
+        $params['_format'] = 'json';
+        array_unshift($params, $parsedUrl['query']);
+        $uri = $uri . '?' . http_build_query($params);
+
+        if ($parsedUrl['query']) {
+            $uri = $uri . '&' . $parsedUrl['query'];
+        }
+
+        try {
+            if ($this->context->isDevelopment()) {
+                $this->logger->info('API Call: ' . $uri);
+            }
+            return $this->client->request($httpMethod, $uri);
+        } catch (GuzzleException $e) {
+            throw ApiRequestException::from_exception($e);
+        }
+    }
+}