ソースを参照

PhpStan Level 6

Vincent 2 年 前
コミット
ec4358cc75
88 ファイル変更736 行追加271 行削除
  1. 0 1
      phpstan.neon.dist
  2. 2 2
      public/index.php
  3. 8 0
      src/ApiResources/Enum/Enum.php
  4. 1 1
      src/ApiResources/Export/ExportRequestInterface.php
  5. 1 0
      src/ApiResources/Export/LicenceCmf/LicenceCmfOrganizationER.php
  6. 16 0
      src/ApiResources/Profile/AccessProfile.php
  7. 17 0
      src/ApiResources/Profile/OrganizationProfile.php
  8. 19 0
      src/Doctrine/AbstractExtension.php
  9. 17 0
      src/Doctrine/Access/CurrentAccessExtension.php
  10. 25 0
      src/Entity/Access/Access.php
  11. 16 0
      src/Entity/Access/PersonalizedList.php
  12. 1 0
      src/Entity/Billing/BillAccounting.php
  13. 45 11
      src/Entity/Organization/Settings.php
  14. 10 0
      src/Entity/Person/Person.php
  15. 12 8
      src/Entity/Public/FederationStructure.php
  16. 3 2
      src/Entity/Public/PublicEvent.php
  17. 5 4
      src/Enum/Access/FunctionEnum.php
  18. 1 1
      src/EventSubscriber/ApiResourcesValidatorSubscriber.php
  19. 1 0
      src/EventSubscriber/ElasticaPostTransformSubscriber.php
  20. 18 15
      src/Filter/DoctrineFilter/AbstractTimeFilter.php
  21. 5 3
      src/Filter/DoctrineFilter/ActivityYearFilter.php
  22. 11 1
      src/Filter/Person/FullNameFilter.php
  23. 11 1
      src/Filter/Utils/DistanceFilter.php
  24. 11 1
      src/Filter/Utils/FindInSetFilter.php
  25. 11 1
      src/Filter/Utils/InFilter.php
  26. 4 0
      src/OpenApi/OpenApiFactory.php
  27. 4 4
      src/Repository/Access/AccessRepository.php
  28. 5 4
      src/Repository/Booking/CourseRepository.php
  29. 2 2
      src/Repository/Core/ContactPointRepository.php
  30. 1 1
      src/Repository/Network/NetworkOrganizationRepository.php
  31. 1 1
      src/Repository/Organization/OrganizationAddressPostalRepository.php
  32. 7 1
      src/Serializer/AccessContextBuilder.php
  33. 32 1
      src/Serializer/DefaultNormalizer.php
  34. 3 3
      src/Service/Access/Utils.php
  35. 15 15
      src/Service/Constraint/AbstractTimeConstraintUtils.php
  36. 5 5
      src/Service/Constraint/ActivityYearConstraint.php
  37. 13 13
      src/Service/Constraint/DateTimeConstraint.php
  38. 1 1
      src/Service/Elasticsearch/EducationNotationUpdater.php
  39. 2 2
      src/Service/Export/BaseExporter.php
  40. 9 0
      src/Service/Export/ExporterInterface.php
  41. 7 3
      src/Service/Export/LicenceCmfExporter.php
  42. 2 2
      src/Service/Mailer/Builder/AbstractBuilder.php
  43. 5 0
      src/Service/Mailer/Builder/AbstractBuilderInterface.php
  44. 7 7
      src/Service/Mailer/Mailer.php
  45. 3 2
      src/Service/MercureHub.php
  46. 1 1
      src/Service/Mobyt/MobytService.php
  47. 3 3
      src/Service/Network/Tree.php
  48. 3 2
      src/Service/Notifier.php
  49. 27 10
      src/Service/Security/Module.php
  50. 7 3
      src/Service/ServiceIterator/CronjobIterator.php
  51. 4 1
      src/Service/ServiceIterator/CurrentAccessExtensionIterator.php
  52. 6 6
      src/Service/ServiceIterator/EncoderIterator.php
  53. 6 4
      src/Service/ServiceIterator/ExporterIterator.php
  54. 6 4
      src/Service/ServiceIterator/Mailer/BuilderIterator.php
  55. 10 2
      src/Service/ServiceIterator/OptionalsRolesIterator.php
  56. 1 1
      src/Service/Twig/AssetsExtension.php
  57. 1 1
      src/Service/Typo3/BindFileService.php
  58. 2 3
      src/Service/Typo3/Typo3Service.php
  59. 4 4
      src/Service/Utils/ArrayUtils.php
  60. 10 7
      src/Service/Utils/DatesUtils.php
  61. 10 5
      src/Service/Utils/EntityUtils.php
  62. 2 1
      src/Service/Utils/Environnement.php
  63. 33 25
      src/Service/Utils/GpsCoordinateUtils.php
  64. 2 2
      src/Service/Utils/Parser.php
  65. 6 4
      src/Service/Utils/Path.php
  66. 4 4
      src/Service/Utils/Reflection.php
  67. 4 4
      src/Service/Utils/UrlBuilder.php
  68. 3 0
      src/Service/Utils/Uuid.php
  69. 12 4
      src/State/Processor/Access/AdminAccessProcessor.php
  70. 7 5
      src/State/Processor/EntityProcessor.php
  71. 7 5
      src/State/Processor/Export/LicenceCmf/ExportRequestProcessor.php
  72. 11 2
      src/State/Provider/Access/AccessProfileProvider.php
  73. 11 2
      src/State/Provider/Access/AdminAccessProvider.php
  74. 19 4
      src/State/Provider/Core/DownloadRequestProvider.php
  75. 9 2
      src/State/Provider/Cotisation/CotisationProvider.php
  76. 9 2
      src/State/Provider/Dolibarr/DolibarrAccountProvider.php
  77. 13 4
      src/State/Provider/Enum/EnumProvider.php
  78. 12 3
      src/State/Provider/Mobyt/MobytUserStatusProvider.php
  79. 33 3
      src/State/Provider/Utils/GpsCoordinateSearchingProvider.php
  80. 17 2
      src/State/Provider/Utils/SiretProvider.php
  81. 2 1
      src/Validator/Core/ContactPoint.php
  82. 7 4
      src/Validator/Core/ContactPointValidator.php
  83. 2 1
      src/Validator/Organization/OrganizationAddressPostal.php
  84. 3 2
      src/Validator/Organization/OrganizationAddressPostalValidator.php
  85. 5 3
      src/Validator/Organization/Parameters/MobytCredentialsValidator.php
  86. 2 1
      tests/Service/Export/LicenceCmfExporterTest.php
  87. 2 2
      tests/Service/Network/UtilsTest.php
  88. 3 3
      tests/Service/ServiceIterator/CurrentAccessExtensionIteratorTest.php

+ 0 - 1
phpstan.neon.dist

@@ -8,6 +8,5 @@ parameters:
 # on ignore les erreurs qui imposent d'indiquer le type d'un iterable dans la phpDoc (cf: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type)
 	ignoreErrors :
 	    - '#Attribute class JetBrains\\PhpStorm\\[a-zA-Z]+ does not exist.#'
-	    - '#no value type specified in iterable type [a-zA-Z]+.#'
 	paths:
 		- src

+ 2 - 2
public/index.php

@@ -24,7 +24,7 @@ if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
 }
 
 // If the header is set
-//if (isset($_SERVER['HTTP_BLACKFIRETRIGGER'])) {
+if (isset($_SERVER['HTTP_BLACKFIRETRIGGER'])) {
     $config = new \Blackfire\ClientConfiguration();
     $config->setClientId($_ENV['BLACKFIRE_CLIENT_ID']);
     $config->setClientToken($_ENV['BLACKFIRE_CLIENT_TOKEN']);
@@ -33,7 +33,7 @@ if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
     $blackfire = new \Blackfire\Client($config);
     // then start the probe
     $probe = $blackfire->createProbe();
-//}
+}
 
 $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
 $request = Request::createFromGlobals();

+ 8 - 0
src/ApiResources/Enum/Enum.php

@@ -25,6 +25,7 @@ class Enum implements ApiResourcesInterface
     #[ApiProperty(identifier: true)]
     private string $name;
 
+    /** @var list<string> $items */
     private array $items = [];
 
     public function __construct()
