Browse Source

Merge branch 'release/2.4.2'

Vincent 11 months ago
parent
commit
83adbca71b
100 changed files with 536 additions and 274 deletions
  1. 5 0
      .gitignore
  2. 61 0
      application_tests.sh
  3. 4 3
      composer.json
  4. 8 0
      config/opentalent/modulesbyconditions.yaml
  5. 1 0
      config/opentalent/products.yaml
  6. 1 1
      config/packages/framework.yaml
  7. 2 2
      config/packages/knp_gaufrette.yaml
  8. 3 0
      config/packages/security.yaml
  9. 11 2
      config/services.yaml
  10. 2 2
      doc/security.md
  11. 1 0
      env/.env.docker
  12. 6 3
      env/.env.staging
  13. 10 10
      old/Entity/Education/Cycle.php
  14. 1 1
      old/Entity/Education/EducationTiming.php
  15. 3 2
      phpunit.xml.dist
  16. 17 0
      src/ApiResources/Profile/AccessProfile.php
  17. 1 1
      src/Attribute/ActivityYearConstraintAware.php
  18. 1 1
      src/Attribute/DateTimeConstraintAware.php
  19. 1 1
      src/Commands/AddSubdomainCommand.php
  20. 6 2
      src/Doctrine/Access/AdditionalExtension/DateTimeConstraintExtensionAdditional.php
  21. 22 11
      src/Doctrine/Access/CurrentAccessExtension.php
  22. 5 1
      src/Doctrine/Access/CurrentUserPersonalizedListExtension.php
  23. 3 0
      src/Doctrine/Billing/CurrentResidenceAreaExtension.php
  24. 3 0
      src/Doctrine/Booking/AttendanceBookingReasonExtension.php
  25. 3 0
      src/Doctrine/Booking/CurrentCoursesExtension.php
  26. 11 3
      src/Doctrine/Core/AllowedAddressPostalExtension.php
  27. 3 0
      src/Doctrine/Core/CurrentUserNotificationExtension.php
  28. 3 0
      src/Doctrine/Core/CurrentUserNotificationUserExtension.php
  29. 3 0
      src/Doctrine/Education/CurrentCycleExtension.php
  30. 3 0
      src/Doctrine/Education/CurrentEducationNotationConfigExtension.php
  31. 3 0
      src/Doctrine/Education/CurrentEducationTimingExtension.php
  32. 3 0
      src/Doctrine/Network/CurrentNetworkOrganizationExtension.php
  33. 4 4
      src/Doctrine/ORM/AST/SphericalDistance.php
  34. 3 0
      src/Doctrine/Organization/CurrentOrganizationExtension.php
  35. 3 0
      src/Doctrine/Organization/CurrentParentOrganizationExtension.php
  36. 18 0
      src/Entity/Access/Access.php
  37. 70 0
      src/Entity/Access/Preferences.php
  38. 1 1
      src/Entity/Education/Cycle.php
  39. 11 6
      src/Entity/Education/EducationTiming.php
  40. 0 59
      src/Entity/Place/Room.php
  41. 3 0
      src/Entity/Public/PublicEvent.php
  42. 52 38
      src/Enum/Cotisation/TypeOfPracticeEnum.php
  43. 1 1
      src/EventSubscriber/ElasticaPostTransformSubscriber.php
  44. 1 1
      src/Filter/ApiPlatform/Utils/ArrayFieldFilter.php
  45. 1 1
      src/Message/Command/Export.php
  46. 1 1
      src/Message/Command/MailerCommand.php
  47. 1 1
      src/Message/Command/Typo3/Typo3DeleteCommand.php
  48. 1 1
      src/Message/Command/Typo3/Typo3UndeleteCommand.php
  49. 1 1
      src/Message/Command/Typo3/Typo3UpdateCommand.php
  50. 1 1
      src/Message/Handler/ExportHandler.php
  51. 1 1
      src/Message/Handler/MailerHandler.php
  52. 1 1
      src/Message/Handler/Typo3/Typo3DeleteCommandHandler.php
  53. 1 1
      src/Message/Handler/Typo3/Typo3UndeleteCommandHandler.php
  54. 1 1
      src/Message/Handler/Typo3/Typo3UpdateCommandHandler.php
  55. 1 1
      src/Repository/Access/AccessRepository.php
  56. 1 1
      src/Repository/Booking/CourseRepository.php
  57. 1 1
      src/Repository/Education/EducationNotationRepository.php
  58. 5 0
      src/Repository/Person/PersonRepository.php
  59. 1 1
      src/Security/Voter/EntityVoter/AbstractEntityVoter.php
  60. 1 1
      src/Serializer/AccessContextBuilder.php
  61. 1 1
      src/Serializer/DefaultNormalizer.php
  62. 24 3
      src/Service/Access/AccessProfileCreator.php
  63. 1 1
      src/Service/Access/AdminAccessUtils.php
  64. 1 1
      src/Service/Access/OptionalsRoles/CriteriaNotationOptionalRole.php
  65. 1 1
      src/Service/Access/Utils.php
  66. 2 2
      src/Service/ApiLegacy/ApiLegacyRequestService.php
  67. 1 1
      src/Service/Constraint/ActivityYearConstraint.php
  68. 1 1
      src/Service/Constraint/DateTimeConstraint.php
  69. 1 1
      src/Service/Cotisation/CotisationCreator.php
  70. 1 1
      src/Service/Cotisation/Utils.php
  71. 1 1
      src/Service/Cron/Job/CleanDb.php
  72. 1 1
      src/Service/Cron/Job/CleanTempFiles.php
  73. 1 1
      src/Service/Cron/Job/DolibarrSync.php
  74. 1 1
      src/Service/Cron/UI/ConsoleUI.php
  75. 1 1
      src/Service/Doctrine/FiltersConfigurationService.php
  76. 2 2
      src/Service/Dolibarr/DolibarrSyncService.php
  77. 23 9
      src/Service/Export/Encoder/DocXEncoder.php
  78. 26 34
      src/Service/Export/Encoder/PdfEncoder.php
  79. 1 1
      src/Service/Export/LicenceCmfExporter.php
  80. 1 1
      src/Service/File/Factory/ImageFactory.php
  81. 3 3
      src/Service/File/FileManager.php
  82. 6 2
      src/Service/File/Storage/ApiLegacyStorage.php
  83. 5 5
      src/Service/File/Storage/LocalStorage.php
  84. 1 1
      src/Service/Mailer/Builder/OnSubdomainChangeMailBuilder.php
  85. 1 1
      src/Service/Mailer/Mailer.php
  86. 1 1
      src/Service/MercureHub.php
  87. 1 1
      src/Service/Mobyt/MobytService.php
  88. 7 7
      src/Service/Notifier.php
  89. 1 1
      src/Service/OnChange/OnChangeContext.php
  90. 1 1
      src/Service/OnChange/Organization/OnParametersChange.php
  91. 1 1
      src/Service/OnlineRegistration/RegistrationStatusService.php
  92. 1 1
      src/Service/Organization/OrganizationProfileCreator.php
  93. 10 5
      src/Service/Organization/Utils.php
  94. 1 1
      src/Service/Rest/ApiRequestInterface.php
  95. 2 2
      src/Service/Rest/ApiRequestService.php
  96. 1 1
      src/Service/Rest/Operation/BaseRestOperation.php
  97. 1 1
      src/Service/Rest/Operation/CreateOperation.php
  98. 1 1
      src/Service/Rest/Operation/DeleteOperation.php
  99. 1 1
      src/Service/Rest/Operation/UpdateOperation.php
  100. 1 1
      src/Service/Security/InternalRequestsService.php

+ 5 - 0
.gitignore

@@ -57,4 +57,9 @@ phpstan.json
 /.php-cs-fixer.cache
 ###< friendsofphp/php-cs-fixer ###
 
+
+###> fake database for applications tests ###
+opentalent_test.sql
+###< fake database for applications tests ###
+
 .php-cs-fixer.cache

+ 61 - 0
application_tests.sh

@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# Configuration des paramètres de la base de données
+DB_USER="root"
+DB_PASSWORD="mysql660"
+DB_HOST="127.0.0.1"
+DB_PORT="3306"
+DB_NAME="opentalent"
+DB_TEST_NAME="opentalent_test"
+MARIADB_CONTAINER="mariaDb"
+
+# Fonction pour réinitialiser la base de données de test
+reset_test_database() {
+    echo "Dropping test database if it exists..."
+    docker exec $MARIADB_CONTAINER mysql --user=$DB_USER --password=$DB_PASSWORD --host=$DB_HOST --port=$DB_PORT -e "DROP DATABASE IF EXISTS $DB_TEST_NAME;"
+
+    echo "Dumping schema from the main database..."
+    docker exec $MARIADB_CONTAINER mysqldump --user=$DB_USER --password=$DB_PASSWORD --host=$DB_HOST --port=$DB_PORT --default-character-set=utf8 --single-transaction=TRUE --no-data --skip-triggers "$DB_NAME" | sed 's/ AUTO_INCREMENT=[0-9]*//g' > opentalent_test.sql
+
+    echo "Creating test database..."
+    docker exec $MARIADB_CONTAINER mysql --user=$DB_USER --password=$DB_PASSWORD --host=$DB_HOST --port=$DB_PORT -e "CREATE DATABASE $DB_TEST_NAME;"
+
+    echo "Importing schema into the test database..."
+    docker exec -i $MARIADB_CONTAINER mysql --user=$DB_USER --password=$DB_PASSWORD --host=$DB_HOST --port=$DB_PORT -D $DB_TEST_NAME < opentalent_test.sql
+
+    echo "Database setup completed."
+}
+
+# Réinitialiser la base de données de test
+reset_test_database
+
+total_tests=0
+passed_tests=0
+failed_tests=0
+
+for test_file in $(find tests/Application -name "*Test.php"); do
+    echo "Running test: $test_file"
+    php bin/phpunit $test_file
+    result=$?
+
+    total_tests=$((total_tests + 1))
+    if [ $result -ne 0 ]; then
+        echo "Test failed: $test_file"
+        failed_tests=$((failed_tests + 1))
+    else
+        passed_tests=$((passed_tests + 1))
+    fi
+done
+
+echo "===================================="
+echo "Test Summary:"
+echo "Total tests run: $total_tests"
+echo "Tests passed: $passed_tests"
+echo "Tests failed: $failed_tests"
+echo "===================================="
+
+if [ $failed_tests -ne 0 ]; then
+    exit 1
+else
+    exit 0
+fi

