Ver código fonte

refactoring après réunion avec Gregoire

Vincent GUFFON 4 anos atrás
pai
commit
aa8345f66d

Diferenças do arquivo suprimidas por serem muito extensas
+ 94 - 350
composer.lock


+ 11 - 11
config/opentalent/modulesbyconditions.yaml

@@ -5,67 +5,67 @@ opentalent:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isLastParentAndCMF
         CotisationStructure:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isStructureAndCMF
         CotisationRate:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isManagerAndLastParentAndCMF
         CotisationTransmissionState:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isManagerAndCMF
         CotisationTransmission:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isManagerAndNotLastParentAndCMF
         CotisationCMFAdministration:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.organization.utils
+                    name: 'App\Service\Organization\Utils'
                     function: isOrganizationIsCMF
         Admin2IOS:
             roles:
                 - ROLE_ADMIN2IOS
             conditions:
                 service:
-                    name: opentalent.organization.utils
+                    name: 'App\Service\Organization\Utils'
                     function: isOrganizationIs2ios
         StatisticFederation:
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isManagerAndNotLastParentAndCMF
         StatisticStructure:
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: 'App\Service\Cotisation\Utils'
                     function: isManagerAndCMF
         Network:
             conditions:
                 service:
-                    name: opentalent.network.utils
+                    name: 'App\Service\Network\Utils'
                     function: isCMF
         NetworkOrganization:
             conditions:
                 service:
-                    name: opentalent.network.utils
+                    name: 'App\Service\Network\Utils'
                     function: isCMF

+ 2 - 0
config/packages/framework.yaml

@@ -20,3 +20,5 @@ framework:
         scoped_clients:
             siret_checking:
                 base_uri: 'https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/'
+            openstreetmap:
+                base_uri: 'https://nominatim.openstreetmap.org/'

+ 4 - 6
config/packages/security.yaml

@@ -134,6 +134,8 @@ security:
                 class: App\Entity\Person\Person
                 property: username
 
+    enable_authenticator_manager: true
+
     firewalls:
         dev:
             pattern: ^/(_(profiler|wdt)|css|images|js)/
@@ -142,7 +144,6 @@ security:
         login:
             pattern:  ^/login_check
             stateless: true
-            anonymous: true
             json_login:
                 provider: person_provider
                 check_path: /login_check
@@ -151,15 +152,12 @@ security:
                 success_handler: lexik_jwt_authentication.handler.authentication_success
                 failure_handler: lexik_jwt_authentication.handler.authentication_failure
         api:
+            jwt: ~
             pattern: ^/api/
             stateless: true
-            anonymous: true
             provider: access_provider
-            guard:
-                authenticators:
-                - lexik_jwt_authentication.jwt_token_authenticator
+
         main:
-            anonymous: true
             # activate different ways to authenticate
             # https://symfony.com/doc/current/security.html#firewalls-authentication
 

+ 19 - 8
config/services.yaml