@@ -42,12 +43,19 @@ class Enum implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @param list<string> $items
+     * @return $this
+     */
     public function setItems(array $items): self
     {
         $this->items = $items;
         return $this;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getItems(): array
     {
         return $this->items;

+ 1 - 1
src/ApiResources/Export/ExportRequestInterface.php

@@ -2,7 +2,7 @@
 
 namespace App\ApiResources\Export;
 
-class ExportRequestInterface
+interface ExportRequestInterface
 {
 
 }

+ 1 - 0
src/ApiResources/Export/LicenceCmf/LicenceCmfOrganizationER.php

@@ -10,6 +10,7 @@ use ApiPlatform\Metadata\Put;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\ApiResource;
 use App\ApiResources\Export\ExportRequest;
+use App\ApiResources\Export\ExportRequestInterface;
 use App\State\Processor\Export\LicenceCmf\ExportRequestProcessor;
 use Symfony\Component\Validator\Constraints as Assert;
 

+ 16 - 0
src/ApiResources/Profile/AccessProfile.php

@@ -53,12 +53,14 @@ class AccessProfile implements ApiResourcesInterface
     #[Groups('access_profile_read')]
     private ?int $avatarId = null;
 
+    /** @var list<string> $roles */
     #[Groups('access_profile_read')]
     private ?array $roles = [];
 
     #[Groups('access_profile_read')]
     private ?int $activityYear = null;
 
+    /** @var bool[] $historical */
     #[Groups('access_profile_read')]
     private ?array $historical = [];
 
@@ -175,12 +177,19 @@ class AccessProfile implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getRoles(): array
     {
         $roles = $this->roles;
         return array_unique($roles);
     }
 
+    /**
+     * @param list<string> $roles
+     * @return $this
+     */
     public function setRoles(array $roles): self
     {
         $this->roles = $roles;
@@ -269,11 +278,18 @@ class AccessProfile implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @return bool[]
+     */
     public function getHistorical(): array
     {
         return $this->historical;
     }
 
+    /**
+     * @param bool[] $historical
+     * @return $this
+     */
     public function setHistorical(array $historical): self
     {
         $this->historical = $historical;

+ 17 - 0
src/ApiResources/Profile/OrganizationProfile.php

@@ -7,6 +7,7 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
 use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
+use App\Entity\Organization\Organization;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
@@ -32,18 +33,21 @@ class OrganizationProfile implements ApiResourcesInterface
     #[Groups('access_profile_read')]
     private ?string $legalStatus = null;
 
+    /** @var list<string> $networks  */
     #[Groups('access_profile_read')]
     private array $networks = [];
 
     #[Groups('access_profile_read')]
     private ?string $website = null;
 
+    /** @var list<string>|null $modules  */
     #[Groups('access_profile_read')]
     private ?array $modules = [];
 
     #[Groups('access_profile_read')]
     private bool $hasChildren = false;
 
+    /** @var list<Organization>|null  */
     #[Groups('access_profile_read')]
     private ?array $parents = [];
 
@@ -100,6 +104,9 @@ class OrganizationProfile implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getNetworks(): array
     {
         return $this->networks;
@@ -122,12 +129,19 @@ class OrganizationProfile implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getModules(): array
     {
         $modules = $this->modules;
         return array_unique($modules);
     }
 
+    /**
+     * @param list<string> $modules
+     * @return $this
+     */
     public function setModules(array $modules): self
     {
         $this->modules = $modules;
@@ -145,6 +159,9 @@ class OrganizationProfile implements ApiResourcesInterface
         return $this;
     }
 
+    /**
+     * @return list<Organization>
+     */
     public function getParents(): array
     {
         return $this->parents;

+ 19 - 0
src/Doctrine/AbstractExtension.php

@@ -15,11 +15,30 @@ use Exception;
  */
 abstract class AbstractExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
 {
+    /**
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     * @throws Exception
+     */
     public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
     {
         $this->addWhere($queryBuilder, $resourceClass);
     }
 
+    /**
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param list<int> $identifiers
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     * @throws Exception
+     */
     public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void
     {
         $this->addWhere($queryBuilder, $resourceClass);

+ 17 - 0
src/Doctrine/Access/CurrentAccessExtension.php

@@ -24,11 +24,28 @@ final class CurrentAccessExtension  implements QueryCollectionExtensionInterface
     )
     { }
 
+    /**
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
     {
         $this->addWhere($queryBuilder, $resourceClass, $operation?->getName());
     }
 
+    /**
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param list<int> $identifiers
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void
     {
         $this->addWhere($queryBuilder, $resourceClass, $operation?->getName());

+ 25 - 0
src/Entity/Access/Access.php

@@ -56,6 +56,7 @@ use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Security\Core\Role\Role;
 use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
 use Symfony\Component\Security\Core\User\UserInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
@@ -98,9 +99,11 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\JoinColumn(nullable: false)]
     private Organization $organization;
 
+    /** @var mixed[]|null  */
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $roles = [];
 
+    /** @var mixed[]|null  */
     #[Groups(['my_access:input'])]
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $setting = [];
@@ -403,11 +406,19 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         return $this;
     }
 
+    /**
+     * @return array<bool|string>
+     */
     public function getHistorical(): array
     {
         return array_key_exists('historical', $this->setting) && $this->setting['historical'] ? $this->setting['historical'] : ['present' => true];
     }
 
+
+    /**
+     * @param bool[] $historical
+     * @return $this
+     */
     #[Groups(['my_access:input'])]
     public function setHistorical(array $historical): self
     {
@@ -418,12 +429,19 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         return $this;
     }
 
+    /**
+     * @param mixed[]|null $roles
+     * @return $this
+     */
     public function setRoles(?array $roles): self
     {
         $this->roles = $roles;
         return $this;
     }
 
+    /**
+     * @return mixed[]
+     */
     public function getRoles(): array
     {
         $roles = $this->roles;
@@ -747,11 +765,18 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         // TODO: Implement eraseCredentials() method.
     }
 
+    /**
+     * @return mixed[]|null
+     */
     public function getSetting(): ?array
     {
         return $this->setting;
     }
 
+    /**
+     * @param mixed[]|null $setting
+     * @return $this
+     */
     public function setSetting(?array $setting): self
     {
         $this->setting = $setting;

+ 16 - 0
src/Entity/Access/PersonalizedList.php

@@ -43,6 +43,7 @@ class PersonalizedList
     #[Groups(['lists:output'])]
     private ?string $label = null;
 
+    /** @var mixed[]|null  */
     #[ORM\Column(length: 4294967295, nullable: true)]
     private ?array $filters = null;
 
@@ -50,6 +51,7 @@ class PersonalizedList
     #[Groups(['lists:output'])]
     private string $entity;
 
+    /** @var mixed[]  */
     #[ORM\Column(length: 4294967295, nullable: true)]
     private array $columns;
 
@@ -67,23 +69,37 @@ class PersonalizedList
         return $this->id;
     }
 
+    /**
+     * @param mixed[] $filters
+     * @return $this
+     */
     public function setFilters(array $filters): self
     {
         $this->filters = $filters;
         return $this;
     }
 
+    /**
+     * @return mixed[]|null
+     */
     public function getFilters(): ?array
     {
         return $this->filters;
     }
 
+    /**
+     * @param mixed[] $columns
+     * @return $this
+     */
     public function setColumns(array $columns): self
     {
         $this->columns = $columns;
         return $this;
     }
 
+    /**
+     * @return mixed[]|null
+     */
     public function getColumns(): ?array
     {
         return $this->columns;

+ 1 - 0
src/Entity/Billing/BillAccounting.php

@@ -209,6 +209,7 @@ class BillAccounting
     {
         if (!$this->billingIntangibleExcludeDates->contains($billingIntangibleExcludeDate)) {
             $this->billingIntangibleExcludeDates[] = $billingIntangibleExcludeDate;
+            /** @phpstan-ignore-next-line */
             $billingIntangibleExcludeDate->setBill($this);
         }
         return $this;

+ 45 - 11
src/Entity/Organization/Settings.php

@@ -13,9 +13,11 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
 use ApiPlatform\Metadata\ApiFilter;
 use App\Repository\Organization\SettingsRepository;
+
 //use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
+
 /**
  * Caractéristiques d'une Organization (produits, options...etc)
  */
@@ -28,63 +30,95 @@ class Settings
     #[ORM\Column]
     #[ORM\GeneratedValue]
     private ?int $id = null;
+
     #[ORM\OneToOne(inversedBy: 'settings', cascade: ['persist', 'remove'])]
     #[ORM\JoinColumn(nullable: false)]
     private ?Organization $organization = null;
+
     #[ORM\Column(length: 255)]
     #[Assert\Choice(callback: ['\\App\\Enum\\Organization\\SettingsProductEnum', 'toArray'], message: 'invalid-product')]
     private string $product;
+
+    /** @var mixed[]|null  */
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $modules = [];
+
+    /** @var mixed[]|null  */
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $actions = [];
+
     #[ORM\Column(length: 255, options: ['default' => 'FRANCE'])]
     private string $country;
-    public function getId() : ?int
+
+    public function getId(): ?int
     {
         return $this->id;
     }
-    public function getOrganization() : ?Organization
+
+    public function getOrganization(): ?Organization
     {
         return $this->organization;
     }
-    public function setOrganization(Organization $organization) : self
+
+    public function setOrganization(Organization $organization): self
     {
         $this->organization = $organization;
         return $this;
     }
-    public function getProduct() : string
+
+    public function getProduct(): string
     {
         return $this->product;
     }
-    public function setProduct(string $product) : self
+
+    public function setProduct(string $product): self
     {
         $this->product = $product;
         return $this;
     }
-    public function getModules() : ?array
+
+    /**
+     * @return mixed[]|null
+     */
+    public function getModules(): ?array
     {
         return $this->modules;
     }
-    public function setModules(?array $modules) : self
+
+    /**
+     * @param mixed[]|null $modules
+     * @return $this
+     */
+    public function setModules(?array $modules): self
     {
         $this->modules = $modules;
         return $this;
     }
-    public function getActions() : ?array
+
+    /**
+     * @return mixed[]|null
+     */
+    public function getActions(): ?array
     {
         return $this->actions;
     }
-    public function setActions(?array $actions) : self
+
+    /**
+     * @param mixed[]|null $actions
+     * @return $this
+     */
+    public function setActions(?array $actions): self
     {
         $this->actions = $actions;
         return $this;
     }
-    public function getCountry() : string
+
+    public function getCountry(): string
     {
         return $this->country;
     }
-    public function setCountry(string $country) : self
+
+    public function setCountry(string $country): self
     {
         $this->country = $country;
         return $this;

+ 10 - 0
src/Entity/Person/Person.php

@@ -45,7 +45,9 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(length: 180, unique: true, nullable: true)]
     private ?string $username = null;
 
+    /** @var string[]  */
     private array $roles = [];
+
     #[ORM\Column(nullable: true)]
     private ?string $password = null;
 
@@ -68,6 +70,7 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\OneToMany(mappedBy: 'person', targetEntity: PersonAddressPostal::class, orphanRemoval: true)]
     #[Groups("access_address")]
     private Collection $personAddressPostal;
+
     #[ORM\Column(nullable: true)]
     #[Assert\Choice(callback: ['\\App\\Enum\\Person\\GenderEnum', 'toArray'], message: 'invalid-gender')]
     private ?string $gender = null;
@@ -144,6 +147,9 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
         return $this;
     }
 
+    /**
+     * @return string[]
+     */
     public function getRoles(): array
     {
         $roles = $this->roles;
@@ -152,6 +158,10 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
         return array_unique($roles);
     }
 
+    /**
+     * @param string[] $roles
+     * @return $this
+     */
     public function setRoles(array $roles): self
     {
         $this->roles = $roles;

+ 12 - 8
src/Entity/Public/FederationStructure.php

@@ -69,6 +69,7 @@ class FederationStructure
     #[Groups(["federation_structure_item_get", "federation_structure_collection_get"])]
     private ?string $website;
 
+    /** @var mixed[] */
     #[ORM\Column(type: 'json')]
     #[Groups(["federation_structure_item_get", "federation_structure_collection_get"])]
     private array $addresses;
@@ -101,10 +102,12 @@ class FederationStructure
     #[Groups(["federation_structure_item_get"])]
     private ?string $youtube;
 
+    /** @var mixed[]|null  */
     #[ORM\Column(type: 'json')]
     #[Groups(["federation_structure_item_get"])]
     private ?array $articles;
 
+    /** @var list<string>|null  */
     #[ORM\Column(type: 'simple_array')]
     #[Groups(["federation_structure_item_get", "federation_structure_collection_get"])]
     private ?array $practices;
@@ -117,6 +120,7 @@ class FederationStructure
     #[Groups(["federation_structure_item_get", "federation_structure_collection_get"])]
     private ?string $parentName;
 
+    /** @var list<string>  */
     #[ORM\Column(type: 'simple_array')]
     #[Groups(["federation_structure_item_get", "federation_structure_collection_get"])]
     private array $parents;
@@ -248,7 +252,7 @@ class FederationStructure
     }
 
     /**
-     * @return array
+     * @return mixed[]
      */
     public function getAddresses(): array
     {
@@ -256,7 +260,7 @@ class FederationStructure
     }
 
     /**
-     * @param array $addresses
+     * @param mixed[] $addresses
      * @return FederationStructure
      */
     public function setAddresses(array $addresses): FederationStructure
@@ -388,7 +392,7 @@ class FederationStructure
     }
 
     /**
-     * @return array|null
+     * @return mixed[]|null
      */
     public function getArticles(): ?array
     {
@@ -396,7 +400,7 @@ class FederationStructure
     }
 
     /**
-     * @param array|null $articles
+     * @param mixed[]|null $articles
      * @return FederationStructure
      */
     public function setArticles(?array $articles): FederationStructure
@@ -406,7 +410,7 @@ class FederationStructure
     }
 
     /**
-     * @return array|null
+     * @return list<string>|null
      */
     public function getPractices(): ?array
     {
@@ -414,7 +418,7 @@ class FederationStructure
     }
 
     /**
-     * @param array|null $practices
+     * @param list<string>|null $practices
      * @return FederationStructure
      */
     public function setPractices(?array $practices): FederationStructure
@@ -460,7 +464,7 @@ class FederationStructure
     }
 
     /**
-     * @return array
+     * @return list<string>
      */
     public function getParents(): array
     {
@@ -468,7 +472,7 @@ class FederationStructure
     }
 
     /**
-     * @param array $parents
+     * @param list<string> $parents
      * @return FederationStructure
      */
     public function setParents(array $parents): FederationStructure

+ 3 - 2
src/Entity/Public/PublicEvent.php

@@ -97,6 +97,7 @@ class PublicEvent
     #[ORM\Column]
     private ?string $thumbnailUrl;
 
+    /** @var list<string>|null  */
     #[ORM\Column(type: 'simple_array')]
     private ?array $categories;
 
@@ -448,7 +449,7 @@ class PublicEvent
     }
 
     /**
-     * @return array|null
+     * @return list<string>|null
      */
     public function getCategories(): ?array
     {
@@ -456,7 +457,7 @@ class PublicEvent
     }
 
     /**
-     * @param array|null $categories
+     * @param list<string>|null $categories
      * @return PublicEvent
      */
     public function setCategories(?array $categories): PublicEvent

+ 5 - 4
src/Enum/Access/FunctionEnum.php

@@ -68,7 +68,10 @@ class FunctionEnum extends Enum
 
     private const OTHER = 'OTHER';
 
-    public static function getOrganizationStaffAndBoardOfDirectorsMission(): array{
+    /**
+     * @return list<string>
+     */
+    public static function getOrganizationStaffAndBoardOfDirectorsMission(): array {
         return [
             self::ACTIVE_MEMBER_OF_THE_CA,
             self::HONORARY_PRESIDENT,
@@ -110,9 +113,7 @@ class FunctionEnum extends Enum
     }
 
     /**
-     * Office missions
-     *
-     * Used by the DolibarrSyncService
+     * @return list<string>
      */
     public static function getOfficeMissions(): array
     {

+ 1 - 1
src/EventSubscriber/ApiResourcesValidatorSubscriber.php

@@ -22,7 +22,7 @@ final class ApiResourcesValidatorSubscriber implements EventSubscriberInterface
 
     /**
      * ne se déclenche qu'après le post validate d'api platform
-     * @return array[]
+     * @return array<string, array<int, int|string>>
      */
     public static function getSubscribedEvents(): array
     {

+ 1 - 0
src/EventSubscriber/ElasticaPostTransformSubscriber.php

@@ -24,6 +24,7 @@ final class ElasticaPostTransformSubscriber implements EventSubscriberInterface
 
     /**
      * ne se déclenche qu'après le post validate d'api platform
+     * @return string[]
      */
     public static function getSubscribedEvents(): array
     {

+ 18 - 15
src/Filter/DoctrineFilter/AbstractTimeFilter.php

@@ -15,9 +15,9 @@ abstract class AbstractTimeFilter extends SQLFilter
 {
     /**
      * Fonction permettant de construire la requête SQL correspondante aux contraintes
-     * @param array $constraints
+     * @param array<string, array<string, int[]>> $constraints
      * @param string $targetTableAlias
-     * @param array $fields
+     * @param array<string, mixed> $fields
      * @return string
      */
     protected function constructQuery(array $constraints, string $targetTableAlias, array $fields): string
@@ -28,14 +28,17 @@ abstract class AbstractTimeFilter extends SQLFilter
             foreach ($constraint as $date => $conditions){
                 foreach ($conditions as $condition){
                     $arithmetic = $this->getArithmeticValue($condition);
-                    if(!is_null($arithmetic))
+                    if(!is_null($arithmetic)) {
                         $queryConditionsOR[] = sprintf("%s.%s %s '%s'", $targetTableAlias, $fields[$key], $arithmetic, $date);
-                    else
+                    }
+                    else {
                         $queryConditionsOR[] = sprintf("%s.%s IS NULL", $targetTableAlias, $fields[$key]);
+                    }
                 }
             }
-            if(!empty($queryConditionsOR))
+            if(!empty($queryConditionsOR)) {
                 $queryConditionsAND[] = sprintf("(%s)", join(' OR ', $queryConditionsOR));
+            }
         }
 
         return implode(" AND ", $queryConditionsAND);
@@ -43,19 +46,19 @@ abstract class AbstractTimeFilter extends SQLFilter
 
     /**
      * Fonction retournant la valeur arithmétique correspondant à la condition de la contrainte
-     * @param DateTimeConstraint $condition
+     * @param int $condition
      * @return string|null
      * @see DateTimeFilterTest::testGetArithmeticValue()
      */
-    protected function getArithmeticValue(DateTimeConstraint $condition): ?string
+    protected function getArithmeticValue(int $condition): ?string
     {
-        switch ($condition){
-            case DateTimeConstraint::INF : return '<';
-            case DateTimeConstraint::EQUAL :  return '=';
-            case DateTimeConstraint::SUP :  return '>';
-            case DateTimeConstraint::INF + DateTimeConstraint::EQUAL : return '<=';
-            case DateTimeConstraint::SUP + DateTimeConstraint::EQUAL  : return '>=';
-        }
-        return null;
+        return match ($condition) {
+            DateTimeConstraint::INF => '<',
+            DateTimeConstraint::EQUAL => '=',
+            DateTimeConstraint::SUP => '>',
+            DateTimeConstraint::INF + DateTimeConstraint::EQUAL => '<=',
+            DateTimeConstraint::SUP + DateTimeConstraint::EQUAL => '>=',
+            default => null,
+        };
     }
 }

+ 5 - 3
src/Filter/DoctrineFilter/ActivityYearFilter.php

@@ -7,6 +7,7 @@ use App\Attribute\ActivityYearConstraintAware;
 use App\Service\Constraint\ActivityYearConstraint;
 use App\Service\Utils\StringsUtils;
 use Doctrine\ORM\Mapping\ClassMetadata;
+use Exception;
 
 /**
  * Classe DateTimeFilter qui définie la requête SQL devant être ajoutée aux Entités possédant l'annotation DateTimeConstraintAware
@@ -20,15 +21,16 @@ final class ActivityYearFilter extends AbstractTimeFilter
      * @param ClassMetadata $targetEntity
      * @param string $targetTableAlias
      * @return string
-     * @throws \Exception
+     * @throws Exception
      */
     public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
     {
         if(!$this->hasParameter('_time_constraint')
-            || !boolval(StringsUtils::unquote($this->getParameter('_time_constraint')))
+            || !(bool) StringsUtils::unquote($this->getParameter('_time_constraint'))
             || !$this->hasParameter('accessId')
-        )
+        ) {
             return '';
+        }
 
         $yearConstraintAware = $targetEntity->getReflectionClass()->getAttributes(ActivityYearConstraintAware::class)[0] ?? null;
         $startFieldName = $yearConstraintAware?->getArguments()['startYearFieldName'] ?? null;

+ 11 - 1
src/Filter/Person/FullNameFilter.php

@@ -9,6 +9,16 @@ use ApiPlatform\Metadata\Operation;
 use Doctrine\ORM\QueryBuilder;
 
 class FullNameFilter extends AbstractFilter {
+    /**
+     * @param string $property
+     * @param mixed $value
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     protected function filterProperty(string $property,
                                       mixed $value,
                                       QueryBuilder $queryBuilder,
@@ -30,7 +40,7 @@ class FullNameFilter extends AbstractFilter {
     /**
      * API docs
      * @param string $resourceClass
-     * @return array[]
+     * @return array<string, mixed[]>
      */
     public function getDescription(string $resourceClass): array
     {

+ 11 - 1
src/Filter/Utils/DistanceFilter.php

@@ -27,7 +27,7 @@ final class DistanceFilter extends AbstractFilter
     /**
      * API docs
      * @param string $resourceClass
-     * @return array[]
+     * @return array<string, mixed[]>
      */
     #[ArrayShape(['search' => "array"])]
     public function getDescription(string $resourceClass): array
@@ -52,6 +52,16 @@ final class DistanceFilter extends AbstractFilter
         ];
     }
 
+    /**
+     * @param string $property
+     * @param mixed $value
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     protected function filterProperty(string $property,
                                       mixed $value,
                                       QueryBuilder $queryBuilder,

+ 11 - 1
src/Filter/Utils/FindInSetFilter.php

@@ -10,6 +10,16 @@ use Doctrine\ORM\QueryBuilder;
 use Symfony\Component\PropertyInfo\Type;
 
 final class FindInSetFilter extends AbstractFilter {
+    /**
+     * @param string $property
+     * @param mixed $value
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     protected function filterProperty(string $property,
                                       mixed $value,
                                       QueryBuilder $queryBuilder,
@@ -34,7 +44,7 @@ final class FindInSetFilter extends AbstractFilter {
     /**
      * API docs
      * @param string $resourceClass
-     * @return array[]
+     * @return array<string, mixed[]>
      */
     public function getDescription(string $resourceClass): array
     {

+ 11 - 1
src/Filter/Utils/InFilter.php

@@ -13,6 +13,16 @@ use Symfony\Component\PropertyInfo\Type;
  * Is property included in the given CSV array
  */
 final class InFilter extends AbstractFilter {
+    /**
+     * @param string $property
+     * @param mixed $value
+     * @param QueryBuilder $queryBuilder
+     * @param QueryNameGeneratorInterface $queryNameGenerator
+     * @param string $resourceClass
+     * @param Operation|null $operation
+     * @param mixed[] $context
+     * @return void
+     */
     protected function filterProperty(string $property,
                                       mixed $value,
                                       QueryBuilder $queryBuilder,
@@ -39,7 +49,7 @@ final class InFilter extends AbstractFilter {
     /**
      * API docs
      * @param string $resourceClass
-     * @return array[]
+     * @return array<string, mixed[]>
      */
     public function getDescription(string $resourceClass): array
     {

+ 4 - 0
src/OpenApi/OpenApiFactory.php

@@ -25,6 +25,10 @@ final class OpenApiFactory implements OpenApiFactoryInterface
         $this->decorated = $decorated;
     }
 
+    /**
+     * @param mixed[] $context
+     * @return OpenApi
+     */
     public function __invoke(array $context = []): OpenApi
     {
         $openApi = $this->decorated->__invoke($context);

+ 4 - 4
src/Repository/Access/AccessRepository.php

@@ -121,11 +121,11 @@ class AccessRepository extends ServiceEntityRepository implements UserLoaderInte
      * Retourne tous les accesses de l'organization ayant la fonction donnée à la date donnée
      *
      * @param Organization $organization
-     * @param FunctionEnum $function
+     * @param string $function
      * @param DateTime|null $date
-     * @return array
+     * @return list<Access>
      */
-    public function findByOrganizationAndMission(Organization $organization, FunctionEnum $function, \DateTime $date = null): array
+    public function findByOrganizationAndMission(Organization $organization, string $function, \DateTime $date = null): array
     {
         if ($date === null)
             $date = new DateTime();
@@ -153,7 +153,7 @@ class AccessRepository extends ServiceEntityRepository implements UserLoaderInte
      *
      * Used by App\Service\Dolibarr\DolibarrSync\DolibarrSyncService
      *
-     * @return array
+     * @return list<Access>
      */
     public function getAllActiveMembersAndMissions(): array
     {

+ 5 - 4
src/Repository/Booking/CourseRepository.php

@@ -5,6 +5,7 @@ namespace App\Repository\Booking;
 
 use App\Entity\Booking\Course;
 use App\Entity\Organization\Organization;
+use DateTimeInterface;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 use Doctrine\Persistence\ManagerRegistry;
 
@@ -18,11 +19,11 @@ class CourseRepository extends ServiceEntityRepository
     /**
      * Récupère les cours d'une organisation d'une date à une autre
      * @param Organization $organization
-     * @param \DateTimeInterface $start
-     * @param \DateTimeInterface $end
-     * @return array
+     * @param DateTimeInterface $start
+     * @param DateTimeInterface $end
+     * @return list<Course>
      */
-    public function getCoursesToFrom(Organization $organization, \DateTimeInterface $start, \DateTimeInterface $end): array
+    public function getCoursesToFrom(Organization $organization, DateTimeInterface $start, DateTimeInterface $end): array
     {
         $this->_em->getFilters()->disable('activity_year_filter');
 

+ 2 - 2
src/Repository/Core/ContactPointRepository.php

@@ -26,7 +26,7 @@ class ContactPointRepository extends ServiceEntityRepository
      * Récupération des points de contacts d'une organization et d'un type précis
      * @param String $type
      * @param Organization $organization
-     * @return array
+     * @return list<ContactPoint>
      */
     public function getByTypeAndOrganization(String $type, Organization $organization): array
     {
@@ -45,7 +45,7 @@ class ContactPointRepository extends ServiceEntityRepository
      * Récupération des points de contacts d'une person et d'un type précis
      * @param String $type
      * @param Person $person
-     * @return array
+     * @return list<ContactPoint>
      */
     public function getByTypeAndPerson(String $type, Person $person): array
     {

+ 1 - 1
src/Repository/Network/NetworkOrganizationRepository.php

@@ -72,7 +72,7 @@ class NetworkOrganizationRepository extends ServiceEntityRepository
      *
      * @param Organization $organization.
      *
-     * @return array The organizations.
+     * @return list<Organization> The organizations.
      */
     public function findAllParents(Organization $organization): array
     {

+ 1 - 1
src/Repository/Organization/OrganizationAddressPostalRepository.php

@@ -25,7 +25,7 @@ class OrganizationAddressPostalRepository extends ServiceEntityRepository
      * Récupération des adresses postal d'une organization et d'un type précis
      * @param String $type
      * @param Organization $organization
-     * @return array|null
+     * @return list<OrganizationAddressPostal>|null
      */
     public function getByType(String $type, Organization $organization): ?array
     {

+ 7 - 1
src/Serializer/AccessContextBuilder.php

@@ -12,7 +12,7 @@ use Symfony\Bundle\SecurityBundle\Security;
 /**
  * Classe servant à ajouter le groupe de denormalization à la ressource Access par rapport au role de l'utilisateur
  */
-final class AccessContextBuilder implements SerializerContextBuilderInterface
+final readonly class AccessContextBuilder implements SerializerContextBuilderInterface
 {
     public function __construct(
         private SerializerContextBuilderInterface $decorated,
@@ -22,6 +22,12 @@ final class AccessContextBuilder implements SerializerContextBuilderInterface
     { }
 
 
+    /**
+     * @param Request $request
+     * @param bool $normalization
+     * @param mixed[]|null $extractedAttributes
+     * @return mixed[]
+     */
     public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
     {
         $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);

+ 32 - 1
src/Serializer/DefaultNormalizer.php

@@ -5,7 +5,10 @@ namespace App\Serializer;
 
 use App\Entity\Access\Access;
 use App\Service\Utils\EntityUtils;
+use ArrayObject;
+use ReflectionException;
 use Symfony\Bundle\SecurityBundle\Security;
+use Symfony\Component\Serializer\Exception\ExceptionInterface;
 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 use Symfony\Component\Serializer\SerializerAwareInterface;
@@ -27,22 +30,50 @@ final class DefaultNormalizer implements NormalizerInterface, DenormalizerInterf
         }
     }
 
+    /**
+     * @param $data
+     * @param $format
+     * @param mixed[] $context
+     * @return bool
+     */
     public function supportsNormalization($data, $format = null, array $context = []): bool
     {
         return $this->decorated->supportsNormalization($data, $format);
     }
 
-    public function normalize($object, $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
+    /**
+     * @param $object
+     * @param $format
+     * @param mixed[]  $context
+     * @return mixed
+     * @throws ExceptionInterface
+     */
+    public function normalize($object, $format = null, array $context = []): mixed
     {
         return $this->decorated->normalize($object, $format, $context);
     }
 
+    /**
+     * @param $data
+     * @param $type
+     * @param $format
+     * @param mixed[] $context
+     * @return bool
+     */
     public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
     {
         /** @phpstan-ignore-next-line */
         return $this->decorated->supportsDenormalization($data, $type, $format);
     }
 
+    /**
+     * @param $data
+     * @param $class
+     * @param $format
+     * @param mixed[] $context
+     * @return mixed
+     * @throws ReflectionException
+     */
     public function denormalize($data, $class, $format = null, array $context = []): mixed
     {
         /** @phpstan-ignore-next-line */

+ 3 - 3
src/Service/Access/Utils.php

@@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
  * Class Utils : service rassemblant des fonctions d'aides pour les questions se rapportant à l'access
  * @package App\Service\Resource
  */
-class Utils
+readonly class Utils
 {
     public function __construct(
         private RoleHierarchyInterface $roleHierarchy,
@@ -28,7 +28,7 @@ class Utils
      * Filtre un tableau d'Access pour ne laisser que les Accesses ne correspondant pas à l'Access passé en second parametre
      * @param array<Access> $accesses
      * @param Access $access
-     * @return array
+     * @return array<Access>
      * @see UtilsTest::testFilterAccesses()
      * TODO: est-ce qu'on essaierait pas de trouver un nom plus explicite? j'ai pas trop d'idée la tout de suite cela dit
      */
@@ -55,7 +55,7 @@ class Utils
     /**
      * Va récupérer les roles d'access + les roles optionnels possibles
      * @param Access $access
-     * @return array
+     * @return string[]
      * @see UtilsTest::testGetAllRoles()
      */
     public function getAllRoles(Access $access): array

+ 15 - 15
src/Service/Constraint/AbstractTimeConstraintUtils.php

@@ -19,7 +19,7 @@ abstract class AbstractTimeConstraintUtils
 
     /**
      * Retourne true si l'utilisateur veux une période précise
-     * @param array<string> $historical
+     * @param array<bool|string> $historical
      * @return bool
      * @see DateTimeConstraintTest::testHasCustomPeriods()
      */
@@ -30,9 +30,9 @@ abstract class AbstractTimeConstraintUtils
 
     /**
      * Fonction permettant d'ajouter une nouvelle contrainte de date
-     * @param array $contraints
-     * @param array $newContraint
-     * @return array
+     * @param array<string, array<string, list<int>>> $contraints
+     * @param array<string, list<int>> $newContraint
+     * @return array<string, array<string, int[]>>
      * @see DateTimeConstraintTest::testAddConstraint()
      */
     protected function addConstraint(array $contraints, array $newContraint): array
@@ -43,10 +43,10 @@ abstract class AbstractTimeConstraintUtils
 
     /**
      * Construit le tableau de contraintes pour une condition (start, end)
-     * @param array $contraints
-     * @param array $newContraint
+     * @param array<string, array<string, list<int>>> $contraints
+     * @param array<string, list<int>> $newContraint
      * @param string $key
-     * @return array
+     * @return array<string, array<string, int[]>>
      */
     protected function mergeConstraint(array $contraints, array $newContraint, string $key): array
     {
@@ -68,8 +68,8 @@ abstract class AbstractTimeConstraintUtils
 
     /**
      * Nettoyage des contraintes (toutes celles supérieur à la condition cancel et les valeurs null isolées)
-     * @param array $constraints
-     * @return array
+     * @param array<string, array<string, list<int>>> $constraints
+     * @return array<string, array<string, list<int>>>
      * @see DateTimeConstraintTest::testCleanConstraints()
      */
     protected function cleanConstraints(array $constraints): array
@@ -85,9 +85,9 @@ abstract class AbstractTimeConstraintUtils
     /**
      * Pour chaque contraintes appliquées à une date on vérifie qu'on ne dépasse pas la valeur cancel : c'est à dire
      * la condition qui démontre que toutes les valeurs arithmétiques ont été choisies
-     * @param array $constraints
-     * @param $key
-     * @return array
+     * @param array<string, array<string, list<int>>> $constraints
+     * @param string $key
+     * @return array<string, list<int>>
      * @see DateTimeConstraintTest::testFilterConstraint()
      */
     protected function filterConstraint(array $constraints, string $key): array
@@ -100,9 +100,9 @@ abstract class AbstractTimeConstraintUtils
     /**
      * On ne conserve pas les contraintes sur des conditions start et end si ces dernieres ne possède qu'une valeur null :
      * une valeur null doit obligatoirement s'appliquer avec un OR
-     * @param array $constraints
-     * @param $key
-     * @return array
+     * @param array<string, array<string, list<int>>> $constraints
+     * @param string $key
+     * @return array<string, list<int>>
      * @see DateTimeConstraintTest::testClearNull()
      */
     protected function clearNull(array $constraints, string $key): array

+ 5 - 5
src/Service/Constraint/ActivityYearConstraint.php

@@ -23,7 +23,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils
      * Main method
      *
      * @param int $accessID
-     * @return array
+     * @return array<string, array<string, list<int>>>
      * @throws \Exception
      */
     public function invoke(int $accessID): array
@@ -68,7 +68,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils
      * Une période est dans le présent si :
      * - l'année de début est égale (=) à l'année à afficher
      * @param int $year
-     * @return array
+     * @return array<string, list<int>>
      */
     protected function presentConstraint(int $year): array
     {
@@ -83,7 +83,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils
      * Une période est dans le passée si :
      * - l'année de début est plus petite (<) à l'année à afficher
      * @param int $year
-     * @return array
+     * @return array<string, list<int>>
      */
     protected function pastConstraint(int $year): array
     {
@@ -98,7 +98,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils
      * Une période est dans le futur si :
      * - l'année de début est plus grande (>) à l'année à afficher
      * @param int $year
-     * @return array
+     * @return array<string, list<int>>
      */
     protected function futureConstraint(int $year): array
     {
@@ -116,7 +116,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils
      * - l'année de début est plus petite ou égale (<=) à l'année de fin
      *
      * @param array<int> $years
-     * @return array
+     * @return array<string, list<int>>
      */
     protected function customConstraint(array $years): array
     {

+ 13 - 13
src/Service/Constraint/DateTimeConstraint.php

@@ -7,7 +7,7 @@ use App\Entity\Access\Access;
 use App\Service\Organization\Utils as OrganizationUtils;
 use App\Tests\Service\Constraint\DateTimeConstraintTest;
 use Doctrine\ORM\EntityManagerInterface;
-use JetBrains\PhpStorm\ArrayShape;
+use Exception;
 
 /**
  * Classe DateTimeConstraint qui définie les dates de débuts et fin de périodes
@@ -16,16 +16,16 @@ use JetBrains\PhpStorm\ArrayShape;
 class DateTimeConstraint extends AbstractTimeConstraintUtils
 {
     public function __construct(
-        private EntityManagerInterface $entityManager,
-        private OrganizationUtils $organizationUtils
+        readonly private EntityManagerInterface $entityManager,
+        readonly private OrganizationUtils $organizationUtils
     )
     { }
 
     /**
      * Main méthod
      * @param int $accessID
-     * @return array
-     * @throws \Exception
+     * @return array<string, array<string, list<int>>>
+     * @throws Exception
      */
     public function invoke(int $accessID): array
     {
@@ -69,8 +69,8 @@ class DateTimeConstraint extends AbstractTimeConstraintUtils
      * Fonction permettant de récupérer les périodes de début et de fin d'affichage
      *
      * @param Access $access
-     * @return array
-     * @throws \Exception
+     * @return string[]
+     * @throws Exception
      * @see DateTimeConstraintTest::testGetPeriodsToday()
      */
     protected function getPeriods(Access $access): array
@@ -96,8 +96,8 @@ class DateTimeConstraint extends AbstractTimeConstraintUtils
      * ET
      *  - la date de fin est plus grande ou égale (>=) à la date de fin de période à afficher OU que la date de fin n'est pas remplie (NULL)
      *
-     * @param array $periods
-     * @return array
+     * @param string[] $periods
+     * @return array<string, int[]>
      *
      * @see DateTimeConstraintTest::testPresentConstrain()
      */
@@ -117,8 +117,8 @@ class DateTimeConstraint extends AbstractTimeConstraintUtils
     /**
      * Une période est dans le passé si :
      * - la date de fin est plus petite (<) que la date de début de période à afficher
-     * @param array<string> $periods
-     * @return array
+     * @param string[] $periods
+     * @return array<string, int[]>
      * @see DateTimeConstraintTest::testPastConstrain()
      */
     protected function pastConstraint(array $periods): array
@@ -133,8 +133,8 @@ class DateTimeConstraint extends AbstractTimeConstraintUtils
     /**
      * Une période est dans le futur si :
      * - la date de début est plus grande (>) que la date de fin de période à afficher
-     * @param array<string> $periods
-     * @return array
+     * @param string[] $periods
+     * @return array<string, int[]>
      * @see DateTimeConstraintTest::testFuturConstrain()
      */
     protected function futureConstraint(array $periods): array

+ 1 - 1
src/Service/Elasticsearch/EducationNotationUpdater.php

@@ -16,7 +16,7 @@ class EducationNotationUpdater
 
     /**
      * Effectue le replace many des educations notations
-     * @param $educationNotations
+     * @param mixed[] $educationNotations
      */
     public function update(array $educationNotations): void{
         $this->objectPersisterEducationNotation->replaceMany($educationNotations);

+ 2 - 2
src/Service/Export/BaseExporter.php

@@ -21,7 +21,7 @@ use Twig\Environment;
 /**
  * Classe de base des services d'export
  */
-abstract class BaseExporter implements ExporterInterface
+abstract class BaseExporter
 {
     // dependencies injections
     protected AccessRepository $accessRepository;
@@ -144,7 +144,7 @@ abstract class BaseExporter implements ExporterInterface
      * @param ExportRequest $exportRequest
      * @return ExportModelInterface
      */
-    protected function buildModel(ExportRequest $exportRequest): ExportModelInterface
+    public function buildModel(ExportRequest $exportRequest): ExportModelInterface
     {
         throw new \RuntimeException('not implemented error');
     }

+ 9 - 0
src/Service/Export/ExporterInterface.php

@@ -5,6 +5,7 @@ namespace App\Service\Export;
 
 use App\ApiResources\Export\ExportRequest;
 use App\Entity\Core\File;
+use App\Service\Export\Model\ExportModelInterface;
 
 /**
  * Classe de base des services d'export
@@ -35,4 +36,12 @@ interface ExporterInterface
      * @return File
      */
     public function prepareFile(ExportRequest $exportRequest, bool $flushFile = true): File;
+
+    /**
+     * Construit le modèle de données qui servira au render du template
+     *
+     * @param ExportRequest $exportRequest
+     * @return ExportModelInterface
+     */
+    public function buildModel(ExportRequest $exportRequest): ExportModelInterface;
 }

+ 7 - 3
src/Service/Export/LicenceCmfExporter.php

@@ -14,7 +14,7 @@ use App\Service\Export\Model\LicenceCmfCollection;
 /**
  * Exporte la licence CMF de la structure ou du ou des access, au format demandé
  */
-class LicenceCmfExporter extends BaseExporter
+class LicenceCmfExporter extends BaseExporter implements ExporterInterface
 {
     public const CMF_ID = 12097;
 
@@ -34,7 +34,11 @@ class LicenceCmfExporter extends BaseExporter
         return $exportRequest instanceof LicenceCmfOrganizationER;
     }
 
-    protected function buildModel(ExportRequest $exportRequest): LicenceCmfCollection
+    /**
+     * @param LicenceCmfOrganizationER $exportRequest
+     * @return LicenceCmfCollection
+     */
+    public function buildModel(ExportRequest $exportRequest): LicenceCmfCollection
     {
         $organization = $this->accessRepository->find($exportRequest->getRequesterId())?->getOrganization();
         if ($organization === null) {
@@ -86,7 +90,7 @@ class LicenceCmfExporter extends BaseExporter
     }
 
     /**
-     * @param ExportRequest $exportRequest
+     * @param LicenceCmfOrganizationER $exportRequest
      * @return string
      */
     protected function getFileBasename(ExportRequest $exportRequest): string

+ 2 - 2
src/Service/Mailer/Builder/AbstractBuilder.php

@@ -54,7 +54,7 @@ class AbstractBuilder implements AbstractBuilderInterface
 
     /**
      * @param string $template
-     * @param array $context
+     * @param mixed[] $context
      * @return string
      *
      * @see AbstractBuilderTest::testRender()
@@ -93,7 +93,7 @@ class AbstractBuilder implements AbstractBuilderInterface
     }
 
     /**
-     * @param array $contactPoints
+     * @param list<ContactPoint> $contactPoints
      * @param EmailRecipient $recipient
      *
      * @see AbstractBuilderTest::testSetMailToRecipient()

+ 5 - 0
src/Service/Mailer/Builder/AbstractBuilderInterface.php

@@ -10,6 +10,11 @@ use App\Service\Mailer\Email;
 
 interface AbstractBuilderInterface {
 
+    /**
+     * @param string $template
+     * @param mixed[] $context
+     * @return string
+     */
     public function render(string $template, array $context): string;
 
     public function buildEmailEntity(string $subject, Access $author, string $content): EmailEntity;

+ 7 - 7
src/Service/Mailer/Mailer.php

@@ -120,7 +120,7 @@ class Mailer
 
     /**
      * Envoi le rapport d'envoi
-     * @param ArrayCollection $emails
+     * @param ArrayCollection<Email> $emails
      *
      * @see MailerTest::testSendReport()
      */
@@ -168,7 +168,7 @@ class Mailer
 
     /**
      * Créé le Templated Email contenant le rapport d'envoi
-     * @param ArrayCollection $emails
+     * @param ArrayCollection<Email> $emails
      * @return TemplatedEmail
      *
      * @see MailerTest::testCreateReportEmail()
@@ -196,8 +196,8 @@ class Mailer
 
     /**
      * Récupère les recipient delivered & undelivered de l'ensemble des emails
-     * @param ArrayCollection $emails
-     * @return array[]
+     * @param ArrayCollection<Email> $emails
+     * @return list<EmailRecipient[]>
      *
      * @see MailerTest::testGetDeliveredAndUndelivered()
      */
@@ -259,9 +259,9 @@ class Mailer
 
     /**
      * Reduit le nombre d'emails a envoyer si on ne se trouve pas en prod
-     * @param ArrayCollection $emailsCollection
+     * @param ArrayCollection<Email> $emailsCollection
      *
-     * @return ArrayCollection
+     * @return ArrayCollection<Email>
      * @see MailerTest::testReduceEmailsCollectionInPreproduction()
      */
     public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection
@@ -289,7 +289,7 @@ class Mailer
     /**
      * On change le #__#ANTISPAM_PERSON_EMAIL#__# par la liste des emails afin d'éviter le spamming sur l'envoi en masse
      * @param Email $email
-     * @param array $addresses
+     * @param list<Address> $addresses
      * @see MailerTest::testSetAntiSpam()
      */
     public function setAntiSpam(Email $email, array $addresses): void

+ 3 - 2
src/Service/MercureHub.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 namespace App\Service;
 
 use ApiPlatform\Api\IriConverterInterface;
+use InvalidArgumentException;
 use Symfony\Component\Mercure\HubInterface;
 use Symfony\Component\Mercure\Update;
 use Symfony\Component\Serializer\Encoder\EncoderInterface;
@@ -17,7 +18,7 @@ use Symfony\Component\Serializer\SerializerInterface;
  * The update topic is the id of the recipient user.
  * The content is a json containing the iri of the entity, the operation type, and the current data of this entity
  */
-class MercureHub
+readonly class MercureHub
 {
     public const UPDATE = 'update';
     public const CREATE = 'create';
@@ -49,7 +50,7 @@ class MercureHub
     public function publish(int $accessId, mixed $entity, string $operationType = self::UPDATE): void
     {
         if (!in_array($operationType, [self::UPDATE, self::CREATE, self::DELETE], true)) {
-            throw new \InvalidArgumentException('Invalid operation type');
+            throw new InvalidArgumentException('Invalid operation type');
         }
 
         $data = $this->encoder->encode([

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

@@ -61,7 +61,7 @@ class MobytService extends ApiRequestService
      *
      * @param string $login
      * @param string $password
-     * @return array
+     * @return mixed[]
      * @throws \JsonException
      */
     public function getUserStatus(string $login, string $password): array

+ 3 - 3
src/Service/Network/Tree.php

@@ -21,7 +21,7 @@ class Tree
     /**
      * Retrouve tous les parents d'une structure et les tries selon leur type principal
      * @param Organization $organization
-     * @return array
+     * @return list<Organization>
      */
     public function findAllParentsAndSortByType(Organization $organization): array
     {
@@ -31,8 +31,8 @@ class Tree
     /**
      * Trie les organisations par rapport à leur type principal :
      * DELEGATION, GROUPMENT, LOCAL_FEDERATION, DEPARTEMENTAL_FEDERATION, REGIONAL_FEDERATION, NATIONAL_FEDERATION
-     * @param array $organizations
-     * @return array
+     * @param list<Organization> $organizations
+     * @return list<Organization>
      * @see TreeTest::testSortByType()
      */
     public function sortByType(array $organizations): array

+ 3 - 2
src/Service/Notifier.php

@@ -7,9 +7,10 @@ use App\Entity\Access\Access;
 use App\Entity\Core\File;
 use App\Entity\Core\Notification;
 use App\Enum\Core\NotificationTypeEnum;
+use DateTime;
 use Doctrine\ORM\EntityManagerInterface;
 
-class Notifier
+readonly class Notifier
 {
     public function __construct(
         private EntityManagerInterface $em,
@@ -23,7 +24,7 @@ class Notifier
         array $message,
         string $link = null
     ): Notification {
-        $now = new \DateTime();
+        $now = new DateTime();
 
         $notification = new Notification();
         $notification->setName($name)

+ 27 - 10
src/Service/Security/Module.php

@@ -6,7 +6,6 @@ namespace App\Service\Security;
 use App\Entity\Organization\Organization;
 use App\Service\Utils\Parser;
 use App\Service\Utils\Reflection;
-use App\Test\Service\Security\ModuleTest;
 use Doctrine\Common\Cache\ApcuCache;
 use Symfony\Component\Config\FileLocator;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -17,17 +16,27 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  */
 class Module
 {
+    /**
+     * @var mixed[]|null $moduleConfig
+     */
     private array | null $moduleConfig = null;
+
+    /**
+     * @var mixed[]|null $moduleByConditionsConfig
+     */
     private array | null $moduleByConditionsConfig = null;
 
-    public function __construct(private Reflection $reflection, private Parser $parser, private string $opentalentConfig)
+    public function __construct(
+        readonly private Reflection $reflection,
+        readonly private Parser $parser,
+        readonly private string $opentalentConfig)
     {}
 
     /**
      * @todo activer le cache après que la fin de la migration.
      * Récupère tous les modules de l'organisation
      * @param Organization $organization
-     * @return array
+     * @return list<string>
      */
     public function getOrganizationModules(Organization $organization): array
     {
@@ -55,7 +64,7 @@ class Module
     /**
      * Récupère les modules disponibles dans les settings de l'organisation (Sms, Pes, etc)
      * @param Organization $organization
-     * @return array
+     * @return list<string>
      * @see ModuleTest::testGetModuleBySettings()
      */
     public function getModuleBySettings(Organization $organization): array
@@ -74,7 +83,7 @@ class Module
     /**
      * Récupère les modules par conditions, grace au fichier modulebyconditions.yaml
      * @param Organization $organization
-     * @return array
+     * @return list<string>
      * @see ModuleTest::testGetModulesByConditions()
      */
     public function getModulesByConditions(Organization $organization): array
@@ -101,7 +110,7 @@ class Module
     /**
      * Récupère les modules disponibles par produit grace au fichier products.yaml
      * @param string $product
-     * @return array|null
+     * @return list<string>|null
      * @see ModuleTest::testGetModulesByProductConfiguration()
      */
     public function getModulesByProductConfiguration(string $product): ?array
@@ -122,6 +131,10 @@ class Module
         return $modules;
     }
 
+    /**
+     * @return mixed[]
+     * @throws \Exception
+     */
     protected function getModuleConfig(): array {
         if ($this->moduleConfig === null) {
             $this->moduleConfig = $this->loadModuleConfig();
@@ -131,14 +144,18 @@ class Module
 
     /**
      * Parse et retourne le contenu du fichier products.yaml
-     * @return array
+     * @return mixed
      * @throws \Exception
      */
-    protected function loadModuleConfig(): array
+    protected function loadModuleConfig(): mixed
     {
         return $this->parser->yamlParser($this->opentalentConfig, 'products.yaml');
     }
 
+    /**
+     * @return mixed[]
+     * @throws \Exception
+     */
     protected function getModuleByConditionsConfig(): array {
         if ($this->moduleByConditionsConfig === null) {
             $this->moduleByConditionsConfig = $this->loadModuleByConditionsConfig();
@@ -148,10 +165,10 @@ class Module
 
     /**
      * Parse et retourne le contenu du fichier modulesbyconditions.yaml
-     * @return array
+     * @return mixed
      * @throws \Exception
      */
-    protected function loadModuleByConditionsConfig(): array
+    protected function loadModuleByConditionsConfig(): mixed
     {
         return $this->parser->yamlParser($this->opentalentConfig, 'modulesbyconditions.yaml');
     }

+ 7 - 3
src/Service/ServiceIterator/CronjobIterator.php

@@ -3,15 +3,16 @@
 namespace App\Service\ServiceIterator;
 
 use App\Service\Cron\CronjobInterface;
+use RuntimeException;
 
 /**
  * Permet d'itérer sur les cronjobs
  */
-class CronjobIterator
+readonly class CronjobIterator
 {
     /**
      * Pour l'injection des services, voir config/services.yaml, section 'TAG Services'
-     * @param iterable $cronjobServices
+     * @param iterable<CronjobInterface> $cronjobServices
      */
     public function __construct(
         private iterable $cronjobServices,
@@ -25,9 +26,12 @@ class CronjobIterator
                 return $cronService;
             }
         }
-        throw new \RuntimeException('no cronjob service found with this name : ' . $name);
+        throw new RuntimeException('no cronjob service found with this name : ' . $name);
     }
 
+    /**
+     * @return iterable<CronjobInterface>
+     */
     public function getAll(): iterable {
         return $this->cronjobServices;
     }

+ 4 - 1
src/Service/ServiceIterator/CurrentAccessExtensionIterator.php

@@ -6,7 +6,10 @@ namespace App\Service\ServiceIterator;
 use App\Doctrine\Access\AccessExtensionInterface;
 use Doctrine\ORM\QueryBuilder;
 
-class CurrentAccessExtensionIterator {
+readonly class CurrentAccessExtensionIterator {
+    /**
+     * @param iterable<AccessExtensionInterface> $extensions
+     */
     public function __construct(private iterable $extensions)
     { }
 

+ 6 - 6
src/Service/ServiceIterator/EncoderIterator.php

@@ -3,18 +3,17 @@ declare(strict_types=1);
 
 namespace App\Service\ServiceIterator;
 
-use App\ApiResources\Export\ExportRequest;
 use App\Service\Export\Encoder\EncoderInterface;
-use Exception;
+use RuntimeException;
 
 /**
  * Permet d'itérer sur les services d'encodage
  */
-class EncoderIterator
+readonly class EncoderIterator
 {
     /**
      * Pour l'injection des services, voir config/services.yaml, section 'TAG Services'
-     * @param iterable $encoders
+     * @param iterable<EncoderInterface> $encoders
      */
     public function __construct(
         private iterable $encoders,
@@ -31,9 +30,10 @@ class EncoderIterator
     {
         /** @var EncoderInterface $encoder */
         foreach ($this->encoders as $encoder){
-            if($encoder->support($format))
+            if($encoder->support($format)) {
                 return $encoder;
+            }
         }
-        throw new \RuntimeException('no encoder found for this export request');
+        throw new RuntimeException('no encoder found for this export request');
     }
 }

+ 6 - 4
src/Service/ServiceIterator/ExporterIterator.php

@@ -6,15 +6,16 @@ namespace App\Service\ServiceIterator;
 use App\ApiResources\Export\ExportRequest;
 use App\Service\Export\ExporterInterface;
 use Exception;
+use RuntimeException;
 
 /**
  * Permet d'itérer sur les services d'export
  */
-class ExporterIterator
+readonly class ExporterIterator
 {
     /**
      * Pour l'injection des services, voir config/services.yaml, section 'TAG Services'
-     * @param iterable $exportServices
+     * @param iterable<ExporterInterface> $exportServices
      */
     public function __construct(
         private iterable $exportServices,
@@ -32,9 +33,10 @@ class ExporterIterator
     {
         /** @var ExporterInterface $exportService */
         foreach ($this->exportServices as $exportService){
-            if($exportService->support($exportRequest))
+            if($exportService->support($exportRequest)) {
                 return $exportService;
+            }
         }
-        throw new Exception('no export service found for this export request');
+        throw new RuntimeException('no export service found for this export request');
     }
 }

+ 6 - 4
src/Service/ServiceIterator/Mailer/BuilderIterator.php

@@ -7,15 +7,16 @@ namespace App\Service\ServiceIterator\Mailer;
 use App\Service\Mailer\Model\MailerModelInterface;
 use App\Service\Mailer\Builder\BuilderInterface;
 use Exception;
+use RuntimeException;
 
 /**
  * Permet d'itérer sur les services de build Mailer
  */
-class BuilderIterator
+readonly class BuilderIterator
 {
     /**
      * Pour l'injection des services, voir config/services.yaml, section 'TAG Services'
-     * @param iterable $builderServices
+     * @param iterable<BuilderInterface> $builderServices
      */
     public function __construct(
         private iterable $builderServices,
@@ -33,9 +34,10 @@ class BuilderIterator
     {
         /** @var BuilderInterface $builderService */
         foreach ($this->builderServices as $builderService){
-            if($builderService->support($mailerModel))
+            if($builderService->support($mailerModel)) {
                 return $builderService;
+            }
         }
-        throw new Exception('no builder service found for this operation');
+        throw new RuntimeException('no builder service found for this operation');
     }
 }

+ 10 - 2
src/Service/ServiceIterator/OptionalsRolesIterator.php

@@ -6,17 +6,25 @@ namespace App\Service\ServiceIterator;
 use App\Entity\Access\Access;
 use App\Service\Access\OptionalsRolesInterface;
 
-class OptionalsRolesIterator {
+readonly class OptionalsRolesIterator {
 
+    /**
+     * @param iterable<OptionalsRolesInterface> $optionalsRoles
+     */
     public function __construct(private iterable $optionalsRoles)
     { }
 
+    /**
+     * @param Access $access
+     * @return list<string>
+     */
     public function getOptionalsRoles(Access $access):array {
         $roles = [];
         /** @var OptionalsRolesInterface $optionalsRoles */
         foreach ($this->optionalsRoles as $optionalsRoles){
-            if($optionalsRoles->support($access))
+            if($optionalsRoles->support($access)) {
                 $roles[] = $optionalsRoles->getRole();
+            }
         }
         return $roles;
     }

+ 1 - 1
src/Service/Twig/AssetsExtension.php

@@ -21,7 +21,7 @@ use Twig\TwigFunction;
 class AssetsExtension extends AbstractExtension
 {
     public function __construct(
-        private FileManager $fileManager
+        readonly private FileManager $fileManager
     )
     {}
 

+ 1 - 1
src/Service/Typo3/BindFileService.php

@@ -7,7 +7,7 @@ namespace App\Service\Typo3;
  *
  * @codeCoverageIgnore
  */
-class BindFileService
+readonly class BindFileService
 {
     public function __construct(
         private string $bindfileBufferFile

+ 2 - 3
src/Service/Typo3/Typo3Service.php

@@ -13,7 +13,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
 class Typo3Service
 {
     public function __construct(
-        private HttpClientInterface $typo3_client,
+        private readonly HttpClientInterface $typo3_client,
     )
     {}
 
@@ -21,8 +21,7 @@ class Typo3Service
      * Send a command to the given route of the Typo3 API
      *
      * @param string $route
-     * @param array $parameters
-     *
+     * @param array<string, string|int> $parameters
      * @return ResponseInterface
      * @throws TransportExceptionInterface
      */

+ 4 - 4
src/Service/Utils/ArrayUtils.php

@@ -12,12 +12,12 @@ class ArrayUtils
      * If recursive is true, when values are arrays, they'll get processed too to only keep changes. Else,
      * the whole value will be added to the changes if there is at least one difference between the former and the latter.
      *
-     * @param array $initialArray
-     * @param array $newArray
+     * @param mixed[] $initialArray
+     * @param mixed[] $newArray
      * @param bool $recursive
      * @param callable|null $callback An optional callback method to test the equality between to values. The callback shall
      *                                accept two parameters (the values) and return true if the values are equals.
-     * @return array
+     * @return mixed[]
      */
     public function getChanges(array $initialArray, array $newArray, bool $recursive = false, ?callable $callback = null): array
     {
@@ -53,7 +53,7 @@ class ArrayUtils
      *     ArrayUtils::getAndCast($array, 'a', 'int')  // => returns `123` as an integer
      *     ArrayUtils::getAndCast($array, 'b', 'int')  // => returns `null`
      *
-     * @param array $array
+     * @param mixed[] $array
      * @param string $key
      * @param string $type
      * @return mixed

+ 10 - 7
src/Service/Utils/DatesUtils.php

@@ -3,7 +3,10 @@ declare(strict_types=1);
 
 namespace App\Service\Utils;
 
+use DateTime;
+use DateTimeInterface;
 use DateTimeZone;
+use Exception;
 
 /**
  * Class Dates : méthodes d'aide pour la gestion de dates.
@@ -15,14 +18,14 @@ class DatesUtils
     protected static string | null $fakeDateTime = null;
 
     /**
-     * @throws \Exception
+     * @throws Exception
      */
-    public static function new(string $datetime = "now", ?DateTimeZone $timezone = null): \DateTime
+    public static function new(string $datetime = "now", ?DateTimeZone $timezone = null): DateTime
     {
         if ($datetime === 'now') {
             $datetime = static::$fakeDateTime ?? $datetime;
         }
-        return new \DateTime($datetime, $timezone);
+        return new DateTime($datetime, $timezone);
     }
 
     /**
@@ -44,14 +47,14 @@ class DatesUtils
 
     /**
      * Vérifie si la date du jour est comprise dans l'interval passé en paramètres
-     * @param \DateTimeInterface $dateStart
-     * @param \DateTimeInterface|null $dateEnd
+     * @param DateTimeInterface $dateStart
+     * @param DateTimeInterface|null $dateEnd
      * @return bool
      * @see DatesUtilsTest::testIsIntervalIsValidNow()
      */
-    public static function isIntervalIsValidNow(\DateTimeInterface $dateStart, \DateTimeInterface $dateEnd = null): bool
+    public static function isIntervalIsValidNow(DateTimeInterface $dateStart, DateTimeInterface $dateEnd = null): bool
     {
-        $now = new \DateTime('now');
+        $now = new DateTime('now');
         return $dateStart <= $now && (is_null($dateEnd) || $dateEnd >= $now);
     }
 }

+ 10 - 5
src/Service/Utils/EntityUtils.php

@@ -6,6 +6,8 @@ namespace App\Service\Utils;
 use App\Attribute\BillingSettingDefaultValue;
 use App\Attribute\OrganizationDefaultValue;
 use App\Entity\Access\Access;
+use ReflectionClass;
+use ReflectionException;
 
 /**
  * Class EntityUtils : Gestion des valeurs par défauts devant être présentes dans les entités.
@@ -13,6 +15,9 @@ use App\Entity\Access\Access;
  */
 class EntityUtils
 {
+    /**
+     * @throws ReflectionException
+     */
     public function defaultValueSettersByAccess(mixed $entity, Access $access): void
     {
         $this->organizationDefaultValue($entity, $access);
@@ -22,11 +27,11 @@ class EntityUtils
     /**
      * @param mixed $entity
      * @param Access $access
-     * @throws \ReflectionException
+     * @throws ReflectionException
      */
     protected function organizationDefaultValue(mixed $entity, Access $access): void
     {
-        $reflection = new \ReflectionClass($entity::class);
+        $reflection = new ReflectionClass($entity::class);
         $organizationFaultValue = $reflection->getAttributes(OrganizationDefaultValue::class)[0] ?? null;
         $fieldName = $organizationFaultValue?->getArguments()['fieldName'] ?? null;
         if($fieldName){
@@ -37,15 +42,15 @@ class EntityUtils
     /**
      * @param mixed $entity
      * @param Access $access
-     * @throws \ReflectionException
+     * @throws ReflectionException
      */
     protected function billingSettingDefaultValueDefaultValue(mixed $entity, Access $access): void
     {
-        $reflection = new \ReflectionClass($entity::class);
+        $reflection = new ReflectionClass($entity::class);
         $billingSettingDefaultValueDefault = $reflection->getAttributes(BillingSettingDefaultValue::class)[0] ?? null;
         $fieldName = $billingSettingDefaultValueDefault?->getArguments()['fieldName'] ?? null;
         if($fieldName){
-            $entity->{sprintf('set%s', ucfirst($fieldName))}(...[$access->getOrganization()->getBillingSetting()]);
+            $entity->{sprintf('set%s', ucfirst($fieldName))}(...[$access->getOrganization()?->getBillingSetting()]);
         }
     }
 }

+ 2 - 1
src/Service/Utils/Environnement.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 namespace App\Service\Utils;
 
 use App\Enum\Utils\EnvironnementVarEnum;
+use RuntimeException;
 
 /**
  * Classe Environnement qui permet de récupérer des variables d'environnement
@@ -14,6 +15,6 @@ class Environnement
         if(in_array($name, EnvironnementVarEnum::toArray(), true)){
             return $_ENV[$name];
         }
-        throw new \RuntimeException(sprintf('Undefined environment variable : %s', $name), 500);
+        throw new RuntimeException(sprintf('Undefined environment variable : %s', $name), 500);
     }
 }

+ 33 - 25
src/Service/Utils/GpsCoordinateUtils.php

@@ -5,7 +5,13 @@ namespace App\Service\Utils;
 
 use App\ApiResources\Utils\GpsCoordinate;
 use App\Tests\Service\Utils\GpsCoordinateUtilsTest;
+use Exception;
+use JsonException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 
 /**
@@ -28,19 +34,20 @@ class GpsCoordinateUtils
      * @param string|null $street
      * @param string|null $cp
      * @param string|null $city
-     * @return array
-     * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
+     * @return mixed
+     * @throws JsonException
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
      * @see GpsCoordinateUtilsTest::testSearchGpsCoordinates()
      */
-    public function searchGpsCoordinates(?string $street, ?string $cp, ?string $city): array
+    public function searchGpsCoordinates(?string $street, ?string $cp, ?string $city): mixed
     {
         try{
             $url = sprintf('search?addressdetails=1&format=json&limit=10&street=%s&postalcode=%s&city=%s', $street, $cp, $city);
             $response = $this->clientOpenStreetMap->request('GET', $url)->getContent();
-        }catch(\Exception $e){
+        }catch(Exception $e){
             throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404);
         }
         return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
@@ -48,21 +55,22 @@ class GpsCoordinateUtils
 
     /**
      * Renvoi l'adresse correspondant à la latitude et longitude demandée
-     * @param $latitude
-     * @param $longitude
-     * @return array
-     * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
-     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
+     * @param float $latitude
+     * @param float $longitude
+     * @return mixed
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
+     * @throws JsonException
      * @see GpsCoordinateUtilsTest::testReverseGpsCoordinates()
      */
-    public function reverseGpsCoordinates(float $latitude, float $longitude): array
+    public function reverseGpsCoordinates(float $latitude, float $longitude): mixed
     {
         try{
             $url = sprintf('reverse?addressdetails=1&format=json&lat=%s&lon=%s', $latitude, $longitude);
             $response = $this->clientOpenStreetMap->request('GET', $url)->getContent();
-        }catch(\Exception $e){
+        }catch(Exception $e){
             throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404);
         }
 
@@ -71,7 +79,7 @@ class GpsCoordinateUtils
 
     /**
      * Transforme une réponse d'API en ressource GpsCoordinate
-     * @param array $gpsApiResponse
+     * @param mixed[] $gpsApiResponse
      * @return GpsCoordinate
      * @see GpsCoordinateUtilsTest::testCreateGpsCoordinate()
      */
@@ -80,8 +88,8 @@ class GpsCoordinateUtils
         $address = $this->transformAddress($gpsApiResponse['address']);
         $gpsCoordinate = new GpsCoordinate();
         $gpsCoordinate
-            ->setLatitude(floatval($gpsApiResponse['lat']))
-            ->setLongitude(floatval($gpsApiResponse['lon']))
+            ->setLatitude((float) $gpsApiResponse['lat'])
+            ->setLongitude((float) $gpsApiResponse['lon'])
             ->setCity($address['city'])
             ->setCp($address['cp'])
             ->setStreetAddress($address['streetAddress'])
@@ -91,15 +99,15 @@ class GpsCoordinateUtils
 
     /**
      * Permet de faire correspondre le bloc adresse renvoyé par l'API avec des éléments plus communs
-     * @param array $address
-     * @return array
+     * @param list<string> $address
+     * @return array<string, string|null>
      */
     public function transformAddress(array $address): array
     {
-        $addressTransformed['streetAddress'] = key_exists('road', $address) ? $address['road'] : (key_exists('hamlet', $address) ? $address['hamlet'] : null);
-        $addressTransformed['streetAddressSecond'] =  key_exists('road', $address) && key_exists('hamlet', $address)  ? $address['hamlet'] : null;
-        $addressTransformed['city'] = key_exists('town', $address) ? $address['town'] : (key_exists('village', $address) ? $address['village'] : null);
-        $addressTransformed['cp'] = key_exists('postcode', $address) ? $address['postcode'] : null;
+        $addressTransformed['streetAddress'] = array_key_exists('road', $address) ? $address['road'] : (array_key_exists('hamlet', $address) ? $address['hamlet'] : null);
+        $addressTransformed['streetAddressSecond'] =  array_key_exists('road', $address) && array_key_exists('hamlet', $address)  ? $address['hamlet'] : null;
+        $addressTransformed['city'] = array_key_exists('town', $address) ? $address['town'] : (array_key_exists('village', $address) ? $address['village'] : null);
+        $addressTransformed['cp'] = array_key_exists('postcode', $address) ? $address['postcode'] : null;
         return $addressTransformed;
     }
 }

+ 2 - 2
src/Service/Utils/Parser.php

@@ -16,10 +16,10 @@ class Parser
      * Parse le fichier yaml passé en paramètre et renvoie un tableau PHP
      * @param string $directory
      * @param string $yamlFile
-     * @return array
+     * @return mixed
      * @see ParserTest::testYamlParser()
      */
-    public function yamlParser(string $directory, string $yamlFile): array
+    public function yamlParser(string $directory, string $yamlFile): mixed
     {
         $configDirectories = [$directory];
         $fileLocator = new FileLocator($configDirectories);

+ 6 - 4
src/Service/Utils/Path.php

@@ -3,6 +3,8 @@ declare(strict_types=1);
 
 namespace App\Service\Utils;
 
+use RuntimeException;
+
 /**
  * Various methods to manipulate file paths
  */
@@ -40,8 +42,8 @@ class Path
      */
     public static function join(): string
     {
-        $paths = array_filter(func_get_args(), function ($s) { return $s !== ''; });
-        return preg_replace('#/+#','/',join('/', $paths));
+        $paths = array_filter(func_get_args(), static function ($s) { return $s !== ''; });
+        return preg_replace('#/+#','/',implode('/', $paths));
     }
 
     /**
@@ -49,7 +51,7 @@ class Path
      *
      * @param string $path
      * @param string $glob
-     * @return array
+     * @return list<string>
      */
     public static function list(string $path, string $glob = '*'): array
     {
@@ -60,7 +62,7 @@ class Path
     {
         $content = file_get_contents($path);
         if ($content === false) {
-            throw new \RuntimeException("File could not be read");
+            throw new RuntimeException("File could not be read");
         }
         return $content;
     }

+ 4 - 4
src/Service/Utils/Reflection.php

@@ -10,7 +10,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  * Class Reflection : Gestion des réflection de class
  * @package App\Service\Utils
  */
-class Reflection
+readonly class Reflection
 {
     public function __construct(private ContainerInterface $container)
     {}
@@ -20,7 +20,7 @@ class Reflection
      *
      * @param string $serviceName
      * @param string $method
-     * @param array $parameters
+     * @param mixed[] $parameters
      * @return mixed
      */
     public function dynamicInvokeServiceWithArgsAndMethod(string $serviceName, string $method, array $parameters = []): mixed
@@ -40,8 +40,8 @@ class Reflection
      *
      * @param string $className
      * @param string $methodName
-     * @param array $parameters
-     * @param array $constructorParameters
+     * @param mixed[] $parameters
+     * @param mixed[] $constructorParameters
      * @return mixed
      * @throws ReflectionException
      */

+ 4 - 4
src/Service/Utils/UrlBuilder.php

@@ -24,17 +24,17 @@ class UrlBuilder
      * Concatenate an url and a list of parameters
      *
      * @param string $url
-     * @param array $parameters
+     * @param list<string> $parameters
      * @return string
      */
     public static function concatParameters(string $url, array $parameters = []): string
     {
         if (!$parameters) { return $url; }
         $url = rtrim($url, '?&/');
-        $query = join(
+        $query = implode(
             '&',
             array_map(
-                function ($k, $v = '') {
+                static function ($k, $v = '') {
                     $q = urlencode((string)$k);
                     if ((string)$v) {
                         $q .= '=' . urlencode((string)$v);
@@ -67,7 +67,7 @@ class UrlBuilder
      *
      * @param string $url The base url
      * @param string $path A path to append (can be an empty string)
-     * @param array $parameters A list of parameters (can be an empty array)
+     * @param list<string> $parameters A list of parameters (can be an empty array)
      * @param bool $preprendHttps Should the 'https://' be prepended if missing
      * @return string
      */

+ 3 - 0
src/Service/Utils/Uuid.php

@@ -2,6 +2,8 @@
 
 namespace App\Service\Utils;
 
+use Exception;
+
 class Uuid
 {
     /**
@@ -10,6 +12,7 @@ class Uuid
      * @param ?int $length To limit the length of the uuid (standard uuid count 36 cars). Warning: reducing
      *                   the number of characters breaks the warranty of global unity.
      * @return string
+     * @throws Exception
      */
     public static function uuid(int $length = null): string
     {

+ 12 - 4
src/State/Processor/Access/AdminAccessProcessor.php

@@ -9,13 +9,14 @@ use App\Entity\Access\Access;
 use App\Service\Access\Utils as AccessUtils;
 use App\Service\Core\ContactPointUtils;
 use Doctrine\ORM\EntityManagerInterface;
+use RuntimeException;
 use Symfony\Bundle\SecurityBundle\Security;
 use ApiPlatform\Metadata\Operation;
 
 /**
  * Classe AdminAccessProcessor qui est un custom dataPersister gérant la resource AdminAccess
  */
-class AdminAccessProcessor implements ProcessorInterface
+readonly class AdminAccessProcessor implements ProcessorInterface
 {
     public function __construct(
         private Security $security,
@@ -25,10 +26,17 @@ class AdminAccessProcessor implements ProcessorInterface
     )
     { }
 
+    /**
+     * @param mixed $data
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return void
+     */
     public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
     {
         if($operation instanceof Delete){
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         /** @var Access $access */
@@ -36,12 +44,12 @@ class AdminAccessProcessor implements ProcessorInterface
 
         $administrator = $this->accessUtils->findAdminFor($access->getOrganization());
         if(!$administrator){
-            throw new \RuntimeException('administrator_not_found', 404);
+            throw new RuntimeException('administrator_not_found', 404);
         }
 
         $contactPoint = $this->contactPointUtils->getPersonContactPointPrincipal($administrator);
         if(!$contactPoint){
-            throw new \RuntimeException('administrator_contact_point_not_found', 404);
+            throw new RuntimeException('administrator_contact_point_not_found', 404);
         }
 
         $contactPoint->setEmail($data->getEmail());

+ 7 - 5
src/State/Processor/EntityProcessor.php

@@ -8,6 +8,7 @@ use ApiPlatform\State\ProcessorInterface;
 use App\Service\OnChange\OnChangeContext;
 use App\Service\OnChange\OnChangeDefault;
 use App\Service\OnChange\OnChangeInterface;
+use RuntimeException;
 use Symfony\Contracts\Service\Attribute\Required;
 
 /**
@@ -31,15 +32,16 @@ class EntityProcessor implements ProcessorInterface
 
     /**
      * Persist l'entité et déclenche les différents hooks de la classe OnChangeInterface définie par le data persister
-     *
      * @param mixed $data
-     * @param array $context
-     * @return object
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return mixed
      */
-    public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
+    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
     {
         if($operation instanceof Delete){
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         $onChangeContext = new OnChangeContext($context);

+ 7 - 5
src/State/Processor/Export/LicenceCmf/ExportRequestProcessor.php

@@ -11,10 +11,12 @@ use App\Entity\Access\Access;
 use App\Entity\Core\File;
 use App\Message\Command\Export;
 use App\Service\ServiceIterator\ExporterIterator;
+use Exception;
+use RuntimeException;
 use Symfony\Component\Messenger\MessageBusInterface;
 use Symfony\Bundle\SecurityBundle\Security;
 
-class ExportRequestProcessor implements ProcessorInterface
+readonly class ExportRequestProcessor implements ProcessorInterface
 {
     public function __construct(
         private Security               $security,
@@ -25,15 +27,15 @@ class ExportRequestProcessor implements ProcessorInterface
     /**
      * @param ExportRequest $exportRequest
      * @param Operation $operation
-     * @param array $uriVariables
-     * @param array $context
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
      * @return File
-     * @throws \Exception
+     * @throws Exception
      */
     public function process(mixed $exportRequest, Operation $operation, array $uriVariables = [], array $context = []): File
     {
         if($operation instanceof Delete){
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         /** @var Access $access */

+ 11 - 2
src/State/Provider/Access/AccessProfileProvider.php

@@ -10,6 +10,8 @@ use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Profile\AccessProfile;
 use App\Entity\Access\Access;
 use App\Service\Access\AccessProfileCreator;
+use Exception;
+use RuntimeException;
 use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
 use Symfony\Bundle\SecurityBundle\Security;
 
@@ -17,7 +19,7 @@ use Symfony\Bundle\SecurityBundle\Security;
  * Class AccessProfileProvider : custom provider pour assurer l'alimentation de la réponse du GET my_profile
  * @package App\DataProvider\Access
  */
-final class AccessProfileProvider implements ProviderInterface
+final readonly class AccessProfileProvider implements ProviderInterface
 {
     public function __construct(
         private Security $security,
@@ -25,10 +27,17 @@ final class AccessProfileProvider implements ProviderInterface
     )
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return AccessProfile|null
+     * @throws Exception
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?AccessProfile
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         /** @var Access $access */

+ 11 - 2
src/State/Provider/Access/AdminAccessProvider.php

@@ -10,13 +10,15 @@ use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Access\AdminAccess;
 use App\Entity\Access\Access;
 use App\Service\Access\AdminAccessUtils;
+use Exception;
+use RuntimeException;
 use Symfony\Bundle\SecurityBundle\Security;
 
 /**
  * Class AdminAccessProvider : custom provider pour la resource AdminAccess
  * @package App\DataProvider\Access
  */
-final class AdminAccessProvider implements ProviderInterface
+final readonly class AdminAccessProvider implements ProviderInterface
 {
     public function __construct(
         private Security $security,
@@ -24,10 +26,17 @@ final class AdminAccessProvider implements ProviderInterface
     )
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return AdminAccess|null
+     * @throws Exception
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?AdminAccess
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         /** @var Access $access */

+ 19 - 4
src/State/Provider/Core/DownloadRequestProvider.php

@@ -9,7 +9,9 @@ use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\DownloadRequest;
 use App\Enum\Core\FileStatusEnum;
 use App\Repository\Core\FileRepository;
+use App\Service\File\Exception\FileNotFoundException;
 use App\Service\File\FileManager;
+use RuntimeException;
 use Symfony\Component\HttpFoundation\HeaderUtils;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Response;
@@ -18,7 +20,7 @@ use Symfony\Bundle\SecurityBundle\Security;
 /**
  * Custom provider pour le téléchargement des fichiers du LocalStorage
  */
-final class DownloadRequestProvider implements ProviderInterface
+final readonly class DownloadRequestProvider implements ProviderInterface
 {
     public function __construct(
         private FileRepository $fileRepository,
@@ -27,24 +29,37 @@ final class DownloadRequestProvider implements ProviderInterface
     )
     {}
 
+    /**
+     * @param string $resourceClass
+     * @param string|null $operationName
+     * @param mixed[] $context
+     * @return bool
+     */
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
         return DownloadRequest::class === $resourceClass;
     }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return Response|RedirectResponse
+     * @throws FileNotFoundException
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): Response | RedirectResponse
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         $id = $uriVariables['id'];
         $file = $this->fileRepository->find($id);
         if (empty($file)) {
-            throw new \RuntimeException("File " . $id . " does not exist; abort.");
+            throw new RuntimeException("File " . $id . " does not exist; abort.");
         }
         if ($file->getStatus() !== FileStatusEnum::READY()->getValue()) {
-            throw new \RuntimeException("File " . $id . " has " . $file->getStatus() . " status; abort.");
+            throw new RuntimeException("File " . $id . " has " . $file->getStatus() . " status; abort.");
         }
 
         // Read the file

+ 9 - 2
src/State/Provider/Cotisation/CotisationProvider.php

@@ -9,20 +9,27 @@ use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Cotisation\Cotisation;
 use App\Service\Cotisation\CotisationCreator;
+use RuntimeException;
 
 /**
  * Class CotisationProvider : custom provider pour assurer l'alimentation de la réponse du GET cotisation
  * @package App\DataProvider\Cotisation
  */
-final class CotisationProvider implements ProviderInterface
+final readonly class CotisationProvider implements ProviderInterface
 {
     public function __construct(private CotisationCreator $cotisationCreator)
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return Cotisation|null
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Cotisation
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         return $this->cotisationCreator->getCotisation($uriVariables['id']);

+ 9 - 2
src/State/Provider/Dolibarr/DolibarrAccountProvider.php

@@ -8,12 +8,13 @@ use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Dolibarr\DolibarrAccount;
 use App\Service\ApiResourceBuilder\Dolibarr\DolibarrAccountBuilder;
+use RuntimeException;
 
 /**
  * Custom provider pour les DolibarrAccounts récupérés via l'api dolibarr
  * @package App\DataProvider\Utils
  */
-final class DolibarrAccountProvider implements ProviderInterface
+final readonly class DolibarrAccountProvider implements ProviderInterface
 {
 
     public function __construct(
@@ -21,10 +22,16 @@ final class DolibarrAccountProvider implements ProviderInterface
     )
     {}
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return DolibarrAccount|null
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?DolibarrAccount
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         return $this->dolibarrAccountCreator->getDolibarrAccount($uriVariables['id']);

+ 13 - 4
src/State/Provider/Enum/EnumProvider.php

@@ -9,13 +9,15 @@ use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Enum\Enum;
 use App\Service\Utils\Parser;
 use App\Service\Utils\Reflection;
+use Exception;
+use RuntimeException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
 /**
  * Class EnumProvider : custom provider pour assurer l'alimentation des enums
  * @package App\DataProvider\Access
  */
-final class EnumProvider implements ProviderInterface
+final readonly class EnumProvider implements ProviderInterface
 {
     public function __construct(
         private Parser $parser,
@@ -24,25 +26,32 @@ final class EnumProvider implements ProviderInterface
     )
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return Enum|null
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Enum
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         $id = $uriVariables['id'];
         $enums = $this->parser->yamlParser($this->opentalentConfig, 'enum.yaml');
         $enumClass = $enums['opentalent'][$id];
 
-        if(!$enumClass)
+        if(!$enumClass) {
             throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $id));
+        }
 
         try{
             $items = $this->reflection->dynamicInvokeClassWithArgsAndMethod(
                 $enumClass,
                 'toArray'
             );
-        }catch (\Exception $exception){
+        }catch (Exception){
             throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $id));
         }
 

+ 12 - 3
src/State/Provider/Mobyt/MobytUserStatusProvider.php

@@ -8,24 +8,33 @@ use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Mobyt\MobytUserStatus;
 use App\Service\ApiResourceBuilder\Mobyt\MobytUserStatusBuilder;
+use JsonException;
+use RuntimeException;
 
 /**
  * Custom provider pour les MobytUserStatus récupérés via l'api Mobyt
  * @package App\DataProvider\Utils
  */
-final class MobytUserStatusProvider implements ProviderInterface
+final readonly class MobytUserStatusProvider implements ProviderInterface
 {
     public function __construct(
         private MobytUserStatusBuilder $mobytUserStatusCreator,
     )
     {}
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return MobytUserStatus|null
+     * @throws JsonException
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?MobytUserStatus
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
-        return $this->mobytUserStatusCreator->getUserStatus($uriVariables['id']);
+        return $this->mobytUserStatusCreator->getUserStatus((int) $uriVariables['id']);
     }
 }

+ 33 - 3
src/State/Provider/Utils/GpsCoordinateSearchingProvider.php

@@ -10,13 +10,18 @@ use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Utils\GpsCoordinate;
 use App\Service\Utils\GpsCoordinateUtils;
+use Exception;
 use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 
 /**
  * Class GpsCoordinateSearchingProvider : custom provider pour assurer l'alimentation de la ressource GpsCoordinate
  * @package App\DataProvider\Utils
  */
-final class GpsCoordinateSearchingProvider implements ProviderInterface
+final readonly class GpsCoordinateSearchingProvider implements ProviderInterface
 {
     public function __construct(
         private GpsCoordinateUtils $gpsCoordinateUtils,
@@ -24,6 +29,16 @@ final class GpsCoordinateSearchingProvider implements ProviderInterface
     )
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return GpsCoordinate[]|GpsCoordinate
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): array | GpsCoordinate
     {
         if($operation instanceof GetCollection) {
@@ -32,6 +47,13 @@ final class GpsCoordinateSearchingProvider implements ProviderInterface
         return $this->getItem($uriVariables['id']);
     }
 
+    /**
+     * @return GpsCoordinate[]
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
+     */
     public function getCollection(): array
     {
         $request = $this->requestStack->getCurrentRequest();
@@ -47,19 +69,27 @@ final class GpsCoordinateSearchingProvider implements ProviderInterface
                     $responses[] = $this->gpsCoordinateUtils->createGpsCoordinate($address);
                 }
             }
-        }catch (\Exception $exception){
+        }catch (Exception){
             $responses[] = new GpsCoordinate();
         }
         return $responses;
     }
 
+    /**
+     * @param string $id
+     * @return GpsCoordinate
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
+     */
     public function getItem(string $id): GpsCoordinate
     {
         $ids = CompositeIdentifierParser::parse($id);
         try{
             $address = $this->gpsCoordinateUtils->reverseGpsCoordinates((float) $ids['latitude'], (float) $ids['longitude']);
             $gpsCoordinateResponse = $this->gpsCoordinateUtils->createGpsCoordinate($address);
-        }catch (\Exception $exception){
+        }catch (Exception){
             $gpsCoordinateResponse = new GpsCoordinate();
         }
         return $gpsCoordinateResponse;

+ 17 - 2
src/State/Provider/Utils/SiretProvider.php

@@ -8,22 +8,37 @@ use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Utils\Siret;
 use App\Service\Utils\Siret as SiretUtils;
+use RuntimeException;
+use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 
 /**
  * Class SiretProvider : custom provider pour assurer l'alimentation des utils Siret
  * @package App\DataProvider\Utils
  */
-final class SiretProvider implements ProviderInterface
+final readonly class SiretProvider implements ProviderInterface
 {
     public function __construct(
         private SiretUtils $siretUtils
     )
     { }
 
+    /**
+     * @param Operation $operation
+     * @param mixed[] $uriVariables
+     * @param mixed[] $context
+     * @return Siret|null
+     * @throws ClientExceptionInterface
+     * @throws RedirectionExceptionInterface
+     * @throws ServerExceptionInterface
+     * @throws TransportExceptionInterface
+     */
     public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Siret
     {
         if($operation instanceof GetCollection) {
-            throw new \RuntimeException('not supported', 500);
+            throw new RuntimeException('not supported', 500);
         }
 
         $id = $uriVariables['id'];

+ 2 - 1
src/Validator/Core/ContactPoint.php

@@ -3,9 +3,10 @@ declare(strict_types=1);
 
 namespace App\Validator\Core;
 
+use Attribute;
 use Symfony\Component\Validator\Constraint;
 
-#[\Attribute]
+#[Attribute]
 class ContactPoint extends Constraint
 {
     public string $message = '{{ type }}_non_unique';

+ 7 - 4
src/Validator/Core/ContactPointValidator.php

@@ -14,7 +14,7 @@ use App\Entity\Core\ContactPoint;
  */
 class ContactPointValidator extends ConstraintValidator
 {
-    public function __construct(private ContactPointRepository $contactPointRepository){}
+    public function __construct(private readonly ContactPointRepository $contactPointRepository){}
 
     public function validate(mixed $value, Constraint $constraint): bool
     {
@@ -22,14 +22,17 @@ class ContactPointValidator extends ConstraintValidator
         $contactPoint = $value;
 
         // si le type est autre, on valide
-        if($contactPoint->getContactType() === ContactPointTypeEnum::OTHER()->getValue())
+        if($contactPoint->getContactType() === ContactPointTypeEnum::OTHER()->getValue()) {
             return true;
+        }
 
         $contactPointByType = [];
-        if(!$contactPoint->getOrganization()->isEmpty())
+        if(!$contactPoint->getOrganization()->isEmpty()) {
             $contactPointByType = $this->contactPointRepository->getByTypeAndOrganization($contactPoint->getContactType(), $contactPoint->getOrganization()->first());
-        else if(!$contactPoint->getPerson()->isEmpty())
+        }
+        else if(!$contactPoint->getPerson()->isEmpty()) {
             $contactPointByType = $this->contactPointRepository->getByTypeAndPerson($contactPoint->getContactType(), $contactPoint->getPerson()->first());
+        }
 
         //Si le nombre de point de contact du type est supérieur à 1, OU si le nombre est égale a 1 ET que l'id du point de contact n'est pas celui en cours : invalide.
         if(count($contactPointByType) > 1 || (count($contactPointByType) === 1 && $contactPointByType[0]->getId() !== $contactPoint->getId())){

+ 2 - 1
src/Validator/Organization/OrganizationAddressPostal.php

@@ -3,9 +3,10 @@ declare(strict_types=1);
 
 namespace App\Validator\Organization;
 
+use Attribute;
 use Symfony\Component\Validator\Constraint;
 
-#[\Attribute]
+#[Attribute]
 class OrganizationAddressPostal extends Constraint
 {
     public string $message = '{{ type }}_non_unique';

+ 3 - 2
src/Validator/Organization/OrganizationAddressPostalValidator.php

@@ -14,7 +14,7 @@ use App\Entity\Organization\OrganizationAddressPostal;
  */
 class OrganizationAddressPostalValidator extends ConstraintValidator
 {
-    public function __construct(private OrganizationAddressPostalRepository $organizationAddressPostalRepository){}
+    public function __construct(private readonly OrganizationAddressPostalRepository $organizationAddressPostalRepository){}
 
     public function validate(mixed $value, Constraint $constraint): bool
     {
@@ -22,8 +22,9 @@ class OrganizationAddressPostalValidator extends ConstraintValidator
         $organizationAddressPostal = $value;
 
         // si le type est adresse autre, on valide
-        if($organizationAddressPostal->getType() === AddressPostalOrganizationTypeEnum::ADDRESS_OTHER()->getValue())
+        if($organizationAddressPostal->getType() === AddressPostalOrganizationTypeEnum::ADDRESS_OTHER()->getValue()) {
             return true;
+        }
 
         $addressesByType = $this->organizationAddressPostalRepository->getByType($organizationAddressPostal->getType(), $organizationAddressPostal->getOrganization());
         //Si le nombre d'adress du type est supérieur à 1, OU si le nombre est égale a 1 ET que l'id de l'adresse n'est pas celui en cours : invalide.

+ 5 - 3
src/Validator/Organization/Parameters/MobytCredentialsValidator.php

@@ -5,6 +5,7 @@ namespace App\Validator\Organization\Parameters;
 
 use App\Entity\Organization\Parameters;
 use App\Service\Mobyt\MobytService;
+use Exception;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
@@ -13,7 +14,7 @@ use Symfony\Component\Validator\ConstraintValidator;
  */
 class MobytCredentialsValidator extends ConstraintValidator
 {
-    public function __construct(private MobytService $mobytService){}
+    public function __construct(private readonly MobytService $mobytService){}
 
     public function validate(mixed $value, Constraint $constraint): bool
     {
@@ -23,12 +24,13 @@ class MobytCredentialsValidator extends ConstraintValidator
         $userNameSms = $parameters->getUsernameSMS();
         $passwordSms = $parameters->getPasswordSMS();
 
-        if(empty($userNameSms) || empty($passwordSms))
+        if(empty($userNameSms) || empty($passwordSms)) {
             return true;
+        }
 
         try{
             return $this->mobytService->hasCredentialsCorrect($userNameSms, $passwordSms);
-        }catch (\Exception $exception){
+        }catch (Exception){
             $this->context->buildViolation($constraint->payload)
                 ->atPath('passwordSMS')
                 ->addViolation();

+ 2 - 1
tests/Service/Export/LicenceCmfExporterTest.php

@@ -10,6 +10,7 @@ use App\Entity\Network\NetworkOrganization;
 use App\Entity\Organization\Organization;
 use App\Entity\Organization\Parameters;
 use App\Entity\Person\Person;
+use App\Enum\Access\FunctionEnum;
 use App\Repository\Access\AccessRepository;
 use App\Repository\Organization\OrganizationRepository;
 use App\Service\Export\Encoder\PdfEncoder;
@@ -130,7 +131,7 @@ class LicenceCmfExporterTest extends TestCase
         $this->accessRepo
             ->expects(self::once())
             ->method('findByOrganizationAndMission')
-            ->with($this->organization, 'PRESIDENT')
+            ->with($this->organization, FunctionEnum::PRESIDENT()->getValue())
             ->willReturn([$this->presidentAccess]);
         $this->presidentAccess->method('getPerson')->willReturn($this->president);
         $this->cmf->method('getParameters')->willReturn($this->cmfParameters);

+ 2 - 2
tests/Service/Network/UtilsTest.php

@@ -203,7 +203,7 @@ class UtilsTest extends TestCase
 
         $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock();
         $networkOrganization
-            ->expects(self::once())
+            ->expects(self::exactly(2))
             ->method('getStartDate')
             ->willReturn($date1);
 
@@ -235,7 +235,7 @@ class UtilsTest extends TestCase
 
         $networkOrganization = $this->getMockBuilder(NetworkOrganization::class)->getMock();
         $networkOrganization
-            ->expects(self::once())
+            ->expects(self::exactly(2))
             ->method('getStartDate')
             ->willReturn($date1);
 

+ 3 - 3
tests/Service/ServiceIterator/CurrentAccessExtensionIteratorTest.php

@@ -22,15 +22,15 @@ class CurrentAccessExtensionIteratorTest extends TestCase
 
         $ext1 = $mocker->getMock();
         $ext1->method('support')->willReturn(false);
-        $ext1->expects($this->never())->method('addWhere')->with($queryBuilder)->willReturn(true);
+        $ext1->expects($this->never())->method('addWhere')->with($queryBuilder);
 
         $ext2 = $mocker->getMock();
         $ext2->method('support')->with('foo')->willReturn(true);
-        $ext2->expects($this->once())->method('addWhere')->with($queryBuilder)->willReturn(true);
+        $ext2->expects($this->once())->method('addWhere')->with($queryBuilder);
 
         $ext3 = $mocker->getMock();
         $ext3->method('support')->willReturn(false);
-        $ext1->expects($this->never())->method('addWhere')->with($queryBuilder)->willReturn(true);
+        $ext1->expects($this->never())->method('addWhere')->with($queryBuilder);
 
         $extensions = [$ext1, $ext2, $ext3];