+ 4 - 3
composer.json

@@ -8,7 +8,7 @@
     },
     {
       "type": "vcs",
-      "url": "ssh://git@gitlab.2iopenservice.com/opentalent/phpdocx.git"
+      "url": "ssh://git@gitlab.2iopenservice.com/opentalent/phpdocx-15.5.git"
     }
   ],
   "require": {
@@ -23,6 +23,7 @@
     "doctrine/doctrine-bundle": "^2.1",
     "doctrine/doctrine-migrations-bundle": "^3.0",
     "doctrine/orm": "^2.17",
+    "dompdf/dompdf": "^3.0",
     "egulias/email-validator": "^3.0",
     "jbouzekri/phumbor-bundle": "^3.1.0",
     "knplabs/knp-gaufrette-bundle": "^0.8.0",
@@ -36,6 +37,7 @@
     "odolbeau/phone-number-bundle": "^3.1",
     "opentalent/phpdocx": "dev-master",
     "phpdocumentor/reflection-docblock": "^5.2",
+    "phpstan/phpdoc-parser": "^1.0",
     "ramsey/uuid": "^4.2",
     "ramsey/uuid-doctrine": "^2.0",
     "symfony/asset": "6.3.*",
@@ -113,8 +115,7 @@
       "App\\": "src/"
     },
     "classmap": [
-      "vendor/opentalent/phpdocx/Classes/Phpdocx/Create/CreateDocx.php",
-      "vendor/opentalent/phpdocx/Classes/Phpdocx/Create/CreateDocxFromTemplate.php"
+      "vendor/opentalent/phpdocx/Classes/Phpdocx"
     ]
   },
   "autoload-dev": {

+ 8 - 0
config/opentalent/modulesbyconditions.yaml

@@ -75,6 +75,14 @@ parameters:
                 service:
                     name: App\Service\Organization\Utils
                     function: isManagerAndCMF
+
+        Basicompta:
+            roles:
+                - ROLE_BASICOMPTA
+            conditions:
+                service:
+                    name: App\Service\Network\Utils
+                    function: isCMF
         Network:
             conditions:
                 service:

+ 1 - 0
config/opentalent/products.yaml

@@ -3,6 +3,7 @@ parameters:
       Core:
         entities:
           - AccessProfile
+          - Preferences
           - Tips
           - Notification
           - NotificationUser

+ 1 - 1
config/packages/framework.yaml

@@ -21,7 +21,7 @@ framework:
     http_client:
         scoped_clients:
             siret_checking:
-                base_uri: 'https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/'
+                base_uri: 'https://api.gouv.fr/api/v1/proxy/sirene_v3/'
             openstreetmap:
                 base_uri: 'https://nominatim.openstreetmap.org/'
             dolibarr_client:

+ 2 - 2
config/packages/knp_gaufrette.yaml

@@ -4,10 +4,10 @@ knp_gaufrette:
   adapters:
     storage:
       local:
-        directory: '%kernel.project_dir%/storage'
+        directory: '%kernel.project_dir%/var/files/storage'
         create: true
   filesystems:
     storage:
       adapter: storage
 
-  stream_wrapper: ~
+  stream_wrapper: ~

+ 3 - 0
config/packages/security.yaml

@@ -26,6 +26,7 @@ security:
             - ROLE_STATISTIC
             - ROLE_ADMIN_CORE
             - ROLE_REWARD
+            - ROLE_BASICOMPTA
 
         ROLE_ADMIN_CORE: *BASE_ROLE_ADMINISTRATION_CORE
 
@@ -44,6 +45,7 @@ security:
             - ROLE_COTISATION
             - ROLE_ONLINEREGISTRATION_ADMINISTRATION
             - ROLE_ADMINISTRATIF_MANAGER_CORE
+            - ROLE_BASICOMPTA
 
         ROLE_ADMINISTRATIF_MANAGER_CORE: *BASE_ROLE_ADMINISTRATION_CORE
 
@@ -72,6 +74,7 @@ security:
             - ROLE_BILLINGS_ADMINISTRATION
             - ROLE_BILLINGS_SEIZURE
             - ROLE_FINANCIAL_MANAGER_CORE
+            - ROLE_BASICOMPTA
 
         ROLE_FINANCIAL_MANAGER_CORE:
             - ROLE_MEMBER_CORE

+ 11 - 2
config/services.yaml

@@ -21,8 +21,10 @@ services:
             $persistProcessor: '@api_platform.doctrine.orm.state.persist_processor'
             $removeProcessor: '@api_platform.doctrine.orm.state.remove_processor'
             $opentalentNoReplyEmailAddress: 'noreply@opentalent.fr'
-            $legacyBaseUrl: '%env(PUBLIC_API_LEG_BASE_URL)%'
-            $baseUrl: '%env(PUBLIC_API_BASE_URL)%'
+            $legacyBaseUrl: '%env(API_LEG_BASE_URL)%'
+            $publicLegacyBaseUrl: '%env(PUBLIC_API_LEG_BASE_URL)%'
+            $baseUrl: '%env(API_BASE_URL)%'
+            $publicBaseUrl: '%env(PUBLIC_API_BASE_URL)%'
 
     # makes classes in src/ available to be used as services
     # this creates a service per class whose id is the fully-qualified class name
@@ -48,6 +50,13 @@ services:
     App\Service\Network\Utils:
         public: true
 
+    Phpdocx\Create\CreateDocx:
+        class: Phpdocx\Create\CreateDocx
+
+#    App\Service\Export\Encoder\PdfEncoder:
+#        arguments:
+#            $phpDocx: '@Phpdocx\Create\CreateDocx'
+
     App\Service\Organization\Utils:
         public: true
 

+ 2 - 2
doc/security.md

@@ -88,11 +88,11 @@ Les voters permettent de contrôler l'accès à certaines ressources, selon le t
 
 Ils implémentent essentiellement deux méthodes : `supports` et `voteOnAttribute` qui prennent en paramètres la ressource 
 et le type d'opération. `supports` retourne `true` si le voter doit s'appliquer dans ce cas. Si oui, `voteOnAttribute`
-est appellée et retourne `true` si l'opération est autorisée.
+est appelée et retourne `true` si l'opération est autorisée.
 
 > TODO: quand faut-il retourner false et quand faut-il lever une AccessDeniedHttpException ?
 
-Pour qu'un Voter soit appellé, il faut configurer la sécurité de la ressource via son annotation et utiliser la méthode 
+Pour qu'un Voter soit appelé, il faut configurer la sécurité de la ressource via son annotation et utiliser la méthode 
 `is_granted` combinée à une des constantes : 
 
 Exemple : 

+ 1 - 0
env/.env.docker

@@ -1,6 +1,7 @@
 ###> symfony/framework-bundle ###
 APP_ENV=dev
 APP_DEBUG=1
+APP_SECRET=211cede3dc4b162da3ec2fbdcd905070
 ###< symfony/framework-bundle ###
 
 ###> nelmio/cors-bundle ###

+ 6 - 3
env/.env.staging

@@ -1,7 +1,9 @@
-# Fichier d'env utilisé pour les tests fonctionnels et applicatifs
 APP_ENV=staging
-APP_DEBUG=1
-
+DATABASE_AUDIT_URL='mysql://root:mysql660@db:3306/audit?serverVersion=5.7'
+DATABASE_ADMINASSOS_URL='mysql://root:mysql660@db:3306/adminassos?serverVersion=5.7'
+DATABASE_URL='mysql://root:mysql660@db:3306/opentalent_test?serverVersion=5.7'
+DOLIBARR_API_TOKEN='Bocc4zC0J186v8J6QCqu7DnoIw4I7mCJ'
+MERCURE_JWT_SECRET='TXsLVKnU4Ew4oyH4qcQO81CuSOVTbj58W42fDTIzIZPwpPCaGu2EvIL3DbtDWtKHIGR6vvL98lnYlOADCB6buOvvfv30HL92OaBhB6jkyVnACipg7W4KQVRnQifiz3WymMnQYiprsBT9gyvRMTyhDHVDGaKrpgD1Y1j1pTR2JON9SSMHYTHsx6g7S7rKydgWEuNq4Jq2nldtYXXTYVRyZ2qKy5uGWfya2ahHsWGWTbz5UOkwN3b48fXpURSsMze4'
 ###> nelmio/cors-bundle ###
 CORS_ALLOW_ORIGIN=^$
 ###< nelmio/cors-bundle ###
@@ -33,3 +35,4 @@ INTERNAL_FILES_DOWNLOAD_URI=https://none
 LOG_FILE_NAME=staging
 ###< filename log ###
 
+

+ 10 - 10
old/Entity/Education/Cycle.php

@@ -45,10 +45,10 @@ class Cycle
     /**
      * @var integer
      */
-    #[ORM\Column(name: '`order`', type: 'integer', nullable: true)]
+    #[ORM\Column(name: 'cycle_order', type: 'integer', nullable: true)]
     #[Assert\Type(type: 'integer', message: 'invalid-integer')]
     #[Groups(['cycle'])]
-    private $order;
+    private $cycleOrder;
     /**
      * @var string
      */
@@ -75,7 +75,7 @@ class Cycle
     /**
      * @var ArrayCollection<CycleByEducation>
      */
-    #[ORM\OneToMany(targetEntity: 'AppBundle\Entity\Education\CycleByEducation', mappedBy: 'cycle', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: 'AppBundle\Entity\Education\CycleByEducation', mappedBy: 'cycle', orphanRemoval: true, persist: true, cascade: ['persist', 'remove'])]
     #[Groups(['cycle_cyclebyeducation'])]
     private $cycleByEducations;
     /**
@@ -130,26 +130,26 @@ class Cycle
         return $this->organization;
     }
     /**
-     * Sets order.
+     * Sets cycle order.
      *
-     * @param integer $order
+     * @param integer $cycleOrder
      *
      * @return $this
      */
-    public function setOrder($order)
+    public function setCycleOrder($cycleOrder)
     {
-        $this->order = $order;
+        $this->cycleOrder = $cycleOrder;
 
         return $this;
     }
     /**
-     * Gets order.
+     * Gets cycle order.
      *
      * @return integer
      */
-    public function getOrder()
+    public function getCycleOrder()
     {
-        return $this->order;
+        return $this->cycleOrder;
     }
     /**
      * Sets label.

+ 1 - 1
old/Entity/Education/EducationTiming.php

@@ -52,7 +52,7 @@ class EducationTiming
     /**
      * @var Education
      */
-    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\Education\EducationCurriculum', mappedBy: 'educationTimings')]
+    #[ORM\ManyToMany(targetEntity: 'AppBundle\Entity\Education\EducationCurriculum', mappedBy: 'educationTimings', cascade: ['persist'])]
     #[Groups(['educationtiming_reference'])]
     private $educationCurriculums;
     /**

+ 3 - 2
phpunit.xml.dist

@@ -6,7 +6,7 @@
         backupGlobals="false"
         colors="true"
         bootstrap="tests/bootstrap.php"
-        defaultTestSuite="unit"
+        defaultTestSuite="application"
 >
   <coverage includeUncoveredFiles="true">
     <include>
@@ -18,12 +18,13 @@
     </report>
   </coverage>
   <php>
-    <ini name="error_reporting" value="-1"/>
+    <ini name="error_reporting" value="E_ALL &amp; ~E_DEPRECATED &amp; ~E_USER_DEPRECATED"/>
     <server name="APP_ENV" value="staging" force="true"/>
     <server name="SHELL_VERBOSITY" value="-1"/>
     <server name="SYMFONY_PHPUNIT_REMOVE" value=""/>
     <server name="SYMFONY_PHPUNIT_VERSION" value="9.4"/>
     <server name="KERNEL_CLASS" value="App\Kernel" />
+    <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled" />
   </php>
   <testsuites>
     <testsuite name="unit">

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

@@ -83,6 +83,9 @@ class AccessProfile implements ApiResourcesInterface
     #[Groups('access_profile_read')]
     private ?AccessProfile $originalAccess = null;
 
+    #[Groups('access_profile_read')]
+    private ?int $preferencesId = null;
+
     #[Pure]
     public function __construct()
     {
@@ -299,6 +302,7 @@ class AccessProfile implements ApiResourcesInterface
     }
 
     /**
+     * return required for PHP Stan
      * @return bool[]
      */
     public function getHistorical(): array
@@ -307,6 +311,7 @@ class AccessProfile implements ApiResourcesInterface
     }
 
     /**
+     * param require for PHP Stan
      * @param bool[] $historical
      *
      * @return $this
@@ -317,4 +322,16 @@ class AccessProfile implements ApiResourcesInterface
 
         return $this;
     }
+
+    public function getPreferencesId(): ?int
+    {
+        return $this->preferencesId;
+    }
+
+    public function setPreferencesId(?int $preferencesId): self
+    {
+        $this->preferencesId = $preferencesId;
+
+        return $this;
+    }
 }

+ 1 - 1
src/Attribute/ActivityYearConstraintAware.php

@@ -15,7 +15,7 @@ final class ActivityYearConstraintAware
 
     public function __construct(
         string $startYearFieldName,
-        string $endYearFieldName
+        string $endYearFieldName,
     ) {
         $this->startYearFieldName = $startYearFieldName;
         $this->endYearFieldName = $endYearFieldName;

+ 1 - 1
src/Attribute/DateTimeConstraintAware.php

@@ -15,7 +15,7 @@ final class DateTimeConstraintAware
 
     public function __construct(
         string $startDateFieldName,
-        string $endDateFieldName
+        string $endDateFieldName,
     ) {
         $this->startDateFieldName = $startDateFieldName;
         $this->endDateFieldName = $endDateFieldName;

+ 1 - 1
src/Commands/AddSubdomainCommand.php

@@ -19,7 +19,7 @@ class AddSubdomainCommand extends Command
 {
     public function __construct(
         private readonly OrganizationRepository $organizationRepository,
-        private readonly SubdomainService $subdomainService
+        private readonly SubdomainService $subdomainService,
     ) {
         parent::__construct();
     }

+ 6 - 2
src/Doctrine/Access/AdditionalExtension/DateTimeConstraintExtensionAdditional.php

@@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
 class DateTimeConstraintExtensionAdditional implements AdditionalAccessExtensionInterface
 {
     public function __construct(
-        private RequestStack $requestStack
+        private RequestStack $requestStack,
     ) {
     }
 
@@ -29,7 +29,11 @@ class DateTimeConstraintExtensionAdditional implements AdditionalAccessExtension
 
     public function addWhere(QueryBuilder $queryBuilder): void
     {
-        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $rootAliases = $queryBuilder->getRootAliases();
+        if (empty($rootAliases)) {
+            throw new \LogicException('No root alias defined.');
+        }
+        $rootAlias = $rootAliases[0];
         $queryBuilder->innerJoin(sprintf('%s.organizationFunction', $rootAlias), 'organization_function');
     }
 }

+ 22 - 11
src/Doctrine/Access/CurrentAccessExtension.php

@@ -18,7 +18,7 @@ final class CurrentAccessExtension extends AbstractExtension
 {
     public function __construct(
         private Security $security,
-        private CurrentAccessExtensionIterator $currentAccessExtensionIterator
+        private CurrentAccessExtensionIterator $currentAccessExtensionIterator,
     ) {
     }
 
@@ -27,16 +27,27 @@ final class CurrentAccessExtension extends AbstractExtension
         return $resourceClass === Access::class;
     }
 
-    public function addWhere(QueryBuilder $queryBuilder, string $resourceClass, ?Operation $operation): void
+    protected function addWhere(QueryBuilder $queryBuilder, string $resourceClass, ?Operation $operation): void
     {
-        /** @var Access $currentUser */
-        $currentUser = $this->security->getUser();
-        $rootAlias = $queryBuilder->getRootAliases()[0];
-        $queryBuilder
-            ->andWhere(sprintf('%s.organization = :current_organization', $rootAlias))
-            ->setParameter('current_organization', $currentUser->getOrganization())
-        ;
-
-        $this->currentAccessExtensionIterator->addWhere($queryBuilder, $operation?->getName());
+        $token = $this->security->getToken();
+        if ($token === null) {
+            return;
+        }
+        $currentUser = $token->getUser();
+        if (!$currentUser instanceof Access) {
+            return;
+        }
+        $organization = $currentUser->getOrganization();
+        $rootAliases = $queryBuilder->getRootAliases();
+        if (empty($rootAliases)) {
+            throw new \LogicException('No root alias defined.');
+        }
+
+        $rootAlias = $rootAliases[0];
+        $queryBuilder->andWhere(sprintf('%s.organization = :current_organization', $rootAlias));
+        $queryBuilder->setParameter('current_organization', $organization);
+
+        $operationName = $operation ? $operation->getName() : '';
+        $this->currentAccessExtensionIterator->addWhere($queryBuilder, $operationName);
     }
 }