@@ -1,8 +1,3 @@
-# This file is the entry point to configure your own services.
-# Files in the packages/ subdirectory configure your dependencies.
-imports:
-    - { resource: services/* }
-
 # Put parameters here that don't need to change on each machine where the app is deployed
 # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
 parameters:
@@ -15,6 +10,10 @@ services:
         bind:
             $opentalentConfig: '%kernel.project_dir%%env(OPENTALENT_CONFIG)%'
 
+    _instanceof:
+        App\Doctrine\Access\AccessExtensionInterface:
+            tags: ['app.extensions.access']
+
     # makes classes in src/ available to be used as services
     # this creates a service per class whose id is the fully-qualified class name
     App\:
@@ -24,6 +23,18 @@ services:
             - '../src/Entity/'
             - '../src/Kernel.php'
             - '../src/Tests/'
-            - '../src/Controller/'
-            - '../src/DataProvider/'
-            - '../src/Serializer/'
+
+    App\Serializer\OpentalentNormalizer:
+        decorates: 'api_platform.jsonld.normalizer.item'
+
+    App\Service\Cotisation\Utils:
+        public: true
+
+    App\Service\Network\Utils:
+        public: true
+
+    App\Service\Organization\Utils:
+        public: true
+
+    App\Doctrine\Access\HandleAccessExtension:
+        - !tagged_iterator app.extensions.access

+ 0 - 14
config/services/apiPlatform.yaml

@@ -1,14 +0,0 @@
-services:
-  # default configuration for services in *this* file
-  _defaults:
-    autowire: true      # Automatically injects dependencies in your services.
-    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
-    public: false
-    bind:
-      $opentalentConfig: '%kernel.project_dir%%env(OPENTALENT_CONFIG)%'
-
-  App\DataProvider\:
-    resource: '../../src/DataProvider/'
-
-  App\Serializer\OpentalentNormalizer:
-    decorates: 'api_platform.jsonld.normalizer.item'

+ 0 - 18
config/services/controlers.yaml

@@ -1,18 +0,0 @@
-services:
-  # default configuration for services in *this* file
-  _defaults:
-    autowire: true      # Automatically injects dependencies in your services.
-    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
-
-  # controllers are imported separately to make sure services can be injected
-  # as action arguments even if you don't extend any base controller class
-  App\Controller\:
-    resource: '../../src/Controller/'
-    tags: ['controller.service_arguments']
-
-  App\Controller\EsController:
-    tags: ['controller.service_arguments']
-    public: true
-    arguments:
-      - '@fos_elastica.index_manager'
-      - '@fos_elastica.elastica_to_model_transformer.collection.search'

+ 0 - 13
config/services/services.yaml

@@ -1,13 +0,0 @@
-services:
-  opentalent.cotisation.utils:
-    class: App\Service\Cotisation\Utils
-    public: true
-    autowire: true
-  opentalent.network.utils:
-    class: App\Service\Network\Utils
-    public: true
-    autowire: true
-  opentalent.organization.utils:
-    class: App\Service\Organization\Utils
-    public: true
-    autowire: true

+ 0 - 49
src/Controller/EsController.php

@@ -1,49 +0,0 @@
-<?php
-// src/Controller/LuckyController.php
-namespace App\Controller;
-
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-use Symfony\Component\HttpFoundation\Response;
-use FOS\ElasticaBundle\Index\IndexManager;
-use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection;
-use Symfony\Component\Routing\Annotation\Route;
-
-
-/**
- * Class EsController
- * @package App\Controller
- */
-class EsController extends AbstractController
-{
-    private $elasticaIndexManager;
-    private $elasticaToModelTransformerCollectionSearch;
-
-    public function __construct(IndexManager $elasticaIndexManager, ElasticaToModelTransformerCollection $elasticaToModelTransformerCollectionSearch)
-    {
-        $this->elasticaToModelTransformerCollectionSearch = $elasticaToModelTransformerCollectionSearch;
-        $this->elasticaIndexManager = $elasticaIndexManager;
-    }
-
-    /**
-     * @Route("/es_test")
-     * @return Response
-     */
-    public function es_test(): Response
-    {
-        $search = $this->elasticaIndexManager->getIndex('search')->createSearch();
-        $search->addType('organization');
-        $options['limit'] = 10;
-
-        $queryPart = new \Elastica\Query\BoolQuery();
-        $filtered = new \Elastica\Query\Filtered($queryPart);
-
-
-        $query = \Elastica\Query::create($filtered);
-        $resultSet = $search->search($query->getQuery(), $options);
-
-        $response = $this->elasticaToModelTransformerCollectionSearch->transform($resultSet->getResults());
-
-        dump($response);
-        die;
-    }
-}

+ 49 - 0
src/Controller/EsController.php.ori

@@ -0,0 +1,49 @@
+<?php
+//// src/Controller/LuckyController.php
+//namespace App\Controller;
+//
+//use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+//use Symfony\Component\HttpFoundation\Response;
+//use FOS\ElasticaBundle\Index\IndexManager;
+//use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection;
+//use Symfony\Component\Routing\Annotation\Route;
+//
+//
+///**
+// * Class EsController
+// * @package App\Controller
+// */
+//class EsController extends AbstractController
+//{
+//    private $elasticaIndexManager;
+//    private $elasticaToModelTransformerCollectionSearch;
+//
+//    public function __construct(IndexManager $elasticaIndexManager, ElasticaToModelTransformerCollection $elasticaToModelTransformerCollectionSearch)
+//    {
+//        $this->elasticaToModelTransformerCollectionSearch = $elasticaToModelTransformerCollectionSearch;
+//        $this->elasticaIndexManager = $elasticaIndexManager;
+//    }
+//
+//    /**
+//     * @Route("/es_test")
+//     * @return Response
+//     */
+//    public function es_test(): Response
+//    {
+//        $search = $this->elasticaIndexManager->getIndex('search')->createSearch();
+//        $search->addType('organization');
+//        $options['limit'] = 10;
+//
+//        $queryPart = new \Elastica\Query\BoolQuery();
+//        $filtered = new \Elastica\Query\Filtered($queryPart);
+//
+//
+//        $query = \Elastica\Query::create($filtered);
+//        $resultSet = $search->search($query->getQuery(), $options);
+//
+//        $response = $this->elasticaToModelTransformerCollectionSearch->transform($resultSet->getResults());
+//
+//        dump($response);
+//        die;
+//    }
+//}

+ 6 - 68
src/DataProvider/Access/AccessProfileDataProvider.php

@@ -1,4 +1,5 @@
 <?php
+
 declare(strict_types=1);
 
 namespace App\DataProvider\Access;
@@ -6,13 +7,8 @@ namespace App\DataProvider\Access;
 use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
 use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
 use App\ApiResources\Profile\AccessProfile;
-use App\ApiResources\Profile\OrganizationProfile;
 use App\Entity\Access\Access;
-use App\Entity\Organization\Organization;
-use App\Service\Network\Tree;
-use App\Service\Security\Module;
-use Symfony\Component\Security\Core\Role\Role;
-use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
+use App\Service\Access\AccessProfileCreator;
 use Symfony\Component\Security\Core\Security;
 
 /**
@@ -22,21 +18,15 @@ use Symfony\Component\Security\Core\Security;
 final class AccessProfileDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
     private Security $security;
-    private RoleHierarchyInterface $roleHierarchy;
-    private Module $module;
-    private Tree $tree;
+    private AccessProfileCreator $accessProfileCreator;
 
     public function __construct(
         Security $security,
-        RoleHierarchyInterface $roleHierarchy,
-        Module $module,
-        Tree $tree
+        AccessProfileCreator $accessProfileCreator
     )
     {
         $this->security = $security;
-        $this->roleHierarchy = $roleHierarchy;
-        $this->module = $module;
-        $this->tree = $tree;
+        $this->accessProfileCreator = $accessProfileCreator;
     }
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
@@ -48,58 +38,6 @@ final class AccessProfileDataProvider implements ItemDataProviderInterface, Rest
     {
         /** @var Access $access */
         $access = $this->security->getUser();
-
-        $myProfile = $this->setProfileFromAccess($access);
-        $myProfile->setRoles($this->roleHierarchy->getReachableRoleNames($this->security->getToken()->getRoleNames()));
-
-        $myProfile->setOrganization($this->setOrganizationProfileFromOrganization($access->getOrganization()));
-
-        return $myProfile;
-    }
-
-    /**
-     * Hydratation du profile de l'access connecté via la resource accessProfile
-     * @param Access $access
-     * @return AccessProfile
-     */
-    public function setProfileFromAccess(Access $access): AccessProfile
-    {
-        $accessProfile = new AccessProfile();
-        $accessProfile->setId($access->getId());
-        $accessProfile->setIsAdminAccess($access->getAdminAccess());
-        $accessProfile->setName($access->getPerson()->getName());
-        $accessProfile->setGivenName($access->getPerson()->getGivenName());
-        return $accessProfile;
-    }
-
-    /**
-     * Hydratation du profile des organizations auxquelles l'access connecté est inscrit
-     * @param Organization $organization
-     * @return OrganizationProfile
-     */
-    public function setOrganizationProfileFromOrganization(Organization $organization): OrganizationProfile{
-        $organizationProfile = new OrganizationProfile();
-        $organizationProfile->setId($organization->getId());
-        $organizationProfile->setName($organization->getName());
-        $organizationProfile->setModules($this->module->getOrganizationModules($organization));
-        $organizationProfile->setProduct($organization->getSettings()->getProduct());
-        $organizationProfile->setHasChildren($organization->getNetworkOrganizationChildren()->count() > 1);
-        $organizationProfile->setSubDomain($organization->getParameters()->getSubDomain());
-        $organizationProfile->setWebsite($organization->getParameters()->getWebsite());
-
-        foreach ($organization->getNetworkOrganizations() as $networkOrganization){
-            $organizationProfile->addNetwork($networkOrganization->getNetwork()->getName());
-        }
-
-        /** @var Organization $parent */
-        foreach ($this->tree->findAllParentsAndSortByType($organization) as $parent){
-            $parentProfile = new OrganizationProfile();
-            $parentProfile->setId($parent->getId());
-            $parentProfile->setName($parent->getName());
-            $parentProfile->setSubDomain($parent->getParameters()->getSubDomain());
-            $parentProfile->setWebsite($parent->getParameters()->getWebsite());
-            $organizationProfile->addParent($parentProfile);
-        }
-        return $organizationProfile;
+        return $this->accessProfileCreator->getAccessProfile($access);
     }
 }

