瀏覽代碼

api request services refactoring and minor fixes of dolibarr sync

Olivier Massot 3 年之前
父節點
當前提交
722d19aa85

+ 1 - 1
doc/logging.md

@@ -66,7 +66,7 @@ Les canaux natifs ou custom sont par défaut gérés par un handler de type rota
 dans `var/log/{env}.main.log`
 
 Certains canaux sont gérés par un handler particulier et logués dans des fichiers spécifiques. Par ex, 
-le canal `doctrine` est redirigé vers `var/log/{env}.doctrine.log`
+le canal `security` est redirigé vers `var/log/{env}.auth.log`
 
 #### critical
 

+ 4 - 5
src/Commands/DolibarrSyncCommand.php

@@ -2,14 +2,13 @@
 
 namespace App\Commands;
 
-use App\Service\Dolibarr\DolibarrSync\DolibarrSyncService;
+use App\Service\Dolibarr\DolibarrSyncService;
 use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Command\LockableTrait;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Question\Question;
 
 #[AsCommand(
     name: 'opentalent:dolibarr-sync',
@@ -40,7 +39,7 @@ class DolibarrSyncCommand extends Command
         );
     }
 
-    protected function execute(InputInterface $input, OutputInterface $output)
+    protected function execute(InputInterface $input, OutputInterface $output): int
     {
         if (!$this->lock()) {
             $output->writeln('The command is already running in another process.');
@@ -68,8 +67,8 @@ class DolibarrSyncCommand extends Command
         } else {
             $t0 = microtime(true);
             $output->writeln("Executing...");
-//            $operations = $this->dolibarrSyncService->execute($operations);
-//            $output->writeln(count($operations) . " operations successfully executed");
+            $operations = $this->dolibarrSyncService->execute($operations);
+            $output->writeln(count($operations) . " operations successfully executed");
 
             $t1 = microtime(true);
             $output->writeln("Execution lasted " . ($t1 - $t0) . " sec.");

+ 1 - 0
src/Enum/Access/FunctionEnum.php

@@ -9,6 +9,7 @@ use MyCLabs\Enum\Enum;
  * Activities functions.
  * @method static STUDENT()
  * @method static ADHERENT()
+ * @method static OTHER()
  */
 class FunctionEnum extends Enum
 {

+ 3 - 3
src/Service/Dolibarr/DolibarrApiService.php

@@ -3,7 +3,7 @@ declare(strict_types=1);
 
 namespace App\Service\Dolibarr;
 
-use App\Service\ApiRequestService;
+use App\Service\Rest\ApiRequestService;
 use JetBrains\PhpStorm\Pure;
 use Symfony\Component\HttpKernel\Exception\HttpException;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -44,7 +44,7 @@ class DolibarrApiService extends ApiRequestService
                 "contracts",
                 ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids" => $socId]
             )[0];
-        } catch (HttpException) {
+        } catch (HttpException $e) {
             if ($e->getStatusCode() == 404) {
                 // /!\ The dolibarr API will return a 404 error if no results are found...
                 return [];
@@ -64,7 +64,7 @@ class DolibarrApiService extends ApiRequestService
             return $this->getJsonContent(
                 "invoices",
                 ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId]);
-        } catch (HttpException) {
+        } catch (HttpException $e) {
             if ($e->getStatusCode() == 404) {
                 // /!\ The dolibarr API will return a 404 error if no results are found...
                 return [];

+ 17 - 18
src/Service/Dolibarr/DolibarrSyncService.php

@@ -1,7 +1,7 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service\Dolibarr\DolibarrSync;
+namespace App\Service\Dolibarr;
 
 use App\Entity\Organization\Organization;
 use App\Entity\Person\Person;
@@ -17,10 +17,9 @@ use App\Repository\Access\FunctionTypeRepository;
 use App\Repository\Core\ContactPointRepository;
 use App\Repository\Organization\OrganizationRepository;
 use App\Service\Core\AddressPostalUtils;
-use App\Service\Dolibarr\DolibarrApiService;
-use App\Service\Dolibarr\DolibarrSync\SyncOperation\DolibarrCreateOperation;
-use App\Service\Dolibarr\DolibarrSync\SyncOperation\DolibarrSyncOperation;
-use App\Service\Dolibarr\DolibarrSync\SyncOperation\DolibarrUpdateOperation;
+use App\Service\Rest\Operation\BaseRestOperation;
+use App\Service\Rest\Operation\CreateOperation;
+use App\Service\Rest\Operation\UpdateOperation;
 use Exception;
 use HttpException;
 use libphonenumber\PhoneNumber;
@@ -55,7 +54,7 @@ class DolibarrSyncService
      *
      * Returns an array of DolibarrSyncOperations
      *
-     * @return array<DolibarrSyncOperation>
+     * @return array<BaseRestOperation>
      * @throws Exception
      */
     public function scan(): array {
@@ -154,7 +153,7 @@ class DolibarrSyncService
 
             // Add an update operation if some data has to be updated
             if (!empty($newSocietyData)) {
-                $operations[] = new DolibarrUpdateOperation(
+                $operations[] = new UpdateOperation(
                     'Update society : ' . $organization->getName() . ' (' . $organization->getId() . ')',
                     'thirdparties',
                     $dolibarrSociety,
@@ -211,7 +210,7 @@ class DolibarrSyncService
                         ];
 
                         if ($dolibarrContact === null) {
-                            $operations[] = new DolibarrCreateOperation(
+                            $operations[] = new CreateOperation(
                                 'New contact: ' . $person->getName() . ' ' . $person->getGivenName() . ' (' . $person->getId() . ')',
                                 'contacts',
                                 $newContactData
@@ -226,7 +225,7 @@ class DolibarrSyncService
 
                             // add an update operation if some data has to be updated
                             if (!empty($newContactData)) {
-                                $operations[] = new DolibarrUpdateOperation(
+                                $operations[] = new UpdateOperation(
                                     'Update contact: ' . $person->getName() . ' ' . $person->getGivenName() . ' (' . $person->getId() . ')' .
                                     ' in ' . $organization->getName() . ' (' . $organization->getId() . ')',
                                     'contacts',
@@ -249,7 +248,7 @@ class DolibarrSyncService
                 }
                 if (!in_array($personId, $contactsProcessed)) {
                     // Ce personId n'existe plus dans les membres Opentalent de cette société, on delete
-                    $operations[] = new DolibarrUpdateOperation(
+                    $operations[] = new UpdateOperation(
                         'Disable contact: ' . $contactData['lastname'] . ' ' . $contactData['firstname'] . ' (' . $personId . ')' .
                         ' from  ' . $organization->getName() . ' (' . $organization->getId() . ')',
                         'contacts',
@@ -277,8 +276,8 @@ class DolibarrSyncService
      *
      * Returns an array of DolibarrSyncOperations
      *
-     * @param array<DolibarrSyncOperation> $operations
-     * @return array<DolibarrSyncOperation>
+     * @param array<BaseRestOperation> $operations
+     * @return array<BaseRestOperation>
      * @throws Exception
      */
     public function execute(array $operations): array
@@ -288,21 +287,21 @@ class DolibarrSyncService
         $done = 0; $errors = 0; $unknown = 0;
 
         foreach ($operations as $operation) {
-            if ($operation->getStatus() !== DolibarrSyncOperation::STATUS_READY) {
+            if ($operation->getStatus() !== BaseRestOperation::STATUS_READY) {
                 // operation has already been treated
                 $this->logger->warning('Tried to execute an operation that was not marked as ready : ' . $operation);
                 continue;
             }
 
-            $operation->execute(
-                $this->dolibarrApiService
+            $operation = $this->dolibarrApiService->execute(
+                $operation
             );
 
-            if ($operation->getStatus() === DolibarrSyncOperation::STATUS_ERROR) {
+            if ($operation->getStatus() === BaseRestOperation::STATUS_ERROR) {
                 $this->logger->error('Error while executing operation : ' . $operation);
                 $this->logger->error($operation->getErrorMessage());
                 $errors++;
-            } elseif ($operation->getStatus() === DolibarrSyncOperation::STATUS_DONE) {
+            } elseif ($operation->getStatus() === BaseRestOperation::STATUS_DONE) {
                 $done++;
             } else {
                 $unknown++;
@@ -321,8 +320,8 @@ class DolibarrSyncService
     /**
      * Scan and execute the sync process
      *
+     * @return array<BaseRestOperation>
      * @throws HttpException
-     * @return array<DolibarrSyncOperation>
      * @throws Exception
      */
     public function run(): array

+ 1 - 1
src/Service/Mobyt/MobytService.php

@@ -3,7 +3,7 @@ declare(strict_types=1);
 
 namespace App\Service\Mobyt;
 
-use App\Service\ApiRequestService;
+use App\Service\Rest\ApiRequestService;
 use JetBrains\PhpStorm\Pure;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 

+ 99 - 1
src/Service/Rest/ApiRequestInterface.php

@@ -1,8 +1,106 @@
 <?php
+declare(strict_types = 1);
 
 namespace App\Service\Rest;
 
-class ApiRequestInterface
+use App\Service\Rest\Operation\BaseRestOperation;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Contracts\HttpClient\ResponseInterface;
+
+/**
+ * Interface for services sending requests to an external REST API
+ */
+interface ApiRequestInterface
 {
+    /**
+     * Sends a GET request and returns the response's body decoded as json
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return array
+     * @throws HttpException
+     */
+    function getJsonContent(string $path, array $parameters = [], array $options = []): array;
+
+    /**
+     * Sends a GET request and returns the response's body
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return string
+     * @throws HttpException
+     */
+    function getContent(string $path, array $parameters = [], array $options = []): string;
+
+    /**
+     * Sends a GET request and returns the response
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     * @throws HttpException
+     */
+    function get(string $path, array $parameters = [], array $options = []): ResponseInterface;
+
+    /**
+     * Sends a POST request and returns the response
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     * @throws HttpException
+     */
+    function post(string $path, array $parameters = [], array $options = []): ResponseInterface;
+
+    /**
+     * Sends a PUT request and returns the response
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     * @throws HttpException
+     */
+    function put(string $path, array $parameters = [], array $options = []): ResponseInterface;
+
+    /**
+     * Sends a DELETE request and returns the response
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     * @throws HttpException
+     */
+    function delete(string $path, array $parameters = [], array $options = []): ResponseInterface;
+
+    /**
+     * Send an HTTP request to the Dolibarr API,
+     * and return the decoded content of the response's body
+     *
+     * @param string $method
+     * @param string $url
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     * @throws HttpException
+     */
+    function request(
+        string $method,
+        string $url,
+        array  $parameters = [],
+        array  $options = []
+    ): ResponseInterface;
+
+    /**
+     * Executes the given Rest Operation, then returns it
+     *
+     * @param BaseRestOperation $operation
+     * @return BaseRestOperation
+     */
+    function execute(BaseRestOperation $operation): BaseRestOperation;
 
 }

+ 17 - 3
src/Service/Rest/ApiRequestService.php

@@ -1,8 +1,9 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service;
+namespace App\Service\Rest;
 
+use App\Service\Rest\Operation\BaseRestOperation;
 use App\Service\Utils\UrlBuilder;
 use Symfony\Component\HttpKernel\Exception\HttpException;
 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
@@ -16,7 +17,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
 /**
  * Base class for services sending requests to an external API
  */
-class ApiRequestService
+class ApiRequestService implements ApiRequestInterface
 {
     function __construct(
         protected HttpClientInterface $client
@@ -60,7 +61,7 @@ class ApiRequestService
      * @return ResponseInterface
      * @throws HttpException
      */
-    protected function get(string $path, array $parameters = [], array $options = []): ResponseInterface {
+    public function get(string $path, array $parameters = [], array $options = []): ResponseInterface {
         return $this->request('GET', $path, $parameters, $options);
     }
 
@@ -132,4 +133,17 @@ class ApiRequestService
             throw new HttpException(500, 'Request error : ', $e);
         }
     }
+
+    /**
+     * Executes the given Rest Operation, then returns it
+     *
+     * @param BaseRestOperation $operation
+     * @return BaseRestOperation
+     */
+    public function execute(BaseRestOperation $operation): BaseRestOperation
+    {
+        $operation->setApiRequestService($this);
+        $operation->execute();
+        return $operation;
+    }
 }

+ 4 - 3
src/Service/Rest/Operation/BaseRestOperation.php

@@ -1,8 +1,9 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service\Rest\SyncOperation;
+namespace App\Service\Rest\Operation;
 
+use App\Service\Rest\ApiRequestInterface;
 use App\Service\Rest\ApiRequestService;
 use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
 use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
@@ -11,7 +12,7 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\Service\Attribute\Required;
 
 /**
- * Single synchronization operation, corresponding to a single request
+ * A single operation, corresponding to a single request
  * to a REST API
  */
 abstract class BaseRestOperation
@@ -21,7 +22,7 @@ abstract class BaseRestOperation
     const STATUS_DONE = 2;
     const STATUS_ERROR = 3;
 
-    protected ApiRequestService $apiService;
+    protected ApiRequestInterface $apiService;
     protected int $status = self::STATUS_READY;
     protected string $label;
     protected string $method;

+ 4 - 1
src/Service/Rest/Operation/CreateOperation.php

@@ -1,10 +1,13 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service\Rest\SyncOperation;
+namespace App\Service\Rest\Operation;
 
 use JetBrains\PhpStorm\Pure;
 
+/**
+ * A single create operation (a POST request)
+ */
 class CreateOperation extends BaseRestOperation
 {
     protected string $entity;

+ 4 - 1
src/Service/Rest/Operation/DeleteOperation.php

@@ -1,10 +1,13 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service\Rest\SyncOperation;
+namespace App\Service\Rest\Operation;
 
 use JetBrains\PhpStorm\Pure;
 
+/**
+ * A single delete operation (a DELETE request)
+ */
 class DeleteOperation extends BaseRestOperation
 {
     protected string $entity;

+ 4 - 1
src/Service/Rest/Operation/UpdateOperation.php

@@ -1,10 +1,13 @@
 <?php
 declare(strict_types=1);
 
-namespace App\Service\Rest\SyncOperation;
+namespace App\Service\Rest\Operation;
 
 use JetBrains\PhpStorm\Pure;
 
+/**
+ * A single update operation (a PUT request)
+ */
 class UpdateOperation extends BaseRestOperation
 {
     protected string $entity;