+ 5 - 1
src/Doctrine/Access/CurrentUserPersonalizedListExtension.php

@@ -27,7 +27,11 @@ final class CurrentUserPersonalizedListExtension extends AbstractExtension
     protected function addWhere(QueryBuilder $queryBuilder, string $resourceClass, ?Operation $operation): void
     {
         $currentUser = $this->security->getUser();
-        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $rootAliases = $queryBuilder->getRootAliases();
+        if (empty($rootAliases)) {
+            throw new \LogicException('No root alias defined.');
+        }
+        $rootAlias = $rootAliases[0];
         $queryBuilder->andWhere(sprintf('%s.access = :current_access', $rootAlias));
         $queryBuilder->setParameter('current_access', $currentUser);
     }

+ 3 - 0
src/Doctrine/Billing/CurrentResidenceAreaExtension.php

@@ -29,6 +29,9 @@ final class CurrentResidenceAreaExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.billingSetting = :billingSetting', $rootAlias))

+ 3 - 0
src/Doctrine/Booking/AttendanceBookingReasonExtension.php

@@ -29,6 +29,9 @@ final class AttendanceBookingReasonExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

+ 3 - 0
src/Doctrine/Booking/CurrentCoursesExtension.php

@@ -32,6 +32,9 @@ final class CurrentCoursesExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.discr = :discr', $rootAlias))

+ 11 - 3
src/Doctrine/Core/AllowedAddressPostalExtension.php

@@ -29,11 +29,19 @@ final class AllowedAddressPostalExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
-        $rootAlias = $queryBuilder->getRootAliases()[0];
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
+
+        $rootAliases = $queryBuilder->getRootAliases();
+        if (empty($rootAliases)) {
+            throw new \LogicException('No root alias defined.');
+        }
+
+        $rootAlias = $rootAliases[0];
         $queryBuilder
             ->innerJoin(sprintf('%s.organizationAddressPostal', $rootAlias), 'organization_address_postal')
             ->andWhere('organization_address_postal.organization = :organization')
-            ->setParameter('organization', $currentUser->getOrganization())
-        ;
+            ->setParameter('organization', $currentUser->getOrganization());
     }
 }

+ 3 - 0
src/Doctrine/Core/CurrentUserNotificationExtension.php

@@ -32,6 +32,9 @@ final class CurrentUserNotificationExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.recipientAccess = :current_access', $rootAlias))

+ 3 - 0
src/Doctrine/Core/CurrentUserNotificationUserExtension.php

@@ -32,6 +32,9 @@ final class CurrentUserNotificationUserExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.access = :current_access', $rootAlias))

+ 3 - 0
src/Doctrine/Education/CurrentCycleExtension.php

@@ -29,6 +29,9 @@ final class CurrentCycleExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

+ 3 - 0
src/Doctrine/Education/CurrentEducationNotationConfigExtension.php

@@ -29,6 +29,9 @@ final class CurrentEducationNotationConfigExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

+ 3 - 0
src/Doctrine/Education/CurrentEducationTimingExtension.php

@@ -29,6 +29,9 @@ final class CurrentEducationTimingExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

+ 3 - 0
src/Doctrine/Network/CurrentNetworkOrganizationExtension.php

@@ -29,6 +29,9 @@ final class CurrentNetworkOrganizationExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

+ 4 - 4
src/Doctrine/ORM/AST/SphericalDistance.php

@@ -28,10 +28,10 @@ use Doctrine\ORM\Query\SqlWalker;
  */
 class SphericalDistance extends FunctionNode
 {
-    private Node|string $latitude1;
-    private Node|string $longitude1;
-    private Node|string $latitude2;
-    private Node|string $longitude2;
+    protected Node|string $latitude1;
+    protected Node|string $longitude1;
+    protected Node|string $latitude2;
+    protected Node|string $longitude2;
 
     /**
      * Parse DQL Function.

+ 3 - 0
src/Doctrine/Organization/CurrentOrganizationExtension.php

@@ -29,6 +29,9 @@ final class CurrentOrganizationExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.id = :organization', $rootAlias))

+ 3 - 0
src/Doctrine/Organization/CurrentParentOrganizationExtension.php

@@ -32,6 +32,9 @@ final class CurrentParentOrganizationExtension extends AbstractExtension
     {
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
         $rootAlias = $queryBuilder->getRootAliases()[0];
         $queryBuilder
             ->andWhere(sprintf('%s.organization = :organization', $rootAlias))

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

@@ -300,6 +300,9 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
+    #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist'], fetch: 'EAGER', orphanRemoval: true)]
+    private ?Preferences $preferences;
+
     #[Pure]
     public function __construct()
     {
@@ -2138,4 +2141,19 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
+
+    public function setPreferences(?Preferences $preferences = null): self
+    {
+        if (!is_null($preferences)) {
+            $preferences->setAccess($this);
+        }
+        $this->preferences = $preferences;
+
+        return $this;
+    }
+
+    public function getPreferences(): ?Preferences
+    {
+        return $this->preferences;
+    }
 }

+ 70 - 0
src/Entity/Access/Preferences.php

@@ -0,0 +1,70 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Access;
+
+// use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use ApiPlatform\Metadata\Put;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Préférence pour un Access.
+ */
+// #[Auditable]
+#[ORM\Entity]
+#[ApiResource(
+    operations: [
+        new Get(
+            security: 'object.getAccess().getId() == user.getId()'
+        ),
+        new Put(
+            security: 'object.getAccess().getId() == user.getId()'
+        ),
+    ]
+)]
+class Preferences
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\OneToOne(inversedBy: 'preferences', fetch: 'EAGER')]
+    #[ORM\JoinColumn(nullable: true)]
+    private Access $access;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $messageReport = true;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getAccess(): ?Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getMessageReport(): ?bool
+    {
+        return $this->messageReport;
+    }
+
+    public function setMessageReport(bool $messageReport): self
+    {
+        $this->messageReport = $messageReport;
+
+        return $this;
+    }
+}

+ 1 - 1
src/Entity/Education/Cycle.php

@@ -50,7 +50,7 @@ class Cycle
     #[ORM\JoinColumn(nullable: false)]
     private Organization $organization;
 
-    #[ORM\Column(nullable: true)]
+    #[ORM\Column(name: '`order`', nullable: true)]
     private ?int $order = null;
 
     #[ORM\Column(length: 255)]

+ 11 - 6
src/Entity/Education/EducationTiming.php

@@ -28,21 +28,26 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(
     operations: [
         new Get(
-            security: 'is_granted("ROLE_ORGANIZATION_VIEW") and object.getOrganization().getId() == user.getOrganization().getId()'
+            security: 'is_granted(\'ROLE_ORGANIZATION_VIEW\') and object.getOrganization().getId() == user.getOrganization().getId()',
+            securityMessage: 'You do not have access to this course duration'
         ),
         new Put(
-            security: 'is_granted("ROLE_ORGANIZATION") and object.getOrganization().getId() == user.getOrganization().getId()'
+            security: 'object.getOrganization().getId() == user.getOrganization().getId()',
+            securityMessage: 'You do not have access to this course duration'
         ),
         new Delete(
-            security: 'is_granted("ROLE_ORGANIZATION") and object.getOrganization().getId() == user.getOrganization().getId()'
+            security: 'object.getOrganization().getId() == user.getOrganization().getId()',
+            securityMessage: 'You do not have access to this course duration'
         ),
         new GetCollection(
-            security: 'is_granted("ROLE_ORGANIZATION_VIEW")'
+            security: 'is_granted(\'ROLE_ORGANIZATION_VIEW\')',
+            securityMessage: 'You do not have access to this course duration'
         ),
         new Post(
-            security: 'is_granted("ROLE_ORGANIZATION")'
+            security: 'is_granted(\'ROLE_ORGANIZATION\')'
         ),
-    ]
+    ],
+    security: 'is_granted(\'ROLE_ORGANIZATION\')'
 )]
 // #[Auditable]
 #[OrganizationDefaultValue(fieldName: 'organization')]

+ 0 - 59
src/Entity/Place/Room.php

@@ -9,7 +9,6 @@ use App\Entity\Booking\Course;
 use App\Entity\Booking\EducationalProject;
 use App\Entity\Booking\Event;
 use App\Entity\Booking\Examen;
-use App\Entity\Core\ContactPoint;
 use App\Entity\Product\Equipment;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -32,14 +31,6 @@ class Room
     #[ORM\ManyToOne(targetEntity: Place::class, inversedBy: 'rooms')]
     private Place $place;
 
-    #[ORM\ManyToMany(targetEntity: ContactPoint::class)]
-    private Collection $contactpoint;
-
-    #[ORM\ManyToMany(targetEntity: Equipment::class, cascade: ['persist'])]
-    #[ORM\JoinColumn(name: 'room_id', referencedColumnName: 'id')]
-    #[ORM\InverseJoinColumn(name: 'equipment_id', referencedColumnName: 'id', unique: true)]
-    private Collection $equipments;
-
     #[ORM\OneToMany(mappedBy: 'room', targetEntity: RoomControl::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
     private Collection $controls;
@@ -68,8 +59,6 @@ class Room
 
     public function __construct()
     {
-        $this->contactpoint = new ArrayCollection();
-        $this->equipments = new ArrayCollection();
         $this->controls = new ArrayCollection();
         $this->repairs = new ArrayCollection();
         $this->courses = new ArrayCollection();
@@ -97,54 +86,6 @@ class Room
         return $this;
     }
 
-    /**
-     * @return Collection<int, ContactPoint>
-     */
-    public function getContactpoint(): Collection
-    {
-        return $this->contactpoint;
-    }
-
-    public function addContactpoint(ContactPoint $contactpoint): self
-    {
-        if (!$this->contactpoint->contains($contactpoint)) {
-            $this->contactpoint[] = $contactpoint;
-        }
-
-        return $this;
-    }
-
-    public function removeContactpoint(ContactPoint $contactpoint): self
-    {
-        $this->contactpoint->removeElement($contactpoint);
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Equipment>
-     */
-    public function getEquipments(): Collection
-    {
-        return $this->equipments;
-    }
-
-    public function addEquipment(Equipment $equipment): self
-    {
-        if (!$this->equipments->contains($equipment)) {
-            $this->equipments[] = $equipment;
-        }
-
-        return $this;
-    }
-
-    public function removeEquipment(Equipment $equipment): self
-    {
-        $this->equipments->removeElement($equipment);
-
-        return $this;
-    }
-
     /**
      * @return Collection<int, RoomControl>
      */

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

@@ -43,6 +43,7 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiFilter(filterClass: OrderFilter::class, properties: ['datetimeStart', 'datetimeEnd'], arguments: ['orderParameterName' => 'order'])]
 #[ApiFilter(filterClass: RangeFilter::class, properties: ['priceMini', 'priceMaxi'])]
 #[ApiFilter(filterClass: ArrayFieldFilter::class, properties: ['categories', 'gender'])]
+#[ApiFilter(filterClass: OrderFilter::class, properties: ['priceMini', 'priceMaxi'], arguments: ['orderParameterName' => 'price_order'])]
 class PublicEvent
 {
     #[ORM\Id]
@@ -351,6 +352,7 @@ class PublicEvent
     public function setStructureLongitude(?float $structureLongitude): self
     {
         $this->structureLongitude = $structureLongitude;
+
         return $this;
     }
 
@@ -362,6 +364,7 @@ class PublicEvent
     public function setStructureLatitude(?float $structureLatitude): self
     {
         $this->structureLatitude = $structureLatitude;
+
         return $this;
     }
 

+ 52 - 38
src/Enum/Cotisation/TypeOfPracticeEnum.php

@@ -13,42 +13,56 @@ enum TypeOfPracticeEnum: string
 {
     use EnumMethodsTrait;
 
-    case BATTERY_FANFARE = 'BATTERY_FANFARE';
-    case BIG_BAND = 'BIG_BAND';
-    case BRASS_BAND = 'BRASS_BAND';
-    case MIXED_CHORUS = 'MIXED_CHORUS';
-    case FEMAL_CHOIR = 'FEMAL_CHOIR';
-    case MENS_CHOIR = 'MENS_CHOIR';
-    case CHILDRENS_CHOIR = 'CHILDRENS_CHOIR';
-    case ORCHESTRA_enum = 'ORCHESTRA_enum';
-    case COPPER_BAND = 'COPPER_BAND';
-    case JAZZ_BAND = 'JAZZ_BAND';
-    case PERCUSSION_BAND = 'PERCUSSION_BAND';
-    case PLUCKED_ORCHESTRA = 'PLUCKED_ORCHESTRA';
-    case FOLKLORIC_BAND = 'FOLKLORIC_BAND';
-    case VOCAL_BAND_UP_16 = 'VOCAL_BAND_UP_16';
-    case FIFE_AND_DRUM = 'FIFE_AND_DRUM';
-    case CURRENT_MUSIC_GROUP = 'CURRENT_MUSIC_GROUP';
-    case CHAMBER_MUSIC_ENSEMBLE = 'CHAMBER_MUSIC_ENSEMBLE';
-    case TRADITIONAL_MUSIC_ENSEMBLE = 'TRADITIONAL_MUSIC_ENSEMBLE';
-    case VARIOUS_ORCHESTRA = 'VARIOUS_ORCHESTRA';
-    case ACCORDION_ORCHESTRA = 'ACCORDION_ORCHESTRA';
-    case HARMONY_ORCHESTRA = 'HARMONY_ORCHESTRA';
-    case FANFARE_BAND = 'FANFARE_BAND';
-    case SYMPHONY_ORCHESTRA = 'SYMPHONY_ORCHESTRA';
-    case VIOLIN_BAND = 'VIOLIN_BAND';
-    case SAXOPHONES_BAND = 'SAXOPHONES_BAND';
-    case HUNTING_HORNS = 'HUNTING_HORNS';
-    case STRING_ORCHESTRA = 'STRING_ORCHESTRA';
-    case FLUTE_ENSEMBLE = 'FLUTE_ENSEMBLE';
-    case CLARINET_CHOIR = 'CLARINET_CHOIR';
-    case PHILHARMONIC_ORCHESTRA = 'PHILHARMONIC_ORCHESTRA';
-    case BANDAS = 'BANDAS';
-    case BAGAD = 'BAGAD';
-    case BATTUCADA = 'BATTUCADA';
-    case MARCHING_BAND = 'MARCHING_BAND';
-    case EDUCATION = 'EDUCATION';
-    case CHEERLEADER = 'CHEERLEADER';
-    case TROOP = 'TROOP';
-    case OTHER = 'OTHER';
+    public const BATTERY_FANFARE = 'BATTERY_FANFARE';
+    public const BIG_BAND = 'BIG_BAND';
+    public const BRASS_BAND = 'BRASS_BAND';
+    public const MIXED_CHORUS = 'MIXED_CHORUS';
+    public const FEMAL_CHOIR = 'FEMAL_CHOIR';
+    public const MENS_CHOIR = 'MENS_CHOIR';
+    public const CHILDRENS_CHOIR = 'CHILDRENS_CHOIR';
+    public const ORCHESTRA_CLASS = 'ORCHESTRA_CLASS'; // Non
+    public const COPPER_BAND = 'COPPER_BAND';
+    public const JAZZ_BAND = 'JAZZ_BAND';
+    public const PERCUSSION_BAND = 'PERCUSSION_BAND';
+    public const PLUCKED_ORCHESTRA = 'PLUCKED_ORCHESTRA'; // Done
+    public const FOLKLORIC_BAND = 'FOLKLORIC_BAND';
+    public const VOCAL_BAND_UP_16 = 'VOCAL_BAND_UP_16';
+    public const FIFE_AND_DRUM = 'FIFE_AND_DRUM';
+    public const CURRENT_MUSIC_GROUP = 'CURRENT_MUSIC_GROUP';
+    public const CHAMBER_MUSIC_ENSEMBLE = 'CHAMBER_MUSIC_ENSEMBLE';
+    public const TRADITIONAL_MUSIC_ENSEMBLE = 'TRADITIONAL_MUSIC_ENSEMBLE';
+    public const VARIOUS_ORCHESTRA = 'VARIOUS_ORCHESTRA';
+    public const ACCORDION_ORCHESTRA = 'ACCORDION_ORCHESTRA';
+    public const HARMONY_ORCHESTRA = 'HARMONY_ORCHESTRA';
+    public const FANFARE_BAND = 'FANFARE_BAND';
+    public const SYMPHONY_ORCHESTRA = 'SYMPHONY_ORCHESTRA';
+    public const VIOLIN_BAND = 'VIOLIN_BAND';
+    public const SAXOPHONES_BAND = 'SAXOPHONES_BAND';
+    public const HUNTING_HORNS = 'HUNTING_HORNS';
+    public const STRING_ORCHESTRA = 'STRING_ORCHESTRA';
+    public const FLUTE_ENSEMBLE = 'FLUTE_ENSEMBLE';
+    public const CLARINET_CHOIR = 'CLARINET_CHOIR';
+    public const PHILHARMONIC_ORCHESTRA = 'PHILHARMONIC_ORCHESTRA';
+    public const BANDAS = 'BANDAS';
+    public const BAGAD = 'BAGAD';
+    public const BATTUCADA = 'BATTUCADA';
+    public const MARCHING_BAND = 'MARCHING_BAND';
+    public const EDUCATION = 'EDUCATION';
+    public const MAJORETTE_AND_TWIRLING = 'MAJORETTE_AND_TWIRLING';
+    public const TROOP = 'TROOP';
+    public const OTHER_TYPE = 'OTHER_TYPE';
+    public const COMPANIES = 'COMPANIES';
+    public const TAP_DANCE = 'TAP_DANCE';
+    public const CLASSICAL_DANCE = 'CLASSICAL_DANCE';
+    public const CONTEMPORARY_DANCE = 'CONTEMPORARY_DANCE';
+    public const BALLROOM_DANCE = 'BALLROOM_DANCE';
+    public const JAZZ_DANCE = 'JAZZ_DANCE';
+    public const FOLK_DANCE = 'FOLK_DANCE';
+    public const BREAK_DANCING = 'BREAK_DANCING';
+    public const LATIN_DANCE = 'LATIN_DANCE';
+    public const ART_TEACHING = 'ART_TEACHING';
+    public const CIRCUS_TRAINING = 'CIRCUS_TRAINING';
+    public const DANCE_LESSONS = 'DANCE_LESSONS';
+    public const MUSIC_TEACHING = 'MUSIC_TEACHING';
+    public const DRAMATIC_ARTS = 'DRAMATIC_ARTS';
 }

+ 1 - 1
src/EventSubscriber/ElasticaPostTransformSubscriber.php

@@ -17,7 +17,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 final class ElasticaPostTransformSubscriber implements EventSubscriberInterface
 {
     public function __construct(
-        private EducationNotationUtils $educationNotationUtils
+        private EducationNotationUtils $educationNotationUtils,
     ) {
     }
 

+ 1 - 1
src/Filter/ApiPlatform/Utils/ArrayFieldFilter.php

@@ -31,7 +31,7 @@ class ArrayFieldFilter extends AbstractFilter
         QueryNameGeneratorInterface $queryNameGenerator,
         string $resourceClass,
         ?Operation $operation = null,
-        array $context = []
+        array $context = [],
     ): void {
         if (!$this->isPropertyEnabled($property, $resourceClass)) {
             return;

+ 1 - 1
src/Message/Command/Export.php

@@ -12,7 +12,7 @@ use App\ApiResources\Export\ExportRequest;
 class Export
 {
     public function __construct(
-        private ExportRequest $exportRequest
+        private ExportRequest $exportRequest,
     ) {
     }
 

+ 1 - 1
src/Message/Command/MailerCommand.php

@@ -12,7 +12,7 @@ use App\Service\Mailer\Model\MailerModelInterface;
 class MailerCommand
 {
     public function __construct(
-        private MailerModelInterface $model
+        private MailerModelInterface $model,
     ) {
     }
 

+ 1 - 1
src/Message/Command/Typo3/Typo3DeleteCommand.php

@@ -10,7 +10,7 @@ namespace App\Message\Command\Typo3;
 class Typo3DeleteCommand
 {
     public function __construct(
-        private int $organizationId
+        private int $organizationId,
     ) {
     }
 

+ 1 - 1
src/Message/Command/Typo3/Typo3UndeleteCommand.php

@@ -10,7 +10,7 @@ namespace App\Message\Command\Typo3;
 class Typo3UndeleteCommand
 {
     public function __construct(
-        private int $organizationId
+        private int $organizationId,
     ) {
     }
 

+ 1 - 1
src/Message/Command/Typo3/Typo3UpdateCommand.php

@@ -10,7 +10,7 @@ namespace App\Message\Command\Typo3;
 class Typo3UpdateCommand
 {
     public function __construct(
-        private int $organizationId
+        private int $organizationId,
     ) {
     }
 

+ 1 - 1
src/Message/Handler/ExportHandler.php

@@ -18,7 +18,7 @@ class ExportHandler
         private ExporterIterator $handler,
         private MercureHub $mercureHub,
         private AccessRepository $accessRepository,
-        private Notifier $notifier
+        private Notifier $notifier,
     ) {
     }
 

+ 1 - 1
src/Message/Handler/MailerHandler.php

@@ -17,7 +17,7 @@ class MailerHandler
     public function __construct(
         private Mailer $mailer,
         private Notifier $notifier,
-        private AccessRepository $accessRepository
+        private AccessRepository $accessRepository,
     ) {
     }
 

+ 1 - 1
src/Message/Handler/Typo3/Typo3DeleteCommandHandler.php

@@ -10,7 +10,7 @@ use Symfony\Component\Messenger\Attribute\AsMessageHandler;
 class Typo3DeleteCommandHandler
 {
     public function __construct(
-        private Typo3Service $typo3Service
+        private Typo3Service $typo3Service,
     ) {
     }
 

+ 1 - 1
src/Message/Handler/Typo3/Typo3UndeleteCommandHandler.php

@@ -10,7 +10,7 @@ use Symfony\Component\Messenger\Attribute\AsMessageHandler;
 class Typo3UndeleteCommandHandler
 {
     public function __construct(
-        private Typo3Service $typo3Service
+        private Typo3Service $typo3Service,
     ) {
     }
 

+ 1 - 1
src/Message/Handler/Typo3/Typo3UpdateCommandHandler.php

@@ -10,7 +10,7 @@ use Symfony\Component\Messenger\Attribute\AsMessageHandler;
 class Typo3UpdateCommandHandler
 {
     public function __construct(
-        private Typo3Service $typo3Service
+        private Typo3Service $typo3Service,
     ) {
     }
 

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

@@ -29,7 +29,7 @@ class AccessRepository extends ServiceEntityRepository implements UserLoaderInte
     public function __construct(
         ManagerRegistry $registry,
         private RequestStack $requestStack,
-        private FiltersConfigurationService $filtersConfigurationService
+        private FiltersConfigurationService $filtersConfigurationService,
     ) {
         parent::__construct($registry, Access::class);
     }

+ 1 - 1
src/Repository/Booking/CourseRepository.php

@@ -14,7 +14,7 @@ class CourseRepository extends ServiceEntityRepository
 {
     public function __construct(
         ManagerRegistry $registry,
-        private FiltersConfigurationService $filtersConfigurationService
+        private FiltersConfigurationService $filtersConfigurationService,
     ) {
         parent::__construct($registry, Course::class);
     }

+ 1 - 1
src/Repository/Education/EducationNotationRepository.php

@@ -14,7 +14,7 @@ class EducationNotationRepository extends ServiceEntityRepository
 {
     public function __construct(
         ManagerRegistry $registry,
-        private FiltersConfigurationService $filtersConfigurationService
+        private FiltersConfigurationService $filtersConfigurationService,
     ) {
         parent::__construct($registry, EducationNotation::class);
     }

+ 5 - 0
src/Repository/Person/PersonRepository.php

@@ -37,4 +37,9 @@ final class PersonRepository extends ServiceEntityRepository implements Password
         $this->_em->persist($user);
         $this->_em->flush();
     }
+
+    public function findOneByUsername(string $username): ?Person
+    {
+        return $this->findOneBy(['username' => $username]);
+    }
 }

+ 1 - 1
src/Security/Voter/EntityVoter/AbstractEntityVoter.php

@@ -53,7 +53,7 @@ abstract class AbstractEntityVoter extends Voter
         protected Utils $accessUtils,
         private InternalRequestsService $internalRequestsService,
         private EntityManagerInterface $em,
-        private SwitchUser $switchUser
+        private SwitchUser $switchUser,
     ) {
     }
 

+ 1 - 1
src/Serializer/AccessContextBuilder.php

@@ -18,7 +18,7 @@ final class AccessContextBuilder implements SerializerContextBuilderInterface
     public function __construct(
         private SerializerContextBuilderInterface $decorated,
         private AuthorizationCheckerInterface $authorizationChecker,
-        private Security $security
+        private Security $security,
     ) {
     }
 

+ 1 - 1
src/Serializer/DefaultNormalizer.php

@@ -21,7 +21,7 @@ final class DefaultNormalizer implements NormalizerInterface, DenormalizerInterf
     public function __construct(
         private NormalizerInterface $decorated,
         private EntityUtils $entityUtils,
-        private Security $security
+        private Security $security,
     ) {
         if (!$this->decorated instanceof DenormalizerInterface) {
             throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));

+ 24 - 3
src/Service/Access/AccessProfileCreator.php

@@ -6,9 +6,10 @@ namespace App\Service\Access;
 
 use App\ApiResources\Profile\AccessProfile;
 use App\Entity\Access\Access;
+use App\Entity\Access\Preferences;
 use App\Repository\Access\AccessRepository;
 use App\Service\Organization\OrganizationProfileCreator;
-use App\Test\Service\Access\AccessProfileCreatorTest;
+use Doctrine\ORM\EntityManagerInterface;
 use Symfony\Component\Security\Core\Exception\AuthenticationException;
 
 /**
@@ -19,7 +20,8 @@ class AccessProfileCreator
     public function __construct(
         private readonly OrganizationProfileCreator $organizationProfileCreator,
         private readonly AccessRepository $accessRepository,
-        private readonly Utils $accessUtils
+        private readonly Utils $accessUtils,
+        private readonly EntityManagerInterface $entityManager,
     ) {
     }
 
@@ -37,6 +39,10 @@ class AccessProfileCreator
             throw new AuthenticationException('no_valid_access', 401);
         }
 
+        if (is_null($access->getPreferences())) {
+            $this->createPreferences($access);
+        }
+
         // L'Access en paramètre est celui de la connexion
         $mainAccessProfile = $this->createCompleteAccessProfile($access);
 
@@ -80,7 +86,9 @@ class AccessProfileCreator
             ->setIsPayor(
                 !$access->getBillingPayers()->isEmpty()
                 || ($access->getBillingReceivers()->isEmpty() && $access->getChildren()->isEmpty() && !$access->getAccessIntangibles()->isEmpty())
-            );
+            )
+            ->setPreferencesId($access->getPreferences()->getId())
+        ;
     }
 
     /**
@@ -104,4 +112,17 @@ class AccessProfileCreator
                 $this->organizationProfileCreator->createLightOrganizationProfile($access->getOrganization())
             );
     }
+
+    /**
+     * Créer l'entrée des Preferences en base.
+     *
+     * @see AccessProfileCreatorTest::testCreatePreferences()
+     *
+     * @return void
+     */
+    public function createPreferences(Access $access)
+    {
+        $access->setPreferences(new Preferences());
+        $this->entityManager->flush();
+    }
 }

+ 1 - 1
src/Service/Access/AdminAccessUtils.php

@@ -16,7 +16,7 @@ class AdminAccessUtils
 {
     public function __construct(
         private Utils $accessUtils,
-        private ContactPointUtils $contactPointUtils
+        private ContactPointUtils $contactPointUtils,
     ) {
     }
 

+ 1 - 1
src/Service/Access/OptionalsRoles/CriteriaNotationOptionalRole.php

@@ -12,7 +12,7 @@ use App\Service\Access\OptionalsRolesInterface;
 class CriteriaNotationOptionalRole implements OptionalsRolesInterface
 {
     public function __construct(
-        private readonly AccessRepository $accessRepository
+        private readonly AccessRepository $accessRepository,
     ) {
     }
 

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

@@ -21,7 +21,7 @@ class Utils
     public function __construct(
         readonly private RoleHierarchyInterface $roleHierarchy,
         readonly private AccessRepository $accessRepository,
-        readonly private OptionalsRolesIterator $optionalsRolesIterator
+        readonly private OptionalsRolesIterator $optionalsRolesIterator,
     ) {
     }
 

+ 2 - 2
src/Service/ApiLegacy/ApiLegacyRequestService.php

@@ -23,7 +23,7 @@ class ApiLegacyRequestService extends ApiRequestService
         HttpClientInterface $apiLegacyClient,
         private readonly Security $security,
         private readonly JWTTokenManagerInterface $jwtManager,
-        readonly private string $internalRequestsToken
+        readonly private string $internalRequestsToken,
     ) {
         parent::__construct($apiLegacyClient);
     }
@@ -36,7 +36,7 @@ class ApiLegacyRequestService extends ApiRequestService
         string $method,
         string $url,
         array $parameters = [],
-        array $options = []
+        array $options = [],
     ): ResponseInterface {
         $token = $this->security->getToken();
 

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

@@ -16,7 +16,7 @@ class ActivityYearConstraint extends AbstractTimeConstraintUtils implements Time
 {
     public function __construct(
         private EntityManagerInterface $entityManager,
-        private OrganizationUtils $organizationUtils
+        private OrganizationUtils $organizationUtils,
     ) {
     }
 

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

@@ -17,7 +17,7 @@ class DateTimeConstraint extends AbstractTimeConstraintUtils implements TimeCons
 {
     public function __construct(
         readonly private EntityManagerInterface $entityManager,
-        readonly private OrganizationUtils $organizationUtils
+        readonly private OrganizationUtils $organizationUtils,
     ) {
     }
 

+ 1 - 1
src/Service/Cotisation/CotisationCreator.php

@@ -14,7 +14,7 @@ class CotisationCreator
 {
     public function __construct(
         private readonly OrganizationRepository $organizationRepository,
-        private readonly Utils $cotisationUtils
+        private readonly Utils $cotisationUtils,
     ) {
     }
 

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

@@ -25,7 +25,7 @@ class Utils
         private readonly NetworkUtils $networkUtils,
         private readonly OrganizationUtils $organizationUtils,
         private readonly NetworkOrganizationRepository $networkOrganizationRepository,
-        private readonly CotisationApiResourcesRepository $cotisationApiResourcesRepository
+        private readonly CotisationApiResourcesRepository $cotisationApiResourcesRepository,
     ) {
     }
 

+ 1 - 1
src/Service/Cron/Job/CleanDb.php

@@ -24,7 +24,7 @@ class CleanDb extends BaseCronJob
 
     #[Pure]
     public function __construct(
-        private Connection $connection
+        private Connection $connection,
     ) {
         parent::__construct();
     }

+ 1 - 1
src/Service/Cron/Job/CleanTempFiles.php

@@ -31,7 +31,7 @@ class CleanTempFiles extends BaseCronJob
     public function __construct(
         private Connection $connection,
         private FileRepository $fileRepository,
-        private LocalStorage $storage
+        private LocalStorage $storage,
     ) {
         parent::__construct();
     }

+ 1 - 1
src/Service/Cron/Job/DolibarrSync.php

@@ -16,7 +16,7 @@ class DolibarrSync extends BaseCronJob
 {
     #[Pure]
     public function __construct(
-        private readonly DolibarrSyncService $dolibarrSyncService
+        private readonly DolibarrSyncService $dolibarrSyncService,
     ) {
         parent::__construct();
     }

+ 1 - 1
src/Service/Cron/UI/ConsoleUI.php

@@ -15,7 +15,7 @@ class ConsoleUI implements CronUIInterface
     protected ProgressBar $progressBar;
 
     public function __construct(
-        private OutputInterface $output
+        private OutputInterface $output,
     ) {
         $this->progressBar = new ProgressBar($output, 0);
     }

+ 1 - 1
src/Service/Doctrine/FiltersConfigurationService.php

@@ -27,7 +27,7 @@ class FiltersConfigurationService
     public function __construct(
         private EntityManagerInterface $entityManager,
         private DateTimeConstraint $dateTimeConstraint,
-        private ActivityYearConstraint $activityYearConstraint
+        private ActivityYearConstraint $activityYearConstraint,
     ) {
     }
 

+ 2 - 2
src/Service/Dolibarr/DolibarrSyncService.php

@@ -66,7 +66,7 @@ class DolibarrSyncService
         private AddressPostalUtils $addressPostalUtils,
         private ArrayUtils $arrayUtils,
         private TranslatorInterface $translator,
-        private Utils $organizationUtils
+        private Utils $organizationUtils,
     ) {
     }
 
@@ -170,7 +170,7 @@ class DolibarrSyncService
                 ) {
                     NetworkEnum::CMF->value => $cmfDolibarrId,
                     NetworkEnum::FFEC->value => $ffecDolibarrId,
-                    default => null
+                    default => null,
                 };
             }
 

+ 23 - 9
src/Service/Export/Encoder/DocXEncoder.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Service\Export\Encoder;
 
 use App\Enum\Export\ExportFormatEnum;
+use App\Service\Utils\FileUtils;
 use Phpdocx\Create\CreateDocx;
 
 /**
@@ -12,27 +13,40 @@ use Phpdocx\Create\CreateDocx;
  */
 class DocXEncoder implements EncoderInterface
 {
+    public function __construct(
+        private readonly CreateDocx $phpDocx,
+        private readonly FileUtils $fileUtils,
+    ) {
+    }
+
     public function support(string $format): bool
     {
         return $format === ExportFormatEnum::DOCX->value;
     }
 
     //  TODO: resolve Phpstan errors
+
     /**
      * Encode the given HTML content into docX, and
      * return the encoded content.
      *
-     * @param array<mixed> $options
+     * @param array<string, mixed> $options
+     *
+     * @throws \Throwable
      */
     public function encode(string $html, array $options = []): string
     {
-        //    $docx = new CreateDocx();
-        //    $docx->embedHTML($html);
-        //    $tempFile = tempnam(sys_get_temp_dir(), 'docx');
-        //    $docx->createDocx($tempFile);
-        //    $content = file_get_contents($tempFile);
-        //    unlink($tempFile);
-        //    return $content;
-        return '';
+        $tempFilename = $this->fileUtils->getTempFilename('docx');
+
+        // @see https://www.phpdocx.com/documentation/introduction/html-to-word-PHP#
+        $this->phpDocx->embedHTML($html);
+
+        try {
+            $this->phpDocx->createDocx($tempFilename);
+
+            return $this->fileUtils->getFileContent($tempFilename);
+        } finally {
+            $this->fileUtils->unlinkIfExist($tempFilename);
+        }
     }
 }

+ 26 - 34
src/Service/Export/Encoder/PdfEncoder.php

@@ -5,32 +5,22 @@ declare(strict_types=1);
 namespace App\Service\Export\Encoder;
 
 use App\Enum\Export\ExportFormatEnum;
-use Knp\Snappy\Pdf;
+use App\Service\Utils\Path;
+use Dompdf\Dompdf;
+use Dompdf\Options;
 
 /**
  * Encode HTML to PDF.
  */
 class PdfEncoder implements EncoderInterface
 {
-    /**
-     * Default encoding options.
-     *
-     * @see https://wkhtmltopdf.org/libwkhtmltox/
-     *
-     * @var array<mixed>
-     */
-    private array $defaultOptions = [
-        'margin-top' => 35,
-        'margin-right' => 10,
-        'margin-bottom' => 15,
-        'margin-left' => 15,
-        'header-spacing' => 5,
-        'enable-local-file-access' => true,
-    ];
-
-    public function __construct(
-        private readonly Pdf $knpSnappy
-    ) {
+    protected Options $domPdfOptions;
+    protected Dompdf $dompdf;
+
+    public function __construct()
+    {
+        $this->domPdfOptions = new Options();
+        $this->dompdf = new Dompdf();
     }
 
     public function support(string $format): bool
@@ -39,25 +29,27 @@ class PdfEncoder implements EncoderInterface
     }
 
     /**
-     * Default encoding options.
+     * Converts the provided HTML content into a PDF document.
      *
-     * @return array<mixed>
-     */
-    public function getDefaultOptions()
-    {
-        return $this->defaultOptions;
-    }
-
-    /**
-     * Encode the given HTML content into PDF, and
-     * return the encoded content.
+     * @param string               $html    the HTML content to be converted to PDF
+     * @param array<string, mixed> $options Optional configuration settings for the PDF generation
+     *
+     *                                      @see https://github.com/dompdf/dompdf/blob/master/src/Options.php
      *
-     * @param array<mixed> $options
+     * @return string the generated PDF content as a string
      */
     public function encode(string $html, array $options = []): string
     {
-        $options = array_merge($this->getDefaultOptions(), $options);
+        $this->domPdfOptions->setIsRemoteEnabled(true);
+        $this->domPdfOptions->setChroot(Path::getProjectDir().'/public');
+        $this->domPdfOptions->setDefaultPaperOrientation('portrait');
+        $this->domPdfOptions->setDefaultPaperSize('A4');
+        $this->domPdfOptions->set($options);
+
+        $this->dompdf->setOptions($this->domPdfOptions);
+        $this->dompdf->loadHtml($html);
+        $this->dompdf->render();
 
-        return $this->knpSnappy->getOutputFromHtml($html, $options);
+        return $this->dompdf->output();
     }
 }

+ 1 - 1
src/Service/Export/LicenceCmfExporter.php

@@ -26,7 +26,7 @@ class LicenceCmfExporter extends BaseExporter implements ExporterInterface
     public const LICENCE_CMF_COLOR = [0 => '931572', 1 => 'C2981A', 2 => '003882', 3 => '27AAE1', 4 => '2BB673'];
 
     public function __construct(
-        private readonly OrganizationRepository $organizationRepository
+        private readonly OrganizationRepository $organizationRepository,
     ) {
     }
 

+ 1 - 1
src/Service/File/Factory/ImageFactory.php

@@ -17,7 +17,7 @@ class ImageFactory
     public function __construct(
         private readonly DataManager $dataManager,
         private readonly FilterManager $filterManager,
-        private readonly CacheManager $cacheManager
+        private readonly CacheManager $cacheManager,
     ) {
     }
 

+ 3 - 3
src/Service/File/FileManager.php

@@ -29,7 +29,7 @@ class FileManager
         protected readonly IriConverterInterface $iriConverter,
         protected readonly StorageIterator $storageIterator,
         protected readonly ImageFactory $imageFactory,
-        protected readonly LocalStorage $localStorage
+        protected readonly LocalStorage $localStorage,
     ) {
     }
 
@@ -87,7 +87,7 @@ class FileManager
         bool $isTemporary = false,
         FileVisibilityEnum $visibility = FileVisibilityEnum::NOBODY,
         ?string $mimeType = null,
-        bool $flushFile = true
+        bool $flushFile = true,
     ): File {
         return $this
             ->localStorage
@@ -118,7 +118,7 @@ class FileManager
         bool $isTemporary = false,
         FileVisibilityEnum $visibility = FileVisibilityEnum::NOBODY,
         ?string $mimeType = null,
-        ?string $config = null
+        ?string $config = null,
     ): File {
         return $this
             ->localStorage

+ 6 - 2
src/Service/File/Storage/ApiLegacyStorage.php

@@ -19,7 +19,8 @@ class ApiLegacyStorage implements FileStorageInterface
         private readonly ApiLegacyRequestService $apiLegacyRequestService,
         protected readonly DataManager $dataManager,
         protected readonly UrlBuilder $urlBuilder,
-        protected readonly string $legacyBaseUrl
+        protected readonly string $legacyBaseUrl,
+        protected readonly string $publicLegacyBaseUrl,
     ) {
     }
 
@@ -45,7 +46,10 @@ class ApiLegacyStorage implements FileStorageInterface
     {
         $url = sprintf('api/files/%s/download/%s?relativePath=1', $file->getId(), $size);
 
-        return UrlBuilder::concat($this->legacyBaseUrl, [$this->apiLegacyRequestService->getContent($url)], []);
+        // L'url interne est l'équivalent d'un chemin relatif dans ce cas
+        $baseUrl = $relativePath ? $this->legacyBaseUrl : $this->publicLegacyBaseUrl;
+
+        return UrlBuilder::concat($baseUrl, [$this->apiLegacyRequestService->getContent($url)], []);
     }
 
     public function support(File $file): bool

+ 5 - 5
src/Service/File/Storage/LocalStorage.php

@@ -54,7 +54,7 @@ class LocalStorage implements FileStorageInterface
         protected readonly CacheManager $cacheManager,
         protected readonly ImageFactory $imageFactory,
         protected readonly FileUtils $fileUtils,
-        protected readonly UrlBuilder $urlBuilder
+        protected readonly UrlBuilder $urlBuilder,
     ) {
         $this->filesystem = $filesystemMap->get(static::FS_KEY);
     }
@@ -74,7 +74,7 @@ class LocalStorage implements FileStorageInterface
      */
     public function listByOwner(
         Organization|Access|Person $owner,
-        ?FileTypeEnum $type = null
+        ?FileTypeEnum $type = null,
     ): array {
         return $this->filesystem->listKeys(
             $this->getPrefix($owner, false, $type)
@@ -152,7 +152,7 @@ class LocalStorage implements FileStorageInterface
         bool $isTemporary = false,
         FileVisibilityEnum $visibility = FileVisibilityEnum::NOBODY,
         ?string $mimeType = null,
-        bool $flushFile = true
+        bool $flushFile = true,
     ): File {
         [$organization, $person] = $this->getOrganizationAndPersonFromOwner($owner);
 
@@ -249,7 +249,7 @@ class LocalStorage implements FileStorageInterface
         bool $isTemporary = false,
         FileVisibilityEnum $visibility = FileVisibilityEnum::NOBODY,
         ?string $mimeType = null,
-        ?string $config = null
+        ?string $config = null,
     ): File {
         $file = $this->prepareFile(
             $owner,
@@ -307,7 +307,7 @@ class LocalStorage implements FileStorageInterface
     protected function getPrefix(
         Organization|Access|Person $owner,
         bool $isTemporary,
-        ?FileTypeEnum $type = null
+        ?FileTypeEnum $type = null,
     ): string {
         if ($owner instanceof Access) {
             $prefix = Path::join('organization', $owner->getOrganization()?->getId(), $owner->getId());

+ 1 - 1
src/Service/Mailer/Builder/OnSubdomainChangeMailBuilder.php

@@ -25,7 +25,7 @@ class OnSubdomainChangeMailBuilder extends AbstractBuilder implements BuilderInt
     public function __construct(
         private readonly EntityManagerInterface $entityManager,
         private readonly string $opentalentNoReplyEmailAddress,
-        private readonly AccessUtils $accessUtils
+        private readonly AccessUtils $accessUtils,
     ) {
     }
 

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

@@ -35,7 +35,7 @@ class Mailer
         private readonly StringsUtils $stringsUtils,
         private readonly EntityManagerInterface $entityManager,
         private readonly Environnement $environnement,
-        private readonly LoggerInterface $logger
+        private readonly LoggerInterface $logger,
     ) {
     }
 

+ 1 - 1
src/Service/MercureHub.php

@@ -28,7 +28,7 @@ class MercureHub
         private HubInterface $hub,
         private SerializerInterface $serializer,
         private EncoderInterface $encoder,
-        private IriConverterInterface $iriConverter
+        private IriConverterInterface $iriConverter,
     ) {
     }
 

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

@@ -21,7 +21,7 @@ class MobytService extends ApiRequestService
     /** @noinspection SenselessProxyMethodInspection */
     #[Pure]
     public function __construct(
-        HttpClientInterface $mobyt_client
+        HttpClientInterface $mobyt_client,
     ) {
         parent::__construct($mobyt_client);
     }

+ 7 - 7
src/Service/Notifier.php

@@ -14,7 +14,7 @@ class Notifier
 {
     public function __construct(
         private EntityManagerInterface $em,
-        private MercureHub $mercureHub
+        private MercureHub $mercureHub,
     ) {
     }
 
@@ -26,7 +26,7 @@ class Notifier
         string $name,
         NotificationTypeEnum $type,
         array $message,
-        ?string $link = null
+        ?string $link = null,
     ): Notification {
         $now = new \DateTime();
 
@@ -51,7 +51,7 @@ class Notifier
         string $name,
         NotificationTypeEnum $type,
         array $message,
-        ?string $link = null
+        ?string $link = null,
     ): Notification {
         $notification = $this->createNotification($access, $name, $type, $message, $link);
 
@@ -65,7 +65,7 @@ class Notifier
 
     public function notifyExport(
         Access $access,
-        File $file
+        File $file,
     ): Notification {
         return $this->notify(
             $access,
@@ -81,7 +81,7 @@ class Notifier
      */
     public function notifyMessage(
         Access $access,
-        array $message
+        array $message,
     ): Notification {
         return $this->notify(
             $access,
@@ -96,7 +96,7 @@ class Notifier
      */
     public function notifySystem(
         Access $access,
-        array $message
+        array $message,
     ): Notification {
         return $this->notify(
             $access,
@@ -112,7 +112,7 @@ class Notifier
     public function notifyError(
         Access $access,
         string $name,
-        array $message
+        array $message,
     ): Notification {
         return $this->notify(
             $access,

+ 1 - 1
src/Service/OnChange/OnChangeContext.php

@@ -8,7 +8,7 @@ class OnChangeContext
      * @param array<mixed> $context
      */
     public function __construct(
-        private array $context
+        private array $context,
     ) {
     }
 

+ 1 - 1
src/Service/OnChange/Organization/OnParametersChange.php

@@ -27,7 +27,7 @@ class OnParametersChange extends OnChangeDefault
         private CourseRepository $courseRepository,
         private NetworkUtils $networkUtils,
         private OrganizationUtils $organizationUtils,
-        private MessageBusInterface $messageBus
+        private MessageBusInterface $messageBus,
     ) {
     }
 

+ 1 - 1
src/Service/OnlineRegistration/RegistrationStatusService.php

@@ -21,7 +21,7 @@ class RegistrationStatusService
     public const DISPLAYING_TIME = 30;
 
     public function __construct(
-        private OnlineRegistrationService $onlineRegistrationService
+        private OnlineRegistrationService $onlineRegistrationService,
     ) {
     }
 

+ 1 - 1
src/Service/Organization/OrganizationProfileCreator.php

@@ -21,7 +21,7 @@ class OrganizationProfileCreator
     public function __construct(
         private Module $module,
         private Tree $tree,
-        private OrganizationUtils $organizationUtils
+        private OrganizationUtils $organizationUtils,
     ) {
     }
 

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

@@ -23,7 +23,7 @@ class Utils
 
     public function __construct(
         private NetworkOrganizationRepository $networkOrganizationRepository,
-        private NetworkUtils $networkUtils
+        private NetworkUtils $networkUtils,
     ) {
     }
 
@@ -184,15 +184,20 @@ class Utils
      *
      * @see UtilsTest::testGetActivityPeriodsSwitchYear()
      */
-    public function getActivityPeriodsSwitchYear(Organization $organization, int $year): array
+    public function getActivityPeriodsSwitchYear(Organization $organization, ?int $year = null): array
     {
+        // Utiliser l'année actuelle si $year est null
+        if ($year === null) {
+            $year = (int) DatesUtils::new()->format('Y');
+        }
+
         $musicalDate = $organization->getParameters()->getMusicalDate();
 
         if (empty($musicalDate)) {
-            $dateStart = new \DateTime($year.'-09-01');
-            $dateEnd = new \DateTime(($year + 1).'-08-31');
+            $dateStart = DatesUtils::new($year.'-09-01');
+            $dateEnd = DatesUtils::new(($year + 1).'-08-31');
         } else {
-            $dateStart = new \DateTime($year.'-'.$musicalDate->format('m').'-'.$musicalDate->format('d'));
+            $dateStart = DatesUtils::new($year.'-'.$musicalDate->format('m').'-'.$musicalDate->format('d'));
             $dateEnd = clone $dateStart;
             $dateEnd->add(new \DateInterval('P1Y'))->sub(new \DateInterval('P1D'));
         }

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

@@ -87,6 +87,6 @@ interface ApiRequestInterface
         string $method,
         string $url,
         array $parameters = [],
-        array $options = []
+        array $options = [],
     ): ResponseInterface;
 }

+ 2 - 2
src/Service/Rest/ApiRequestService.php

@@ -19,7 +19,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
 class ApiRequestService implements ApiRequestInterface
 {
     public function __construct(
-        protected HttpClientInterface $client
+        protected HttpClientInterface $client,
     ) {
     }
 
@@ -123,7 +123,7 @@ class ApiRequestService implements ApiRequestInterface
         string $method,
         string $url,
         array $parameters = [],
-        array $options = []
+        array $options = [],
     ): ResponseInterface {
         $url = ltrim($url, '/');
         $url = UrlBuilder::concatParameters($url, $parameters);

+ 1 - 1
src/Service/Rest/Operation/BaseRestOperation.php

@@ -39,7 +39,7 @@ abstract class BaseRestOperation
         protected string $path,
         protected array $initialData = [],
         protected array $parameters = [],
-        protected array $options = []
+        protected array $options = [],
     ) {
     }
 

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

@@ -21,7 +21,7 @@ class CreateOperation extends BaseRestOperation
         protected string $entityName,
         protected array $data,
         protected array $parameters = [],
-        protected array $options = []
+        protected array $options = [],
     ) {
         $options['json'] = $this->data;
 

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

@@ -23,7 +23,7 @@ class DeleteOperation extends BaseRestOperation
         protected string $entityName,
         protected int $id,
         protected array $initialData = [],
-        protected array $options = []
+        protected array $options = [],
     ) {
         parent::__construct(
             $label,

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

@@ -27,7 +27,7 @@ class UpdateOperation extends BaseRestOperation
         protected array $data,
         protected array $initialData = [],
         protected array $parameters = [],
-        protected array $options = []
+        protected array $options = [],
     ) {
         $options['json'] = $this->data;
 

+ 1 - 1
src/Service/Security/InternalRequestsService.php

@@ -21,7 +21,7 @@ class InternalRequestsService
     ];
 
     public function __construct(
-        readonly private string $internalRequestsToken
+        readonly private string $internalRequestsToken,
     ) {
     }
 

Some files were not shown because too many files changed in this diff