+ 2 - 8
src/DataProvider/Enum/EnumDataProvider.php

@@ -44,19 +44,13 @@ final class EnumDataProvider implements ItemDataProviderInterface, RestrictedDat
         if(!$enumClass)
             throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $name));
 
-        $items = [];
         try{
             $items = $this->reflection->dynamicInvokeClassWithArgsAndMethod(
                 $enumClass,
-                'toArrayCustom'
+                'toArray'
             );
         }catch (\Exception $exception){
-            try{
-                $items = $this->reflection->dynamicInvokeClassWithArgsAndMethod(
-                    $enumClass,
-                    'toArray'
-                );
-            }catch (\Exception $exception){}
+            throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $name));
         }
 
         $enumResponse = new Enum();

+ 1 - 1
src/DataProvider/Utils/SiretDataProvider.php

@@ -10,7 +10,7 @@ use App\Service\Utils\Siret as SiretUtils;
 
 /**
  * Class SiretDataProvider : custom provider pour assurer l'alimentation des utils Siret
- * @package App\DataProvider\Access
+ * @package App\DataProvider\Utils
  */
 final class SiretDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {

+ 59 - 3
src/Entity/Access/Access.php

@@ -19,8 +19,16 @@ use Symfony\Component\Security\Core\User\UserInterface;
  * Fais le lien entre une Person et une Organization
  * @ApiResource(
  *     collectionOperations={
- *         "get"={"security"="is_granted('ROLE_USERS_VIEW')"},
- *         "post"
+ *         "cget_students"={
+ *             "method"="GET",
+ *             "path"="/students",
+ *             "security"="is_granted('ROLE_USERS_VIEW')"
+ *          },
+ *          "cget_admin"={
+ *              "method"="GET",
+ *              "path"="/admin"
+ *          },
+ *          "get"
  *     },
  *     itemOperations={
  *         "get"={"security"="(is_granted('ROLE_USERS_VIEW') and object.getOrganization().getId() == user.getOrganization().getId()) or (object.getId() == user.getId())"},
@@ -63,11 +71,19 @@ class Access implements UserInterface
     private $roles = [];
 
     /**
-     * @ORM\OneToMany(targetEntity=PersonActivity::class, mappedBy="access")
+     * @var ArrayCollection<PersonActivity>
+     * @ORM\OneToMany(targetEntity=PersonActivity::class, mappedBy="access", orphanRemoval=true, cascade={"persist"})
      * @ApiSubresource()
      */
     private $personActivity;
 
+    /**
+     * @var ArrayCollection<OrganizationFunction>
+     * @ORM\OneToMany(targetEntity=OrganizationFunction::class, mappedBy="access", orphanRemoval=true, cascade={"persist"})
+     * @ApiSubresource()
+     */
+    private $organizationFunction;
+
     /**
      * @ORM\OneToMany(targetEntity=OrganizationLicence::class, mappedBy="licensee", orphanRemoval=true)
      */
@@ -76,6 +92,7 @@ class Access implements UserInterface
     public function __construct()
     {
         $this->personActivity = new ArrayCollection();
+        $this->organizationFunction = new ArrayCollection();
         $this->organizationLicences = new ArrayCollection();
     }
 
@@ -150,6 +167,36 @@ class Access implements UserInterface
         return $this;
     }
 
+    /**
+     * @return Collection|OrganizationFunction[]
+     */
+    public function getOrganizationFunction(): Collection
+    {
+        return $this->organizationFunction;
+    }
+
+    public function addOrganizationFunction (OrganizationFunction $organizationFunction): self
+    {
+        if (!$this->organizationFunction->contains($organizationFunction)) {
+            $this->organizationFunction[] = $organizationFunction;
+            $organizationFunction->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOrganizationFunction(OrganizationFunction $organizationFunction): self
+    {
+        if ($this->organizationFunction->removeElement($organizationFunction)) {
+            // set the owning side to null (unless already changed)
+            if ($organizationFunction->getAccess() === $this) {
+                $organizationFunction->setAccess(null);
+            }
+        }
+
+        return $this;
+    }
+
     /**
      * A visual identifier that represents this user.
      *
@@ -160,6 +207,15 @@ class Access implements UserInterface
         return $this->getPerson()->getUsername();
     }
 
+    /**
+     * @inheritDoc
+     */
+    public function setRoles(array $roles): self
+    {
+        $this->roles = $roles;
+        return $this;
+    }
+
     /**
      * @inheritDoc
      */

+ 17 - 0
src/Entity/Access/OrganizationFunction.php

@@ -22,6 +22,11 @@ class OrganizationFunction
      */
     private $id;
 
+    /**
+     * @ORM\ManyToOne(targetEntity=Access::class, inversedBy="personActivity")
+     */
+    private $access;
+
     /**
      * @ORM\Column(type="date")
      */
@@ -42,6 +47,18 @@ class OrganizationFunction
         return $this->id;
     }
 
+    public function getAccess(): ?Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
     public function getStartDate(): ?\DateTimeInterface
     {
         return $this->startDate;

+ 1 - 0
src/Entity/Core/ContactPoint.php

@@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraints as Assert;
  *     itemOperations={
  *           "get"={"security"="is_granted('CONTACT_POINT_READ', object)"},
  *           "put"={"security"="is_granted('CONTACT_POINT_EDIT', object)"},
+ *           "delete"={"security"="is_granted('CONTACT_POINT_DELETE', object)"},
  *     }
  * )
  * @ORM\Entity(repositoryClass=ContactPointRepository::class)

+ 2 - 1
src/Entity/Person/Person.php

@@ -3,6 +3,7 @@ declare(strict_types=1);
 
 namespace App\Entity\Person;
 
+use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Core\ContactPoint;
 use App\Repository\Person\PersonRepository;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -14,7 +15,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
  * Personne physique ou morale
  *
  * @ORM\Entity(repositoryClass=PersonRepository::class)
- *
+ * @ApiResource()
  */
 class Person implements UserInterface
 {

+ 1 - 1
src/Enum/Core/ContactPointTypeEnum.php

@@ -19,7 +19,7 @@ class ContactPointTypeEnum extends Enum
      * @param bool $type
      * @return array
      */
-    public static function toArrayCustom($type = false)
+    public static function toArray($type = false)
     {
         if($type == 'person'){
             return ['PRINCIPAL'=>self::PRINCIPAL,'OTHER'=>self::OTHER];

+ 1 - 1
src/Enum/Core/TimeZoneEnum.php

@@ -14,7 +14,7 @@ class TimeZoneEnum extends Enum
      * Return a custom array instead the original array
      * @return mixed
      */
-    public static function toArrayCustom()
+    public static function toArray()
     {
         return [
          'Indian/Reunion' => 'Indian/Reunion',

+ 47 - 0
src/Service/Access/AccessProfileCreator.php

@@ -0,0 +1,47 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Access;
+
+use App\ApiResources\Profile\AccessProfile;
+use App\Entity\Access\Access;
+use App\Service\Organization\OrganizationProfileCreator;
+use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
+
+/**
+ * Class AccessProfileCreator : Service contenant les manipulations associés à la ressource AccessProfile
+ * @package App\Service\ProfileCreator
+ */
+class AccessProfileCreator
+{
+    private RoleHierarchyInterface $roleHierarchy;
+    private OrganizationProfileCreator $organizationProfileCreator;
+
+    public function __construct(
+        RoleHierarchyInterface $roleHierarchy,
+        OrganizationProfileCreator $organizationProfileCreator
+    )
+    {
+        $this->roleHierarchy = $roleHierarchy;
+        $this->organizationProfileCreator = $organizationProfileCreator;
+    }
+
+    /**
+     * Créer une ressource AccessProfile à partir d'une entité Access
+     * @param Access $access
+     * @return AccessProfile
+     * @see AccessProfileCreatorTest::testGetAccessProfile()
+     */
+    public function getAccessProfile(Access $access): AccessProfile{
+        $accessProfile = new AccessProfile();
+        $accessProfile
+            ->setId($access->getId())
+            ->setIsAdminAccess($access->getAdminAccess())
+            ->setName($access->getPerson()->getName())
+            ->setGivenName($access->getPerson()->getGivenName())
+            ->setRoles($this->roleHierarchy->getReachableRoleNames($access->getRoles()))
+            ->setOrganization($this->organizationProfileCreator->getOrganizationProfile($access->getOrganization()));
+
+        return $accessProfile;
+    }
+}

+ 68 - 0
src/Service/Organization/OrganizationProfileCreator.php

@@ -0,0 +1,68 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Organization;
+
+use App\ApiResources\Profile\OrganizationProfile;
+use App\Entity\Organization\Organization;
+use App\Service\Network\Tree;
+use App\Service\Security\Module;
+use App\Test\Service\Organization\OrganizationProfileCreatorTest;
+
+/**
+ * Class OrganizationProfileCreator : Service contenant les manipulations associés à la ressource OrganizationProfile
+ * @package App\Service\ProfileCreator
+ */
+class OrganizationProfileCreator
+{
+    private Module $module;
+    private Tree $tree;
+
+    public function __construct(
+        Module $module,
+        Tree $tree
+    )
+    {
+        $this->module = $module;
+        $this->tree = $tree;
+    }
+
+    /**
+     * Classe permettant de créer le profile d'une organisation à partir d'une entité Organization
+     * @param Organization $organization
+     * @return OrganizationProfile
+     * @see OrganizationProfileCreatorTest::testGetOrganizationProfile()
+     */
+    public function getOrganizationProfile(Organization $organization): OrganizationProfile{
+        $organizationProfile = $this->setCommonElements($organization);
+        $organizationProfile->setModules($this->module->getOrganizationModules($organization));
+        $organizationProfile->setProduct($organization->getSettings()->getProduct());
+        $organizationProfile->setHasChildren($organization->getNetworkOrganizationChildren()->count() > 1);
+
+        foreach ($organization->getNetworkOrganizations() as $networkOrganization){
+            $organizationProfile->addNetwork($networkOrganization->getNetwork()->getName());
+        }
+
+        /** @var \App\Entity\Organization\Organization $parent */
+        foreach ($this->tree->findAllParentsAndSortByType($organization) as $parent){
+            $parentProfile = $this->setCommonElements($parent);
+            $organizationProfile->addParent($parentProfile);
+        }
+        return $organizationProfile;
+    }
+
+    /**
+     * Classe permettant de créer et Setter les éléments de base d'un profile d'organisation à partir d'une entité Organization
+     * @param Organization $organization
+     * @return OrganizationProfile
+     */
+    private function setCommonElements(Organization $organization): OrganizationProfile{
+        $organizationProfile = new OrganizationProfile();
+        $organizationProfile
+            ->setId($organization->getId())
+            ->setName($organization->getName())
+            ->setSubDomain($organization->getParameters()->getSubDomain())
+            ->setWebsite($organization->getParameters()->getWebsite());
+        return $organizationProfile;
+    }
+}

+ 3 - 1
src/Service/Security/Module.php

@@ -98,7 +98,9 @@ class Module
                 if($response) {
                     $modulesByConditions[] = $moduleName;
                 }
-            }catch (\Exception $exception){}
+            }catch (\Exception $exception){
+                throw new \LogicException($exception->getMessage(), 400, $exception);
+            }
         }
         return $modulesByConditions;
     }

+ 5 - 3
src/Service/Utils/Reflection.php

@@ -4,7 +4,6 @@ declare(strict_types=1);
 namespace App\Service\Utils;
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
 
 /**
  * Class Reflection : Gestion des réflection de class
@@ -25,11 +24,14 @@ class Reflection
      * @param string $method
      * @param array $parameters
      * @return mixed
-     * @throws \ReflectionException
      */
     public function dynamicInvokeServiceWithArgsAndMethod(string $serviceName, string $method, array $parameters = []) {
         $class = $this->container->get($serviceName);
-        return $this->dynamicInvokeClassWithArgsAndMethod(get_class($class),  $method,  $parameters = []);
+        //verif méthode exist
+        if(method_exists($class, $method))
+            return $class->{$method}(...$parameters);
+
+        throw new \LogicException("method_not_exist", 400);
     }
 
     /**

+ 1 - 1
src/Service/Utils/Siret.php

@@ -29,7 +29,7 @@ class Siret
      * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
      * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
      * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
-     * @see DatesTest::testIsIntervalIsValidNow()
+     * @see SiretTest::testIsSiretIsCorrect()
      */
     public function isSiretIsCorrect(string $siret): bool {
         $response = $this->clientSiret->request('GET', $siret);

+ 0 - 3
symfony.lock

@@ -119,9 +119,6 @@
     "jbouzekri/phumbor-bundle": {
         "version": "2.1.0"
     },
-    "laminas/laminas-zendframework-bridge": {
-        "version": "1.1.1"
-    },
     "lcobucci/clock": {
         "version": "2.0.0"
     },

+ 55 - 0
tests/Service/Access/AccessProfileCreatorTest.php

@@ -0,0 +1,55 @@
+<?php
+namespace App\Test\Service\Access;
+
+use App\ApiResources\Profile\AccessProfile;
+use App\ApiResources\Profile\OrganizationProfile;
+use App\Entity\Access\Access;
+use App\Entity\Organization\Organization;
+use App\Entity\Person\Person;
+use App\Service\Access\AccessProfileCreator;
+use App\Service\Organization\OrganizationProfileCreator;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Security\Core\Role\RoleHierarchy;
+
+class AccessProfileCreatorTest extends TestCase
+{
+    private Access  $access;
+    private Person $person;
+
+    public function setUp():void
+    {
+        $this->person = new Person();
+        $this->person
+            ->setName('Foo')
+            ->setGivenName('Bar')
+        ;
+
+        $this->access = new Access();
+        $this->access
+            ->setAdminAccess(true)
+            ->setPerson($this->person)
+            ->setOrganization(new Organization())
+        ;
+    }
+
+    /**
+     * @see AccessProfileCreator::getAccessProfile()
+     */
+    public function testGetAccessProfile(){
+        $roleHierarchyMock = $this->getMockBuilder(RoleHierarchy::class)->disableOriginalConstructor()->getMock();
+        $roleHierarchyMock
+            ->method('getReachableRoleNames')
+            ->willReturn(["ROLE_A", "ROLE_B"]);
+
+        $organizationProfileCreator = $this->getMockBuilder(OrganizationProfileCreator::class)->disableOriginalConstructor()->getMock();
+        $organizationProfileCreator
+            ->method('getOrganizationProfile')
+            ->with($this->access->getOrganization())
+            ->willReturn(new OrganizationProfile());
+
+        $accessProfileCreator = new AccessProfileCreator($roleHierarchyMock,$organizationProfileCreator);
+        $accessProfile = $accessProfileCreator->getAccessProfile($this->access);
+
+        $this->assertInstanceOf(AccessProfile::class, $accessProfile);
+    }
+}

+ 50 - 0
tests/Service/Organization/OrganizationProfileCreatorTest.php

@@ -0,0 +1,50 @@
+<?php
+namespace App\Test\Service\Organization;
+
+use App\ApiResources\Profile\OrganizationProfile;
+use App\Entity\Organization\Organization;
+use App\Entity\Organization\Parameters;
+use App\Entity\Organization\Settings;
+use App\Service\Network\Tree;
+use App\Service\Organization\OrganizationProfileCreator;
+use App\Service\Security\Module;
+use PHPUnit\Framework\TestCase;
+
+class OrganizationProfileCreatorTest extends TestCase
+{
+    private Organization  $organization;
+
+    public function setUp():void
+    {
+        $this->organization = new Organization();
+        $this->organization
+            ->setParameters(new Parameters())
+            ->setSettings(new Settings())
+            ->setName('Foo')
+        ;
+    }
+
+    /**
+     * @see OrganizationProfileCreator::getOrganizationProfile()
+     */
+    public function testGetOrganizationProfile(){
+        $moduleMock = $this->getMockBuilder(Module::class)->disableOriginalConstructor()->getMock();
+        $moduleMock
+            ->method('getOrganizationModules')
+            ->with($this->organization)
+            ->willReturn(["MODULE_A", "MODULE_B"]);
+
+        $treeMock = $this->getMockBuilder(Tree::class)->disableOriginalConstructor()->getMock();
+        $parent = new Organization();
+        $parent->setParameters(new Parameters());
+        $treeMock
+            ->method('findAllParentsAndSortByType')
+            ->with($this->organization)
+            ->willReturn([$parent, $parent]);
+
+        $organizationProfileCreator = new OrganizationProfileCreator($moduleMock,$treeMock);
+        $organizationProfile = $organizationProfileCreator->getOrganizationProfile($this->organization);
+
+        $this->assertInstanceOf(OrganizationProfile::class, $organizationProfile);
+    }
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff