Browse Source

fix merge conflicts

Olivier Massot 1 year ago
parent
commit
cbf56f217b
100 changed files with 1505 additions and 832 deletions
  1. 26 19
      .env
  2. 0 42
      .env.ci
  3. 0 59
      .env.prod
  4. 0 52
      .env.staging
  5. 0 61
      .env.test
  6. 15 5
      .gitignore
  7. 7 4
      .gitlab-ci.yml
  8. 25 0
      .php-cs-fixer.dist.php
  9. 8 4
      composer.json
  10. 1 0
      config/api_platform/Access/access.yaml
  11. 9 10
      config/bundles.php
  12. 13 11
      config/opentalent/enum.yaml
  13. 8 5
      config/opentalent/products.yaml
  14. 0 86
      config/packages/docker/monolog.yaml
  15. 4 4
      config/packages/doctrine.yaml
  16. 3 1
      config/packages/knp_gaufrette.yaml
  17. 55 0
      config/packages/liip_imagine.yaml
  18. 1 1
      config/packages/mercure.yaml
  19. 0 1
      config/packages/messenger.yaml
  20. 103 0
      config/packages/monolog.yaml
  21. 1 1
      config/packages/nelmio_cors.yaml
  22. 0 86
      config/packages/prod/monolog.yaml
  23. 2 0
      config/routes/liip_imagine.yaml
  24. 3 0
      config/secrets/docker/docker.DATABASE_ADMINASSOS_URL.3cc6e9.php
  25. 3 0
      config/secrets/docker/docker.DATABASE_AUDIT_URL.f1a8d2.php
  26. 3 0
      config/secrets/docker/docker.DATABASE_URL.8ea85a.php
  27. 3 0
      config/secrets/docker/docker.DOLIBARR_API_TOKEN.bdeaba.php
  28. 3 0
      config/secrets/docker/docker.MERCURE_JWT_SECRET.88e4d2.php
  29. 4 0
      config/secrets/docker/docker.decrypt.private.php
  30. 3 0
      config/secrets/docker/docker.encrypt.public.php
  31. 9 0
      config/secrets/docker/docker.list.php
  32. 3 0
      config/secrets/prod/prod.DATABASE_ADMINASSOS_URL.3cc6e9.php
  33. 3 0
      config/secrets/prod/prod.DATABASE_AUDIT_URL.f1a8d2.php
  34. 3 0
      config/secrets/prod/prod.DATABASE_URL.8ea85a.php
  35. 3 0
      config/secrets/prod/prod.DOLIBARR_API_TOKEN.bdeaba.php
  36. 3 0
      config/secrets/prod/prod.MERCURE_JWT_SECRET.88e4d2.php
  37. 3 0
      config/secrets/prod/prod.encrypt.public.php
  38. 9 0
      config/secrets/prod/prod.list.php
  39. 3 0
      config/secrets/readme.md
  40. 3 0
      config/secrets/staging/staging.DATABASE_ADMINASSOS_URL.3cc6e9.php
  41. 3 0
      config/secrets/staging/staging.DATABASE_AUDIT_URL.f1a8d2.php
  42. 3 0
      config/secrets/staging/staging.DATABASE_URL.8ea85a.php
  43. 3 0
      config/secrets/staging/staging.DOLIBARR_API_TOKEN.bdeaba.php
  44. 4 0
      config/secrets/staging/staging.decrypt.private.php
  45. 3 0
      config/secrets/staging/staging.encrypt.public.php
  46. 8 0
      config/secrets/staging/staging.list.php
  47. 3 0
      config/secrets/test/test.DATABASE_ADMINASSOS_URL.3cc6e9.php
  48. 3 0
      config/secrets/test/test.DATABASE_AUDIT_URL.f1a8d2.php
  49. 3 0
      config/secrets/test/test.DATABASE_URL.8ea85a.php
  50. 3 0
      config/secrets/test/test.DOLIBARR_API_TOKEN.bdeaba.php
  51. 3 0
      config/secrets/test/test.MERCURE_JWT_SECRET.88e4d2.php
  52. 4 0
      config/secrets/test/test.decrypt.private.php
  53. 3 0
      config/secrets/test/test.encrypt.public.php
  54. 9 0
      config/secrets/test/test.list.php
  55. 7 5
      config/services.yaml
  56. 37 0
      doc/cron.md
  57. 51 6
      doc/env.md
  58. 0 20
      docker-compose.override.yml
  59. 0 44
      docker-compose.yml
  60. 7 21
      env/.env.docker
  61. 36 0
      env/.env.prod
  62. 35 0
      env/.env.staging
  63. 34 0
      env/.env.test
  64. 34 0
      env/.env.test1
  65. 34 0
      env/.env.test2
  66. 34 0
      env/.env.test3
  67. 34 0
      env/.env.test4
  68. 34 0
      env/.env.test5
  69. 34 0
      env/.env.test6
  70. 34 0
      env/.env.test7
  71. 34 0
      env/.env.test8
  72. 34 0
      env/.env.test9
  73. 3 0
      env/readme.md
  74. 0 0
      icon.svg
  75. 2 2
      old/Entity/Awin/Product.php
  76. 0 1
      phpstan.json
  77. 10 9
      phpstan.neon.dist
  78. BIN
      public/images/missing-file.png
  79. 9 0
      readme.md
  80. 50 48
      sql/schema-extensions/001-view_public_events.sql
  81. 0 0
      src/ApiResource/.gitignore
  82. 44 17
      src/ApiResources/Access/AdminAccess.php
  83. 4 2
      src/ApiResources/ApiResourcesInterface.php
  84. 36 0
      src/ApiResources/Core/File/Download.php
  85. 0 48
      src/ApiResources/Core/File/DownloadRequest.php
  86. 59 0
      src/ApiResources/Core/File/Image.php
  87. 164 0
      src/ApiResources/Core/File/Upload.php
  88. 15 9
      src/ApiResources/Cotisation/Cotisation.php
  89. 20 13
      src/ApiResources/Dolibarr/DolibarrAccount.php
  90. 18 23
      src/ApiResources/Dolibarr/DolibarrBill.php
  91. 13 8
      src/ApiResources/Dolibarr/DolibarrContract.php
  92. 15 8
      src/ApiResources/Dolibarr/DolibarrContractLine.php
  93. 10 6
      src/ApiResources/Enum/Enum.php
  94. 12 44
      src/ApiResources/Export/ExportRequest.php
  95. 0 1
      src/ApiResources/Export/ExportRequestInterface.php
  96. 22 31
      src/ApiResources/Export/LicenceCmf/LicenceCmfOrganizationER.php
  97. 9 8
      src/ApiResources/Mobyt/MobytUserStatus.php
  98. 1 1
      src/ApiResources/OnlineRegistration/RegistrationAvailability.php
  99. 7 5
      src/ApiResources/OnlineRegistration/RegistrationStatus.php
  100. 69 0
      src/ApiResources/Organization/Subdomain/SubdomainAvailability.php

+ 26 - 19
.env

@@ -18,9 +18,22 @@ APP_DEBUG=0
 APP_SECRET=6a76497c8658bb23e2236f97a2627df3
 ###< symfony/framework-bundle ###
 
-###> doctrine/doctrine-bundle ###
-# => defined in the .env.<environment> files
-###< doctrine/doctrine-bundle ###
+###> secret values <###
+# > @see doc/env.md
+DATABASE_URL=xxx
+DATABASE_ADMINASSOS_URL=xxx
+DATABASE_AUDIT_URL=xxx
+DOLIBARR_API_TOKEN=xxx
+MERCURE_JWT_SECRET=xxx
+###< secret values ###
+
+###> nelmio/cors-bundle ###
+CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
+###< nelmio/cors-bundle ###
+
+###> url v2 ###
+PUBLIC_API_BASE_URL=https://local.ap2i.opentalent.fr
+###
 
 ###> lexik/jwt-authentication-bundle ###
 JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
@@ -34,7 +47,6 @@ OPENTALENT_CONFIG=/config/opentalent
 
 ###> dolibarr client ###
 DOLIBARR_API_BASE_URI=https://dev-erp.2iopenservice.com/api/index.php/
-DOLIBARR_API_TOKEN=Bocc4zC0J186v8J6QCqu7DnoIw4I7mCJ
 ###< dolibarr client ###
 
 ###> mobyt client ###
@@ -77,29 +89,17 @@ ELASTICSEARCH_PORT=9200
 ###> symfony/mercure-bundle ###
 # See https://symfony.com/doc/current/mercure.html#configuration
 # The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
-MERCURE_URL=http://mercure/.well-known/mercure
+MERCURE_URL=xxx
 # The public URL of the Mercure hub, used by the browser to connect
-MERCURE_PUBLIC_URL=https://local.mercure.opentalent.fr/.well-known/mercure
+MERCURE_PUBLIC_URL=xxx
 # The secret key used to sign the JWTs
-MERCURE_PUBLISHER_JWT_KEY=NQEupdREijrfYvCmF2mnvZQFL9zLKDH9RCYter6tUWzjemPqzicffhc2fSf0yEmM
+MERCURE_JWT_SECRET=xxx
 ###< symfony/mercure-bundle ###
 
-###> AdminAssos configuration ###
-DATABASE_ADMINASSOS_URL=mysql://root:mysql660@db:3306/adminassos?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> Audit configuration ###
-DATABASE_AUDIT_URL=mysql://root:mysql660@db:3306/audit?serverVersion=5.7
-###< Audit configuration ###
-
 ###> typo3 client ###
 TYPO3_BASE_URI=http://docker.sub.opentalent.fr
 ###< typo3 client ###
 
-###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
-###< nelmio/cors-bundle ###
-
 ###> filename log ###
 LOG_FILE_NAME=undefined
 ###< filename log ###
@@ -108,3 +108,10 @@ LOG_FILE_NAME=undefined
 INTERNAL_REQUESTS_TOKEN=sRyfu6SZLR9StpnSKYRdl6i9wr5qs1bJQzro4DUiVyYJ2jknl
 INTERNAL_FILES_DOWNLOAD_URI=https://local.api.opentalent.fr/_internal/secure/files
 ###
+
+###> BlackFire configuration ###
+BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
+BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
+BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
+BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
+###< BlackFire configuration ###

+ 0 - 42
.env.ci

@@ -1,42 +0,0 @@
-###> symfony/framework-bundle ###
-APP_DEBUG=1
-APP_SECRET=6a76497c8658bb23e2236f97a2627df3
-#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
-#TRUSTED_HOSTS='^(localhost|example\.com)$'
-###< symfony/framework-bundle ###
-
-###> doctrine/doctrine-bundle ###
-# >>> No database shall be needed by unit tests
-DATABASE_URL=mysql://root:xxx@none:3306/opentalent?serverVersion=5.7
-###< doctrine/doctrine-bundle ###
-
-###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
-###< nelmio/cors-bundle ###
-
-###> BlackFire configuration ###
-BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
-BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
-BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
-BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
-###< BlackFire configuration ###
-
-###> AdminAssos configuration ###
-# >>> No database shall be needed by unit tests
-DATABASE_ADMINASSOS_URL=mysql://root:xxx@preprod:3306/none?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> typo3 client ###
-TYPO3_BASE_URI=http://docker.sub.opentalent.fr
-###< typo3 client ###
-
-###> bindfile populate buffer file
-BIND_FILE_BUFFER_FILE=var/subdomain.txt
-###< bindfile populate buffer file
-
-###> filename log ###
-LOG_FILE_NAME=ci
-###< filename log ###
-
-###> api v1 ###
-API_LEG_BASE_URL=https://api.ci.opentalent.fr/api

+ 0 - 59
.env.prod

@@ -1,59 +0,0 @@
-###> doctrine/doctrine-bundle ###
-# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
-# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
-DATABASE_URL=mysql://root:mysql2iopenservice369566@prod-back:3306/opentalent?serverVersion=5.7
-###< doctrine/doctrine-bundle ###
-
-###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
-###< nelmio/cors-bundle ###
-
-###> api v1 ###
-API_LEG_BASE_URL=https://api.opentalent.fr/api
-###< files management ###
-
-###> BlackFire configuration ###
-BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
-BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
-BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
-BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
-###< BlackFire configuration ###
-
-###> typo3 client ###
-TYPO3_BASE_URI=http://ohcluses.opentalent.fr
-###< typo3 client ###
-
-###> AdminAssos configuration ###
-DATABASE_ADMINASSOS_URL=mysql://root:mysql2iopenservice369566@prod-back:3306/adminassos?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> Audit configuration ###
-DATABASE_AUDIT_URL=mysql://root:mysql2iopenservice369566@prod-back:3306/audit?serverVersion=5.7
-###< Audit configuration ###
-
-###> dolibarr client ###
-DOLIBARR_API_BASE_URI=https://prod-erp.2iopenservice.com/api/index.php/
-###< dolibarr client ###
-
-###> symfony/mercure-bundle ###
-# See https://symfony.com/doc/current/mercure.html#configuration
-# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
-MERCURE_URL=https://mercure.opentalent.fr/.well-known/mercure
-# The public URL of the Mercure hub, used by the browser to connect
-MERCURE_PUBLIC_URL=https://mercure.opentalent.fr/.well-known/mercure
-# The secret used to sign the JWTs
-MERCURE_JWT_SECRET=iz3XZPCfxZTOMjJUeJ5IUHNs1WxToeo4ApIdEKjxOwR906uU08noSjwwAJDAPegm
-###< symfony/mercure-bundle ###
-
-###> bindfile populate buffer file
-BIND_FILE_BUFFER_FILE=/env/subdomain.txt
-###< bindfile populate buffer file
-
-###> knplabs/knp-snappy-bundle ###
-WKHTMLTOPDF_PATH=/usr/bin/wkhtmltopdf
-WKHTMLTOIMAGE_PATH=/usr/bin/wkhtmltoimage
-###< knplabs/knp-snappy-bundle ###
-
-###> filename log ###
-LOG_FILE_NAME=prod
-###< filename log ###

+ 0 - 52
.env.staging

@@ -1,52 +0,0 @@
-# Fichier d'env utilisé pour les tests fonctionnels et applicatifs
-APP_DEBUG=1
-
-###> doctrine/doctrine-bundle ###
-DATABASE_URL=mysql://root:mysql660@db:3306/opentalent_test?serverVersion=5.7
-###< doctrine/doctrine-bundle ###
-
-###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN=^$
-###< nelmio/cors-bundle ###
-
-####> api v1 ###
-API_LEG_BASE_URL=https://none
-####< api v1 ###
-
-###> elasticsearch ###
-ELASTICSEARCH_HOST=es
-ELASTICSEARCH_PORT=9200
-###< elasticsearch ###
-
-###> BlackFire configuration ###
-BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
-BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
-BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
-BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
-###< BlackFire configuration ###
-
-###> AdminAssos configuration ###
-DATABASE_ADMINASSOS_URL=mysql://root:mysql660@db:3306/adminassos_test?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> Audit configuration ###
-DATABASE_AUDIT_URL=mysql://root:mysql660@db:3306/audit_test?serverVersion=5.7
-###< Audit configuration ###
-
-###> typo3 client ###
-TYPO3_BASE_URI=https://none
-###< typo3 client ###
-
-###> symfony/mercure-bundle ###
-# See https://symfony.com/doc/current/mercure.html#configuration
-# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
-MERCURE_URL=https://none
-# The public URL of the Mercure hub, used by the browser to connect
-MERCURE_PUBLIC_URL=https://none
-# The secret used to sign the JWTs
-MERCURE_JWT_SECRET=gEwnJpcR8k0xE2sfBpEJzzuP2b2TXhZnzImIqCUk3j4RStBZa2pQjbEMsnGE4iGM
-###< symfony/mercure-bundle ###
-
-### Internal requests (@see doc/internal_requests.md)
-INTERNAL_FILES_DOWNLOAD_URI=https://none
-###

+ 0 - 61
.env.test

@@ -1,61 +0,0 @@
-###> symfony/framework-bundle ###
-APP_DEBUG=1
-###< symfony/framework-bundle ###
-
-###> doctrine/doctrine-bundle ###
-DATABASE_URL=mysql://root:mysql2iopenservice369566@localhost:3306/opentalent?serverVersion=5.7
-###< doctrine/doctrine-bundle ###
-
-###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
-###< nelmio/cors-bundle ###
-
-###> api v1 ###
-API_LEG_BASE_URL=https://api.test.opentalent.fr/api
-###< files management ###
-
-###> typo3 client ###
-TYPO3_BASE_URI=http://test.opentalent.fr/ohcluses
-###< typo3 client ###
-
-###> BlackFire configuration ###
-BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
-BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
-BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
-BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
-###< BlackFire configuration ###
-
-###> AdminAssos configuration ###
-DATABASE_ADMINASSOS_URL=mysql://root:mysql2iopenservice369566@test:3306/adminassos?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> Audit configuration ###
-DATABASE_AUDIT_URL=mysql://root:mysql2iopenservice369566@test:3306/audit?serverVersion=5.7
-###< Audit configuration ###
-
-###> symfony/mercure-bundle ###
-# See https://symfony.com/doc/current/mercure.html#configuration
-# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
-MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
-# The public URL of the Mercure hub, used by the browser to connect
-MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
-# The secret used to sign the JWTs
-MERCURE_JWT_SECRET=NQEupdREijrfYvCmF2mnvZQFL9zLKDH9RCYter6tUWzjemPqzicffhc2fSf0yEmM
-###< symfony/mercure-bundle ###
-
-###> bindfile populate buffer file
-BIND_FILE_BUFFER_FILE=var/subdomain.txt
-###< bindfile populate buffer file
-
-###> knplabs/knp-snappy-bundle ###
-WKHTMLTOPDF_PATH=/usr/bin/wkhtmltopdf
-WKHTMLTOIMAGE_PATH=/usr/bin/wkhtmltoimage
-###< knplabs/knp-snappy-bundle ###
-
-###> filename log ###
-LOG_FILE_NAME=test
-###< filename log ###
-
-### Internal requests (@see doc/internal_requests.md)
-INTERNAL_FILES_DOWNLOAD_URI=https://api.test1.opentalent.fr/_internal/secure/files
-###

+ 15 - 5
.gitignore

@@ -9,6 +9,7 @@
 /config/secrets/prod/prod.decrypt.private.php
 /public/bundles/
 /var/
+/files/
 /vendor/
 ###< symfony/framework-bundle ###
 
@@ -33,11 +34,6 @@ symfony.lock
 
 /coverage/
 
-###> phpunit/phpunit ###
-/phpunit.xml
-.phpunit.result.cache
-###< phpunit/phpunit ###
-
 ###> phpstan ###
 .phpstan.neon
 ###< phpstan ###
@@ -47,4 +43,18 @@ public/phpstorm_debug.php
 
 public/phpstorm_index.php
 
+###> phpstan/phpstan ###
+phpstan.neon
+phpstan.json
+###< phpstan/phpstan ###
+
+###> liip/imagine-bundle ###
+/public/media/cache/
+###< liip/imagine-bundle ###
+
+###> friendsofphp/php-cs-fixer ###
+/.php-cs-fixer.php
+/.php-cs-fixer.cache
+###< friendsofphp/php-cs-fixer ###
+
 .php-cs-fixer.cache

+ 7 - 4
.gitlab-ci.yml

@@ -2,7 +2,7 @@ stages:
   - test
 
 variables:
-  APP_ENV: ci
+  APP_ENV: staging
   SSH_PRIVATE_KEY: $SSH_PRIVATE_KEY
   XDEBUG_MODE: coverage
 
@@ -16,14 +16,17 @@ before_script:
 
 static_analysis:
   script:
-    - php --version
-    - php -d memory_limit=512M vendor/bin/phpstan analyse -c phpstan.neon.dist --error-format gitlab > phpstan.json  # Display code quality in MR
-    - php -d memory_limit=512M vendor/bin/phpstan analyse -c phpstan.neon.dist  # Display in console
+    - php vendor/bin/phpstan analyse -c phpstan.neon.dist --error-format gitlab > phpstan.json  # Display code quality in MR
+    - php vendor/bin/phpstan analyse -c phpstan.neon.dist
   artifacts:
     when: always
     reports:
       codequality: phpstan.json
 
+code_style:
+  script:
+    - php vendor/bin/php-cs-fixer check --config=.php-cs-fixer.dist.php
+
 unit:
   stage: test
 

+ 25 - 0
.php-cs-fixer.dist.php

@@ -0,0 +1,25 @@
+<?php
+
+$finder = (new PhpCsFixer\Finder())
+    ->in(__DIR__)
+    ->exclude([
+        'bin',
+        'config/jwt',
+        'config/secrets',
+        'old',
+        'public',
+        'var',
+        'vendor',
+    ])
+    ->notPath([
+        'rector.php',
+    ])
+;
+
+return (new PhpCsFixer\Config())
+    ->setRules([
+        '@Symfony' => true,
+        'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false]
+    ])
+    ->setFinder($finder)
+;

+ 8 - 4
composer.json

@@ -22,17 +22,19 @@
     "doctrine/dbal": "^2.6",
     "doctrine/doctrine-bundle": "^2.1",
     "doctrine/doctrine-migrations-bundle": "^3.0",
-    "doctrine/orm": "^2.9",
+    "doctrine/orm": "^2.17",
     "egulias/email-validator": "^3.0",
     "jbouzekri/phumbor-bundle": "^3.1.0",
     "knplabs/knp-gaufrette-bundle": "^0.8.0",
     "knplabs/knp-snappy-bundle": "^1.9",
     "lcobucci/jwt": "^4.1",
     "lexik/jwt-authentication-bundle": "^2.8",
+    "liip/imagine-bundle": "^2.12",
     "lorenzo/pinky": "^1.0",
     "myclabs/php-enum": "^1.7",
     "nelmio/cors-bundle": "^2.1",
     "odolbeau/phone-number-bundle": "^3.1",
+    "opentalent/phpdocx": "dev-master",
     "phpdocumentor/reflection-docblock": "^5.2",
     "ramsey/uuid": "^4.2",
     "ramsey/uuid-doctrine": "^2.0",
@@ -67,7 +69,6 @@
     "twig/extra-bundle": "^3.4",
     "twig/inky-extra": "^3.4",
     "vincent/foselastica": "1.3.1",
-    "opentalent/phpdocx": "dev-master",
     "webonyx/graphql-php": "^14.3",
     "xantios/mimey": "*"
   },
@@ -75,13 +76,14 @@
     "cyclonedx/cyclonedx-php-composer": "^3.4",
     "dg/bypass-finals": "^1.4",
     "doctrine/doctrine-fixtures-bundle": "^3.4",
+    "friendsofphp/php-cs-fixer": "^3.52.1",
     "hautelook/alice-bundle": "^2.11",
     "justinrainbow/json-schema": "^5.2",
     "phpstan/extension-installer": "^1.2",
-    "phpstan/phpstan": "^1.9",
+    "phpstan/phpstan": "^1.10",
     "phpstan/phpstan-doctrine": "^1.3",
     "phpstan/phpstan-phpunit": "^1.3",
-    "phpstan/phpstan-symfony": "^1.2",
+    "phpstan/phpstan-symfony": "^1.3",
     "phpunit/phpunit": "^9.6",
     "rector/rector": "^0.15.13",
     "symfony/browser-kit": "6.3.*",
@@ -132,6 +134,8 @@
   },
   "scripts": {
     "auto-scripts": {
+      "ot:setup:env": "symfony-cmd",
+      "secrets:decrypt-to-local --force": "symfony-cmd",
       "cache:clear": "symfony-cmd",
       "assets:install %PUBLIC_DIR%": "symfony-cmd"
     },

+ 1 - 0
config/api_platform/Access/access.yaml

@@ -6,4 +6,5 @@ resources:
 
         ApiPlatform\Metadata\Put:
           security: 'is_granted("ROLE_USERS") or (object.getId() == user.getId())'
+    - paginationClientEnabled: true
 

+ 9 - 10
config/bundles.php

@@ -1,7 +1,5 @@
 <?php
 
-$devEnvs = ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true];
-
 return [
     Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
     Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
@@ -19,12 +17,13 @@ return [
     Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
     Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
     Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
-    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => $devEnvs,
-    Symfony\Bundle\MakerBundle\MakerBundle::class => $devEnvs,
-    Symfony\Bundle\DebugBundle\DebugBundle::class => $devEnvs,
-    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => $devEnvs,
-    Zenstruck\Foundry\ZenstruckFoundryBundle::class => $devEnvs,
-    Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => $devEnvs,
-    Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => $devEnvs,
-    Hautelook\AliceBundle\HautelookAliceBundle::class => $devEnvs,
+    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Zenstruck\Foundry\ZenstruckFoundryBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Hautelook\AliceBundle\HautelookAliceBundle::class => ['dev' => true, 'docker' => true, 'test' => false, 'staging' => true],
+    Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
 ];

+ 13 - 11
config/opentalent/enum.yaml

@@ -1,17 +1,17 @@
 parameters:
     opentalent.enum:
         #AccessAndFunction
-          function: 'App\Enum\AccessAndFunction\FunctionEnum'
-          function_activities: 'App\Enum\AccessAndFunction\ActivitiesFunctionEnum'
-          function_administratives: 'App\Enum\AccessAndFunction\AdministrativesFunctionEnum'
-          function_associatives: 'App\Enum\AccessAndFunction\AssociativesFunctionEnum'
-          function_departures_cause: 'App\Enum\AccessAndFunction\DeparturesCauseEnum'
-          function_pedagogics: 'App\Enum\AccessAndFunction\PedagogicsFunctionEnum'
-          function_other: 'App\Enum\AccessAndFunction\OtherFunctionEnum'
-          function_type: 'App\Enum\AccessAndFunction\TypeFunctionEnum'
-          license_type: 'App\Enum\AccessAndFunction\LicenseTypeEnum'
-          license_rate: 'App\Enum\AccessAndFunction\LicenseRateEnum'
-          function_role: 'App\Enum\AccessAndFunction\FunctionalRoleEnum'
+          function: 'App\Enum\Access\FunctionEnum'
+          function_activities: 'App\Enum\Access\ActivitiesFunctionEnum'
+          function_administratives: 'App\Enum\Access\AdministrativesFunctionEnum'
+          function_associatives: 'App\Enum\Access\AssociativesFunctionEnum'
+          function_departures_cause: 'App\Enum\Access\DeparturesCauseEnum'
+          function_pedagogics: 'App\Enum\Access\PedagogicsFunctionEnum'
+          function_other: 'App\Enum\Access\OtherFunctionEnum'
+          function_type: 'App\Enum\Access\TypeFunctionEnum'
+          license_type: 'App\Enum\Access\LicenseTypeEnum'
+          license_rate: 'App\Enum\Access\LicenseRateEnum'
+          function_role: 'App\Enum\Access\FunctionalRoleEnum'
 
         #AccessSocial
           professional_status: 'App\Enum\AccessSocial\ProfessionalStatusEnum'
@@ -63,6 +63,7 @@ parameters:
           organization_bulletin_period: 'App\Enum\Organization\BulletinPeriodEnum'
           organization_bulletin_output: 'App\Enum\Organization\BulletinOutputEnum'
           organization_bulletin_send_to: 'App\Enum\Organization\SendToBulletinEnum'
+          organization_bulletin_criteria_sort: 'App\Enum\Organization\BulletinCriteriaSortEnum'
           organization_setting_country: 'App\Enum\Organization\CountryEnum'
           address_postal_organization: 'App\Enum\Organization\AddressPostalOrganizationTypeEnum'
 
@@ -128,6 +129,7 @@ parameters:
           education_year: 'App\Enum\Education\YearEnum'
           education_period: 'App\Enum\Education\PeriodEnum'
           education_periodicity: 'App\Enum\Education\PeriodicityEnum'
+          education_cycle: 'App\Enum\Education\CycleEnum'
           advanced_education_notation: 'App\Enum\Education\AdvancedEducationNotationTypeEnum'
 
           #billing

+ 8 - 5
config/opentalent/products.yaml

@@ -9,12 +9,14 @@ parameters:
           - ContactPoint
           - PersonalizedList
           - File
+          - Image
           - City
           - Country
           - Tagg
           - Enum
           - LicenceCmfOrganizationER
-          - DownloadRequest
+          - UploadRequest
+          - SubdomainAvailability
         roles:
           - ROLE_IMPORT
           - ROLE_TAGG
@@ -130,6 +132,7 @@ parameters:
             - Categories
             - EventReport
             - AttendanceBooking
+            - AttendanceBookingReason
           roles:
             - ROLE_EVENTS
 
@@ -287,14 +290,14 @@ parameters:
           - Statistic
           - Dolibarr
 
-      artist_premium:
+      artist-premium:
         extend: artist
         modules:
           - MessagesAdvanced
           - TaggAdvanced
 
       school:
-        extend: artist_premium
+        extend: artist-premium
         modules:
           - PedagogicsAdministation
           - PedagogicsSeizure
@@ -306,7 +309,7 @@ parameters:
           - BillingAdministration
           - TemplateMessages
 
-      school_premium:
+      school-premium:
         extend: school
         modules: ~
 
@@ -314,7 +317,7 @@ parameters:
         extend: artist-premium
         modules: ~
 
-      manager_premium:
+      manager-premium:
         extend: manager
         modules:
           - CorePremium

+ 0 - 86
config/packages/docker/monolog.yaml

@@ -1,86 +0,0 @@
-# Voir doc/logging.md
-monolog:
-    channels: ['cron']
-    handlers:
-        # sorties standards (stdout, stderr, console)
-        stderr:
-            type: stream
-            path: php://stderr
-            level: error
-            channels: ["!event", "!doctrine"]
-        console:
-            type: console
-            process_psr_3_messages: false
-            level: debug
-            channels: ["!event", "!doctrine", "!console"]
-
-        # email en cas d'erreurs critiques, sauf erreurs 404 / 405
-#        critical:
-#            type: fingers_crossed
-#            action_level: critical
-#            excluded_http_codes: [ 404, 405 ]
-#            handler: deduplicated
-#        deduplicated:
-#            type: deduplication
-#            handler: mailer
-#        mailer:
-#            type: symfony_mailer
-#            from_email: "process@opentalent.fr"
-#            to_email: "exploitation@opentalent.fr"
-#            subject: AP2I - Critical Error Occurred
-#            level: critical
-#            formatter: monolog.formatter.html
-#            content_type: text/html
-
-        # logging fichier
-        file_main:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%env(LOG_FILE_NAME)%.main.log"
-            level: debug
-            max_files: 3
-            channels: [php, doctrine, http_client, elastica]
-        file_auth:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%kernel.environment%.auth.log"
-            level: debug
-            max_files: 3
-            channels: security
-
-        # logs dédiés à l'exécution des cron-jobs
-        cron:
-            type: group
-            members: [cron_file]
-            channels: cron
-        cron_file:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%kernel.environment%.cron.log"
-            level: debug
-            max_files: 7
-            formatter: monolog.formatter.message
-#        cron_critical:
-#            type:           fingers_crossed
-#            action_level:   critical
-#            handler:        cron_deduplicated
-#        cron_deduplicated:
-#            type: deduplication
-#            # the time in seconds during which duplicate entries are discarded (default: 60)
-#            time: 10
-#            handler: cron_mailer
-#        cron_mailer:
-#            type:           symfony_mailer
-#            from_email:     "process@opentalent.fr"
-#            to_email:       "exploitation@opentalent.fr"
-#            subject:        "Cron - Critical Error"
-#            level:          error
-#            formatter:      monolog.formatter.html
-#            content_type:   text/html
-
-
-        # uncomment to get logging in your browser
-        # you may have to allow bigger header sizes in your Web server configuration
-        #firephp:
-        #    type: firephp
-        #    level: info
-        #chromephp:
-        #    type: chromephp
-        #    level: info

+ 4 - 4
config/packages/doctrine.yaml

@@ -32,11 +32,11 @@ doctrine:
             default:
                 filters:
                     date_time_filter:
-                        class: App\Filter\DoctrineFilter\DateTimeFilter
-                        enabled: true
+                        class: App\Filter\Doctrine\TimeConstraint\DatetimeFilter
+                        enabled: false
                     activity_year_filter:
-                        class: App\Filter\DoctrineFilter\ActivityYearFilter
-                        enabled: true
+                        class: App\Filter\Doctrine\TimeConstraint\ActivityYearFilter
+                        enabled: false
                 connection: default
                 auto_mapping: true
                 mappings:

+ 3 - 1
config/packages/knp_gaufrette.yaml

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

+ 55 - 0
config/packages/liip_imagine.yaml

@@ -0,0 +1,55 @@
+services:
+    opentalent.liip_imagine.binary.loader.stream.profile_photos:
+        class: Liip\ImagineBundle\Binary\Loader\StreamLoader
+        arguments:
+            - 'gaufrette://storage/'
+        tags:
+            - { name: 'liip_imagine.binary.loader', loader: 'stream.storage' }
+
+# Documentation on how to configure the bundle can be found at: https://symfony.com/doc/current/bundles/LiipImagineBundle/basic-usage.html
+liip_imagine:
+    resolvers:
+        my_resolver:
+            web_path: ~
+
+    cache : my_resolver
+
+    # valid drivers options include "gd" or "gmagick" or "imagick"
+    driver: "imagick"
+
+    data_loader: stream.storage
+
+    filter_sets:
+        sm:
+            filters:
+                relative_resize:
+                    widen: 100
+        md:
+            filters:
+                relative_resize:
+                    widen: 300
+        lg:
+            filters:
+                relative_resize:
+                    widen: 800
+        crop_sm:
+            filters:
+                crop:
+                    size: ~
+                    start: ~
+                relative_resize:
+                    widen: 100
+        crop_md:
+            filters:
+                crop:
+                    size: ~
+                    start: ~
+                relative_resize:
+                    widen: 300
+        crop_lg:
+            filters:
+                crop:
+                    size: ~
+                    start: ~
+                relative_resize:
+                    widen: 800

+ 1 - 1
config/packages/mercure.yaml

@@ -4,7 +4,7 @@ mercure:
             url: '%env(MERCURE_URL)%'
             public_url: '%env(MERCURE_PUBLIC_URL)%'
             jwt:
-                secret: '%env(MERCURE_PUBLISHER_JWT_KEY)%'
+                secret: '%env(MERCURE_JWT_SECRET)%'
                 algorithm: 'hmac.sha256'
                 publish: ['*']
 

+ 0 - 1
config/packages/messenger.yaml

@@ -12,7 +12,6 @@ framework:
         routing:
             # Route your messages to the transports
             'App\Message\Command\MailerCommand': async
-            'App\Message\Command\Parameters\AverageChange': async
             'App\Message\Command\Export': async
             'App\Message\Command\Typo3\Typo3UpdateCommand': async
             'App\Message\Command\Typo3\Typo3DeleteCommand': async

+ 103 - 0
config/packages/monolog.yaml

@@ -1,3 +1,106 @@
 monolog:
     channels:
         - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
+        - cron
+
+    handlers:
+        # sorties standards (stdout, stderr, console)
+        stderr:
+            type: stream
+            path: php://stderr
+            level: error
+            channels: [ "!event", "!doctrine", "!cron" ]
+        console:
+            type: console
+            process_psr_3_messages: false
+            level: debug
+            channels: [ "!event", "!doctrine", "!console" ]
+
+        # logging fichier
+        file_main:
+            type: rotating_file
+            path: "%kernel.logs_dir%/%env(LOG_FILE_NAME)%.main.log"
+            level: debug
+            max_files: 3
+            channels: [php, doctrine, http_client, elastica]
+        file_auth:
+            type: rotating_file
+            path: "%kernel.logs_dir%/%kernel.environment%.auth.log"
+            level: debug
+            max_files: 3
+            channels: security
+
+        # email en cas d'erreurs critiques, sauf erreurs 404 / 405
+        #        critical:
+        #            type: fingers_crossed
+        #            action_level: critical
+        #            excluded_http_codes: [ 404, 405 ]
+        #            handler: deduplicated
+        #        deduplicated:
+        #            type: deduplication
+        #            handler: mailer
+        #        mailer:
+        #            type: symfony_mailer
+        #            from_email: "process@opentalent.fr"
+        #            to_email: "exploitation@opentalent.fr"
+        #            subject: AP2I - Critical Error Occurred
+        #            level: critical
+        #            formatter: monolog.formatter.html
+        #            content_type: text/html
+
+        ### --- Cron-Jobs ---
+        # Log fichier (niveau debug)
+        cron_file:
+            type: rotating_file
+            path: "%kernel.logs_dir%/%kernel.environment%.cron.log"
+            level: debug
+            max_files: 7
+            formatter: monolog.formatter.message
+            channels: [cron]
+
+        # Rapport par mail
+        cron_info:
+            type:           fingers_crossed
+            action_level:   info
+            handler:        cron_info_deduplicated
+            channels: ['cron']
+        cron_info_deduplicated:
+            type: deduplication
+            # the time in seconds during which duplicate entries are discarded (default: 60)
+            time: 10
+            handler: cron_info_mailer
+        cron_info_mailer:
+            type:           symfony_mailer
+            from_email:     "mail.report@opentalent.fr"
+            to_email:       "exploitation@opentalent.fr"
+            subject:        "Cron - Execution Report"
+            level:          info
+            content_type:   text/html
+
+        # Log par mail en cas d'erreur critique
+        cron_critical:
+            type:           fingers_crossed
+            action_level:   critical
+            handler:        cron_critical_deduplicated
+        cron_critical_deduplicated:
+            type: deduplication
+            # the time in seconds during which duplicate entries are discarded (default: 60)
+            time: 10
+            handler: cron_critical_mailer
+        cron_critical_mailer:
+            type:           symfony_mailer
+            from_email:     "mail.report@opentalent.fr"
+            to_email:       "exploitation@opentalent.fr"
+            subject:        "Cron - Critical Error"
+            level:          critical
+            formatter:      monolog.formatter.html
+            content_type:   text/html
+
+        # uncomment to get logging in your browser
+        # you may have to allow bigger header sizes in your Web server configuration
+        #firephp:
+        #    type: firephp
+        #    level: info
+        #chromephp:
+        #    type: chromephp
+        #    level: info

+ 1 - 1
config/packages/nelmio_cors.yaml

@@ -3,7 +3,7 @@ nelmio_cors:
         origin_regex: true
         allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
         allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
-        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user']
+        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user', 'profileHash']
         expose_headers: ['Link']
         max_age: 3600
     paths:

+ 0 - 86
config/packages/prod/monolog.yaml

@@ -1,86 +0,0 @@
-# Voir doc/logging.md
-monolog:
-    channels: ['cron']
-    handlers:
-        # sorties standards (stdout, stderr, console)
-        stderr:
-            type: stream
-            path: php://stderr
-            level: error
-            channels: ["!event", "!doctrine"]
-        console:
-            type: console
-            process_psr_3_messages: false
-            level: debug
-            channels: ["!event", "!doctrine", "!console"]
-
-        # email en cas d'erreurs critiques, sauf erreurs 404 / 405
-        #        critical:
-        #            type: fingers_crossed
-        #            action_level: critical
-        #            excluded_http_codes: [ 404, 405 ]
-        #            handler: deduplicated
-        #        deduplicated:
-        #            type: deduplication
-        #            handler: mailer
-        #        mailer:
-        #            type: symfony_mailer
-        #            from_email: "process@opentalent.fr"
-        #            to_email: "exploitation@opentalent.fr"
-        #            subject: AP2I - Critical Error Occurred
-        #            level: critical
-        #            formatter: monolog.formatter.html
-        #            content_type: text/html
-
-        # logging fichier
-        file_main:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%env(LOG_FILE_NAME)%.main.log"
-            level: debug
-            max_files: 3
-            channels: [php, doctrine, http_client, elastica]
-        file_auth:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%kernel.environment%.auth.log"
-            level: debug
-            max_files: 3
-            channels: security
-
-        # logs dédiés à l'exécution des cron-jobs
-        cron:
-            type: group
-            members: [cron_file]
-            channels: cron
-        cron_file:
-            type: rotating_file
-            path: "%kernel.logs_dir%/%kernel.environment%.cron.log"
-            level: debug
-            max_files: 7
-            formatter: monolog.formatter.message
-#        cron_critical:
-#            type:           fingers_crossed
-#            action_level:   critical
-#            handler:        cron_deduplicated
-#        cron_deduplicated:
-#            type: deduplication
-#            # the time in seconds during which duplicate entries are discarded (default: 60)
-#            time: 10
-#            handler: cron_mailer
-#        cron_mailer:
-#            type:           symfony_mailer
-#            from_email:     "process@opentalent.fr"
-#            to_email:       "exploitation@opentalent.fr"
-#            subject:        "Cron - Critical Error"
-#            level:          error
-#            formatter:      monolog.formatter.html
-#            content_type:   text/html
-
-
-        # uncomment to get logging in your browser
-        # you may have to allow bigger header sizes in your Web server configuration
-        #firephp:
-        #    type: firephp
-        #    level: info
-        #chromephp:
-        #    type: chromephp
-        #    level: info

+ 2 - 0
config/routes/liip_imagine.yaml

@@ -0,0 +1,2 @@
+_liip_imagine:
+    resource: "@LiipImagineBundle/Resources/config/routing.yaml"

+ 3 - 0
config/secrets/docker/docker.DATABASE_ADMINASSOS_URL.3cc6e9.php

@@ -0,0 +1,3 @@
+<?php // docker.DATABASE_ADMINASSOS_URL.3cc6e9 on Thu, 16 Nov 2023 10:19:24 +0000
+
+return "\x93\xE5\x8F\xE7\xE0X\x93\xB2dJ\x29\xB7\xF6\x27.\xB4~\x23\xE5\x5B\xCCu\x1E\xDC\x0FO\x28\xDA\x9B\xB5\xDC\x7F\x06\x1E\x8E\xC4\xF6ZrR-\xE1\xCEZ\x3BF\x05\x0C\xBE\xD5\x2B\xFE\x10\x09\xBE\xE9S-\xE7\x21u\xB8w\x99\xD8\xDE\x3F\x11\x81\x12\xFF\x3DV\xEC\x03\x88\x06\xD3\xEA\xB4\xC8\xD8\x00zhKv_\xB3\xB4\x29\xED_\xA3\x8D\x02\x95\x5C\xB1\x94\x90\xD0\x0C\x95\x97\x86";

+ 3 - 0
config/secrets/docker/docker.DATABASE_AUDIT_URL.f1a8d2.php

@@ -0,0 +1,3 @@
+<?php // docker.DATABASE_AUDIT_URL.f1a8d2 on Thu, 16 Nov 2023 10:21:36 +0000
+
+return "\x92\x26\xEA\x07\xB9\xE90\x27\xCCX\x94W\x05\x5D\x1E\xDF\x27\xAFG\xD0\xADx\xF1\x96\x81\x01\xDFE\xAF\xA6\xF4s\x83\x9DL\x02\xFE\x06r\xE5\x5C\xF4\xB4\xBBc\x88\xA1n9\x19\xA5\xD52o\xAE\xAF\xA5Vk\x3Dc\x1Ds\x9E\xFC\xD0\xF2\xAAca\xBD\x93\xC7\x01\xAC\x91N\xD3\xED\xE0\xE1qh\x28\xCD\x83\x3F\x7F\x9A\x9D\xDF\xB8\xCCn\xD7\xE3\x9Ax\x0C\xC9\x27";

+ 3 - 0
config/secrets/docker/docker.DATABASE_URL.8ea85a.php

@@ -0,0 +1,3 @@
+<?php // docker.DATABASE_URL.8ea85a on Thu, 16 Nov 2023 10:15:53 +0000
+
+return "\x7F\xDA\x2FU\xBD1\x01\xBC\xC7\xB8\xA0\xE1\x8EqWN\xD2\xEF\x8B\x00\x88V\x20\x0E\x7B\x12\x3E\xEB6\xD1n\x3E\x9Aaf\x9AS\x7D\x95\x02i\x04\xC0\x1D\x2B\x0F\x16\xFE\xCBF\x29\xF6\xD1R\xFCi\xA3D\xDF\xF3\xAF\xF6T\x2F\xCB4u\x27g\x93\xE1wP\x85v\x9F\x01\x8F\xBF\x82X8\x18\x89\xE5\x7C\xF1\x83\xE8f\xE5\xF3\x0Dc7\x96s_\x0C\x0ETh\x21\x16\x60\x7F";

+ 3 - 0
config/secrets/docker/docker.DOLIBARR_API_TOKEN.bdeaba.php

@@ -0,0 +1,3 @@
+<?php // docker.DOLIBARR_API_TOKEN.bdeaba on Thu, 16 Nov 2023 10:28:37 +0000
+
+return "~\xF1fM\xEC\x7DK-\xD9\x95\x5C\x81\xF5\xA3\x8B\x9B\x1D\x0E\xDBxO\x2C\xC2\x5ET\xAF\xA7Q\x28b\xC6\x1DN\xC53FZ\x00\x02Z\x18q\x99\x15\x28\xBC\xA6c\x17\x1Fn\x21\x5B-Y\x91\x01\xD4\xF2\xDE\x94\xB2\x26\xF6\xFAHQ\x9F\x18\xCB\x29\x26\x23\x84-\x1AS\x3B\x8A\xD0";

+ 3 - 0
config/secrets/docker/docker.MERCURE_JWT_SECRET.88e4d2.php

@@ -0,0 +1,3 @@
+<?php // docker.MERCURE_JWT_SECRET.88e4d2 on Tue, 19 Dec 2023 15:28:57 +0000
+
+return "\x97\x9A\x800T\x24\x94B\xBB\xFE\x5EU\x0E\x08N\xBC\xED\xE6\x09O\x7C\x05\xA5\xEE\xBF\x04EL\x86\xD5KxQ\xDAu\xC4\x06\x96\xADj\xCF\x98\xAE\xCCT\x1C\xD6H\xD5\x3Duw\xDD\xDE\xD8\xBDu\xAE\x22\xEF\x12\xCAU\xC4\xE9\x5D\x8Aj\xBE\xB0\x18\x15\x8F\x8B\xFBy\xD1\x08\x7D\x9Cw\xBEy\xFD\x12\xA0\xD9a\x13\xCCxS\x25\xD2\x27\xC7\x8Co\x0FW\xC0a\x81\xEEj\x8En\xB1\xC3Ca\xCA\xDD\xB0\xD5\xB9\x20\xF4\xF8\xC9\xBDGN\xCD\x81\xFEF\xDE\x28\x8B\x0B\xA1\xDE\x1C\xA2\x88\xC0\xE9\xBE\x7C\x03\x3Dc\xE0\x86\x08\x3D\xFAUG\x26\x95l\xE0\xC1H5\x08Rt\x94\xD8\xDE\xAF\xDB\x9F\x27\xFE\x10\xE6W\xCB\xDF\x3A\x2A\xB2\x9D\xE6\x89\xD9\x15\x18Ox\xF2\x0C\x853\xC6i\xB2a\x8D\x92f\x40gt9X\x2F\x90vK\x06\x28\xAF\xF4q\x0D\x1E\xDA\x0D\xC68\xD9\x21\x8B\xDC\x60\xDE\x29\xDE\xA8O\xF6\x0CVE1\x0F\xAE\x9DC\xEB\xC9\xB7\x8B\xAE\x3Bq\x7Dr\x85\x7Dv\xB0n\x8F\x94\x3EI\xC2\xFF\x3A\xF9\xD2\xC6d\xE5\xAA\x9A\x98\xA1\x91\x11\x23\xE2\x02\x9A\xA5\x29o\x28\x13E\xAD\x3F\xC6bg\x20\x0E\x9E\xDA\xDA\xF3\xE2\xC5E2V\x82\xFF\xD4W\xC6I\xC6\xDD\x19\xA6\x8DR";

+ 4 - 0
config/secrets/docker/docker.decrypt.private.php

@@ -0,0 +1,4 @@
+<?php // docker.decrypt.private on Thu, 16 Nov 2023 10:08:31 +0000
+
+// SYMFONY_DECRYPTION_SECRET=7omNksoSvy9aANXer7SmAB87Mup7gcTdtvkZXFaakCgPiNt/KfT24LCON4fMz0g/7Rx2cqkOHV3EsRFjFvS3LA==
+return "\xEE\x89\x8D\x92\xCA\x12\xBF\x2FZ\x00\xD5\xDE\xAF\xB4\xA6\x00\x1F\x3B2\xEA\x7B\x81\xC4\xDD\xB6\xF9\x19\x5CV\x9A\x90\x28\x0F\x88\xDB\x7F\x29\xF4\xF6\xE0\xB0\x8E7\x87\xCC\xCFH\x3F\xED\x1Cvr\xA9\x0E\x1D\x5D\xC4\xB1\x11c\x16\xF4\xB7\x2C";

+ 3 - 0
config/secrets/docker/docker.encrypt.public.php

@@ -0,0 +1,3 @@
+<?php // docker.encrypt.public on Thu, 16 Nov 2023 10:08:31 +0000
+
+return "\x0F\x88\xDB\x7F\x29\xF4\xF6\xE0\xB0\x8E7\x87\xCC\xCFH\x3F\xED\x1Cvr\xA9\x0E\x1D\x5D\xC4\xB1\x11c\x16\xF4\xB7\x2C";

+ 9 - 0
config/secrets/docker/docker.list.php

@@ -0,0 +1,9 @@
+<?php
+
+return [
+    'DATABASE_ADMINASSOS_URL' => null,
+    'DATABASE_AUDIT_URL' => null,
+    'DATABASE_URL' => null,
+    'DOLIBARR_API_TOKEN' => null,
+    'MERCURE_JWT_SECRET' => null,
+];

+ 3 - 0
config/secrets/prod/prod.DATABASE_ADMINASSOS_URL.3cc6e9.php

@@ -0,0 +1,3 @@
+<?php // prod.DATABASE_ADMINASSOS_URL.3cc6e9 on Thu, 16 Nov 2023 10:19:48 +0000
+
+return "a\x7B\x7F\x82\x0A\xC3m\xE6\xC8R\xE6\xC8\x1F\x409\xC5\x23\xEC\x21\xBC\xB2\x0F\xC5.E\x0FU7T\x3F\xA7wk\x9Da\xAFAg\x06\x06GYB\xB4\xFC\xA1\x16R\xD5\xA1o\xD5sR\x27\x02\x97\xA2\x85U\xEC\x80o\x87j\xEE\x40pB\x2C5H\x2FhY\xCCS\x80\xF9\x23Z\xAF\xEE\x1F\x1B\x88\xFC\xC1\x03\x40\xADr\xA55\x21\x8B\xA6\xF2\x8A\x88\xF8\x0E\x02\x5BO\x05\x03\xF2\xBB\x18\xF3\xAF\xC6x\xE7\xFE\xB9D\xC5\x92\xCE\x1DcP\x3Fn\xF8\x15\xA0";

+ 3 - 0
config/secrets/prod/prod.DATABASE_AUDIT_URL.f1a8d2.php

@@ -0,0 +1,3 @@
+<?php // prod.DATABASE_AUDIT_URL.f1a8d2 on Thu, 16 Nov 2023 10:22:22 +0000
+
+return "\xDFp\xA4\xE9\xF5\x01-\x5B\x7F\x8A\xC6\xC37\x953u\xB0\x0D9\x9B\x7COUX4J\x0E\xA2\xA1\xE3\x95\x21\xA1\xF5\xE3\x5EO\x3E\xD2Ih\xD3\xF6\x7D\xD6\x25\xA3\x08\x22\x91\xA1\xEB\x99O\x0C\x2A\xE1\xAA\xBC\xAC~\xEAX\x8A\x00\xF2P\xEE\xDC\x8E\xEB\x84\x3E\x04b\xA8\x02\x25DwI\xAF\x40\xC4B\x9A\x84\xC2\xA8\x8F\xF94\x5C1jW\xEA\xDAp\x7C\xDD\xEE9\xE7\xE6\xFA\x83\x13c\x8D\xC4Xb\x09\xE5W\x7D\x08\xDC\xA8l\xDE\xCCy";

+ 3 - 0
config/secrets/prod/prod.DATABASE_URL.8ea85a.php

@@ -0,0 +1,3 @@
+<?php // prod.DATABASE_URL.8ea85a on Thu, 16 Nov 2023 10:16:28 +0000
+
+return "\xB7\x28\x0A\x29\xD7j\xD2\x271\xEDp\xDB\x9Es\xD33S\x2F\xDF\xFB\xA44\x10\x97\xA8\xA33R\x1Fkc\x10\x15\xE1\xEB3\x16W\xB5\xB0\xD0\x99\x09\x7D\xF6\xD0\xF6\x1B\xD0KC\xD96n\xD1\xC5\xEAH\x09\xD7\xBF\x9C\xDE\x0B\xD995C\x1Cw\xC4\x91\xC2\x27\xEE\xB5.u\x60A\xA4\xFBSP\x9CS\xE6t\x0AC\x26\xE6\xD5\x40\xA2\x7B\xA7\xE02\xB6\x90D\xAD\x28\xA4V\xDEF\x90\xBDB\xC6\xE9\xC6\x22\x81S\xD6\x23\xDA\xCD\xF4\x18ur\x7DDu\x1E";

+ 3 - 0
config/secrets/prod/prod.DOLIBARR_API_TOKEN.bdeaba.php

@@ -0,0 +1,3 @@
+<?php // prod.DOLIBARR_API_TOKEN.bdeaba on Thu, 16 Nov 2023 10:28:49 +0000
+
+return "\x00\x9FWd\xFE\xFA\x11\xDA\x91\x1A\x5BxB\xB4\x95B\x28\xE7\xC0\xF8\xF4w\xB9\x84\xAB\x97\x91\xD4\xFF\x8CE\x40\x08D\xB7\xBD\xD5\x02\xD7\xA0.\x18\xE1\xEC\x84\xB1\x12-A.\x5E\x5B\x1D-\xEAI\xC2_\x80pw\xCB\xB1\x8D\x87Y\xAA\xEC\xED\xF9O\x16\xAES\x25\xCAG\x7C\x0D\xDC";

+ 3 - 0
config/secrets/prod/prod.MERCURE_JWT_SECRET.88e4d2.php

@@ -0,0 +1,3 @@
+<?php // prod.MERCURE_JWT_SECRET.88e4d2 on Tue, 19 Dec 2023 15:29:48 +0000
+
+return "f\x0D2\x9D\x3FOGF\x06\x26t\x2F\x23\x85\xEB\x8D\xB3\x8F\x05t\xA3e\xC5\xD2Qb\x16\xFC\x2C\xA3\x12\x16zL\xF3\x2C\xFC\xB8\xF5\xC9~\x06\xFA\xD2\x13\xB5\x19I\x5B\x1F\x9Ff\xDF\x10k\x04\xC6\xF6\xAC\x25\xA1\xC4\xFA\x95\xF4\xF1-\xB7\x97\xD9c\x25\xB2\xE6\xA8\x16\xA4M\x06\x13\x9B\xB6\xB8\xE0\x60\xA0\xFB\x8F\xED\x17\xC4\xFD\x1C\xFD8\xA0\xA4\x3A\x8A\x89\xC3\x13s\x96\x25\xC9B\x8B\xFB\xA7\xAEsZM\x0Cu\xCA\x1A1\xE1K\xF9DB\xD10t\xA3\x24\x9A\x9C\x1D\xE9q\x7C\x23wq\x3D\x2F\xE3\xBD\xC93r\x8D\xEEd\xEF4\x98\xD9\xCF\xC8\x7F\xF2\xC2\xE7\xE6\x19\x7D\x8E\xCB\xCD\xFFR\xB9N\x04\x2AG\x60\x0E\x1BX\x40\xF5\xFD\x80\xA9\xE0\x27\xD2BP\x60\x2A\xF8\x06\x80\xC4\xD4\xB7\x5E-\xD5\xC4g\x9A\xDD.\x87\x2C\xA9\xD0\x82\xB3\xBE\x03\xF2M\x10s\x80\xC3Y\x82\x8D\x7D\x9A\x90\xABk\x1E\x7B\x5C\xA8i\xD2\xC9N\xA6f\x15\xA3\xB8T\xDEJ\x22n\xD7\x24\x06\xF8\xA8\xAAx\xBE\xB5\x26\xAF\x1B\x0E\xF7\xCD\xC63\xA8N\x1D\xD1\xC1F\x95\x1F\x2Fk\xC5\x24\xAC\x29\x2A\x1C\xB94\xB3\x81\xB5\xAB\x8F\x60\x076\xBE\x80\xAFb\xA6\xED\x99\xE7\x95\x91\x0B\x10\xEB\x85xf\xBB\xDE\x3AS";

+ 3 - 0
config/secrets/prod/prod.encrypt.public.php

@@ -0,0 +1,3 @@
+<?php // prod.encrypt.public on Thu, 16 Nov 2023 10:14:08 +0000
+
+return "\x5C\x82\x00\xA7\xAE\x2F\xF3\xAC\xC09\x0D\xE9\x8F\x7D\xF0LU\x82\x3A\x12\x3A\xDF\xC4r\xA2\x80\x95\xD4\x3B\x21ls";

+ 9 - 0
config/secrets/prod/prod.list.php

@@ -0,0 +1,9 @@
+<?php
+
+return [
+    'DATABASE_ADMINASSOS_URL' => null,
+    'DATABASE_AUDIT_URL' => null,
+    'DATABASE_URL' => null,
+    'DOLIBARR_API_TOKEN' => null,
+    'MERCURE_JWT_SECRET' => null,
+];

+ 3 - 0
config/secrets/readme.md

@@ -0,0 +1,3 @@
+# Env files
+
+> @see doc/env.md

+ 3 - 0
config/secrets/staging/staging.DATABASE_ADMINASSOS_URL.3cc6e9.php

@@ -0,0 +1,3 @@
+<?php // staging.DATABASE_ADMINASSOS_URL.3cc6e9 on Thu, 16 Nov 2023 10:20:30 +0000
+
+return "\x13\x02-\xC7\xE3\x17\xB2\x93\x11\x7D\xBD\xF8mS\xF0\x3D\x99\xCFc\xD7\x0E\x3C\xBE\x88r\xBCP\xA6\xC5f\xB9\x3A\xFDK\x29\xECD\xED\xE9\x2FPS\x10\x99\x25\x92\x0B8\xDE\x18l_\x1F\xFD\x13\xA7E\x9F\xD5\xDEAk\x2B\xF9\xB5\x17Q\xAD\x86\xF1\x0F\xD7\x3B\x0Ch\xE9\xEC\x08\xCE\xDB0\xD0\xF4\xCA\xA8\x92\xC7\xFD\x2C\x02\x83\xDC\x3C\xA6\x00\xBB\xEE\xD0\x7F\x17\x92\x2B\xB4e\xE7\xEA\x10\x9EM\x9E\xE2";

+ 3 - 0
config/secrets/staging/staging.DATABASE_AUDIT_URL.f1a8d2.php

@@ -0,0 +1,3 @@
+<?php // staging.DATABASE_AUDIT_URL.f1a8d2 on Thu, 16 Nov 2023 10:22:51 +0000
+
+return "5\x7D\x9C\xDF\x25\xF56\x81\xE8N\xDA\xB0\xA2\xCB\xCD\xDC\xD4\x12\x22O\x80\x0D\x22B\x09_\x0C\x02\xDE6\x2A8\xB5\xEB8m\xF9i\xF4\xED\x10\xBA\x18f\xA7\x13\x86\x27\xF0A\xE4\xDA\xFAY\x7B\xE3\x9D\x84\xBD\xED\x29\xC7\x15\x0B\xCC\xC0\x10\xE9\x87\x10\xDER\xB2\xBE\x1E\xC1\x29\xBFP\xEE\x82\x0D\x94C\xA4f\xABi\xD6\x0C\x3D\xC0\xA0\x7D\x2Bz\x223\x93\xC6\xF9\xF1.\x88\xD8\xFD";

+ 3 - 0
config/secrets/staging/staging.DATABASE_URL.8ea85a.php

@@ -0,0 +1,3 @@
+<?php // staging.DATABASE_URL.8ea85a on Thu, 16 Nov 2023 10:17:49 +0000
+
+return "\x21\xF6\x09\x5Ce\xF2A\x21\xA3\xCDv\x0B\x07\x86\xC1\x5Dy\xD1\xCC\xE5\x1A\xE7Z\x1D\x0B\xCA\x11\x0C-v5\x05k\xAC\xAB\x20.\x244\x04\xEA\xB9\xB5\xFF\x07\x21\xCA\x17\xE68\xD2\x1A\x0C\x20\x98L\xD8\x0A\xC3A\xE3tl\xA1\x3C\x8B\x21k\x9F\x1AK\x5D\xAA\xE5\xCE\x0A\x3D\x90\xE3\x1F\xD1\xE9N\x7F\xA0\x28\xB0\xA1D5\xF5\xBB\x5E\xD8\x99\xCB\xAF\xD7\x23\x0F\x2A\xC2\xB3F\x8D\xBAef\x3D\xC2\xC5";

+ 3 - 0
config/secrets/staging/staging.DOLIBARR_API_TOKEN.bdeaba.php

@@ -0,0 +1,3 @@
+<?php // staging.DOLIBARR_API_TOKEN.bdeaba on Thu, 16 Nov 2023 10:31:36 +0000
+
+return "\x14\x1D0\x3A\xFD\xB0t\x09\x85\xF6Z\xFCe\x94Q\x93\xF4\xB0\x7FC\x8D\x96\x93\x12\xE6\xF9\x89\xF7\x9A\xE0\x8F2\x95x\xEE\xDC\xA27\x3B\x23\xC0\x3A\x3C\xFC\xEA\xFD\x865S\xB5\xE6";

+ 4 - 0
config/secrets/staging/staging.decrypt.private.php

@@ -0,0 +1,4 @@
+<?php // staging.decrypt.private on Thu, 16 Nov 2023 10:17:25 +0000
+
+// SYMFONY_DECRYPTION_SECRET=XLWVeOSrseUae7uUxswNnWdmCI+CoYP4sHhaYOZuByHjVy53OLwZUpkzmLnFHf9GWm4Ta0NTss7Gy2rbf9gSSg==
+return "\x5C\xB5\x95x\xE4\xAB\xB1\xE5\x1A\x7B\xBB\x94\xC6\xCC\x0D\x9Dgf\x08\x8F\x82\xA1\x83\xF8\xB0xZ\x60\xE6n\x07\x21\xE3W.w8\xBC\x19R\x993\x98\xB9\xC5\x1D\xFFFZn\x13kCS\xB2\xCE\xC6\xCBj\xDB\x7F\xD8\x12J";

+ 3 - 0
config/secrets/staging/staging.encrypt.public.php

@@ -0,0 +1,3 @@
+<?php // staging.encrypt.public on Thu, 16 Nov 2023 10:17:25 +0000
+
+return "\xE3W.w8\xBC\x19R\x993\x98\xB9\xC5\x1D\xFFFZn\x13kCS\xB2\xCE\xC6\xCBj\xDB\x7F\xD8\x12J";

+ 8 - 0
config/secrets/staging/staging.list.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'DATABASE_ADMINASSOS_URL' => null,
+    'DATABASE_AUDIT_URL' => null,
+    'DATABASE_URL' => null,
+    'DOLIBARR_API_TOKEN' => null,
+];

+ 3 - 0
config/secrets/test/test.DATABASE_ADMINASSOS_URL.3cc6e9.php

@@ -0,0 +1,3 @@
+<?php // test.DATABASE_ADMINASSOS_URL.3cc6e9 on Thu, 16 Nov 2023 10:20:08 +0000
+
+return "a\xD9\x08bvL\xE5J\xF3\x40\x00y\xDER\xC8\xC2~\xF3\x97G\x25\x2A\xFF\x8A\xFF\xFF\x9FwQ\x9B\xE7GL\xD2\x84\x0CS\xE3\xF9\xD4\x83\xB4\xC0\x05\xFC\xAEW\xEE\x9B\xC5\xC1\x8F\xEDj\xA3.\xD6\x09\x40\x90\xC7\xDAU\xDE\xB1\x8Clg\x9C\xA6\xCE\xCF\xA0J\x13\x22\x0Bx\xB6x\x97o\x60\xF4h7\x0D\xF4I\x93\x3B\x8B\x88\x00\xC3V\xF4\x3FA\xFB\xBA\x8AX\x24\xD9\x9D\xF1\xA4\x16\x3C\xFA\xC8wS\x13p94z\xEE\xA3\x3C\xC0R";

+ 3 - 0
config/secrets/test/test.DATABASE_AUDIT_URL.f1a8d2.php

@@ -0,0 +1,3 @@
+<?php // test.DATABASE_AUDIT_URL.f1a8d2 on Thu, 16 Nov 2023 10:22:36 +0000
+
+return "\xA2\x7F\xD6\x0B5\xA0p\x11\x89\xFA4d\xF7\xEC\x8FN\x11\xF8\xF2\x87q\xEAb\xB9\xF6\x3C.\x14j\x2B\x2B\x00lv\xD6zY\xB6\xF7\x8E\xB86\xFC\xBA\x2C\xAB\xB5\x87\x16\xE3\x2F\x90K\xC7\x92\xB8_Hq\xAE\xDC\xA2Rq\xE2o\x1Cq\xD5\xC1\x11\x1C\xF4D\xDD\x9F\xBC\xBC\x7B\x1F\x3A\xE3\x96\x1A\xEC\x5C\x04\x1D\xA0\x5B\xC1Lm8\x21\x0F5\x0D\xD6\xCB\x11\x25\xAC\x1C\x3DG\xD0\xCA\x95\xB3\x08A\x0F\xD9\x19\xA3\x06\xE1\x9F";

+ 3 - 0
config/secrets/test/test.DATABASE_URL.8ea85a.php

@@ -0,0 +1,3 @@
+<?php // test.DATABASE_URL.8ea85a on Thu, 16 Nov 2023 10:17:09 +0000
+
+return "h1\x9Dv\xE2\x1C\x5D5Slnf\xE8\x22_\x22\xF7\x021\x21\xE3\x1C\xA9pQr\xA3E\x7D\xEAr\x3F\x5C3_j\x86\x0F\x28L\xA8uy\x0C\xB33c\x24I\xE0\x18\xEFo\x8D\xAE\x3F7\x1B\x2Af\xA9BH\x1F\x85\xDBO\xEDg\xCD\xD5vA\x13\x2F\x18\xD0\x5D\xB9\xA4B\x2C\xBBm\x87\xA6\x85L\x8AV\xF8Z\xC0O\xB8\xFC\x91\xAD\xF8\xC7\x1C\xDA\xD9_\xB7\x9F\xD4\xF9~.G\x9ErY\x7B\xAF\x07\xB3\x83\x05o\x83\x3B\xEFv\xC0\x21\x1B\x40";

+ 3 - 0
config/secrets/test/test.DOLIBARR_API_TOKEN.bdeaba.php

@@ -0,0 +1,3 @@
+<?php // test.DOLIBARR_API_TOKEN.bdeaba on Thu, 16 Nov 2023 10:29:33 +0000
+
+return "\xEB\x0D\xEAp\xCA\xD9\x19\xCD\xD9\x13\xA1\x955\x83\xC8\xED\xE07\xE6\xCF6\x26\xAE\x0Eq7\xEAH\xCD\xE7\xC65B\xFC\xDB\x10\xAC\xED\xF5j\xA1S\x94\xE8Z\xD3\xCF\xE0\x93\xAB\xD7\x17\xE0\x9Bk\xC9c\x0CL\xF1H\x0E\x15yF\xFB\xEE\x97\xD3\xFB\xAC\xAEw1\x8D\x9EI8N\xC8";

+ 3 - 0
config/secrets/test/test.MERCURE_JWT_SECRET.88e4d2.php

@@ -0,0 +1,3 @@
+<?php // test.MERCURE_JWT_SECRET.88e4d2 on Tue, 19 Dec 2023 15:30:04 +0000
+
+return "\x7Fp\xD9\xB7\x3A\x08\x87\x3CB\x28W\x23\x40\xCD\x2B\xB7\xCE\xB3\xC9\x93\xDA\xDC\x7F1l\x22\xB8\xE2\xD8\xB6p~K\xD8\x88N\xA9E\x8A\xBD\x1B\xE3\xD6\xB67\xB9\xD6\xD7\xA4\x82Qh\xDB\x9B\x20\xC0\xF1r\xA0\x2F\xF3\x05\xE2\xEF\x10\x3C\xAB\x09\xD1\x07\x86\xCD\x26\x60\x8D\xDE\xC9\xBD\xCE~\xD6\xA8\xCA\xDB\xB4\x15\x9F\xE8\xE0\x91Q\xE7\xC9\x899l\xB0q\xA3\x94\x9B\x98\x26\x2A\xF4\x7B\x29\xF7\xC4\x8F\x84A\xBAR\x2B\x8Blk\xA1\x1Az\xFE\xA8\x7B\xC8\x98oY\x18o\xF7\x15\x22\xFE\x2B\x87w\x5B\x98\xD0\xC5\xD3\x0C\xC5\x08\x28\xB4\x19\xD8\x1F\x9F\xC5\x07_\x5D\xE8\xE1\x9B\x60\xED\xA6\x0F\xF4j\xB7\xE7J\x80\xA4\xBD\xD0\xFF\xB5\x26\x8F\x17\xC7\xBA6eO\x99\x86\x93\x5D\xCD\xCFm\xFC\xC8U\xD1\xDCb\xE7q\xDCf\xAD\xE2\xAEn\xF9\xA6I\x2C9\xF3a\xC4Y\xB95\x10\x18\x83\xBDg\x2CX\xDF\xFE\x02zk\xC4M\x12\x13Y\x9A_\x03\x1CD2\xE7z\xCBpq\x94\xD27\x5C\xB0\x27\xA4\xEA\x12\x7D\x03\x17\x3F\xFB\xBB\xD3\xE7\x0B\xE8\xE3\x9D\x8A\xC6\xD0\x91\x853\x23J\xB8\x03\xC8\x0B\xB1\x7BMu\xFDAI\x9B\xCD\xAE\x02\x89\x851\xEA\x9E\xC5\xF5\x191\xA1\x09\xA6\x09\xE82\x09\xD7LC";

+ 4 - 0
config/secrets/test/test.decrypt.private.php

@@ -0,0 +1,4 @@
+<?php // test.decrypt.private on Thu, 16 Nov 2023 10:13:56 +0000
+
+// SYMFONY_DECRYPTION_SECRET=U/ZT3zSbTufU3kD1t528eRUvRD/6J2CviMj0qKvN+Olw+z8L2R8FMAJCwWcwUtheJEwNepPoJj09ME5xQw9kcQ==
+return "S\xF6S\xDF4\x9BN\xE7\xD4\xDE\x40\xF5\xB7\x9D\xBCy\x15\x2FD\x3F\xFA\x27\x60\xAF\x88\xC8\xF4\xA8\xAB\xCD\xF8\xE9p\xFB\x3F\x0B\xD9\x1F\x050\x02B\xC1g0R\xD8\x5E\x24L\x0Dz\x93\xE8\x26\x3D\x3D0NqC\x0Fdq";

+ 3 - 0
config/secrets/test/test.encrypt.public.php

@@ -0,0 +1,3 @@
+<?php // test.encrypt.public on Thu, 16 Nov 2023 10:13:56 +0000
+
+return "p\xFB\x3F\x0B\xD9\x1F\x050\x02B\xC1g0R\xD8\x5E\x24L\x0Dz\x93\xE8\x26\x3D\x3D0NqC\x0Fdq";

+ 9 - 0
config/secrets/test/test.list.php

@@ -0,0 +1,9 @@
+<?php
+
+return [
+    'DATABASE_ADMINASSOS_URL' => null,
+    'DATABASE_AUDIT_URL' => null,
+    'DATABASE_URL' => null,
+    'DOLIBARR_API_TOKEN' => null,
+    'MERCURE_JWT_SECRET' => null,
+];

+ 7 - 5
config/services.yaml

@@ -13,6 +13,7 @@ services:
         autowire: true      # Automatically injects dependencies in your services.
         autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
         bind:
+            $projectDir: '%kernel.project_dir%'
             $opentalentConfig: '%kernel.project_dir%%env(OPENTALENT_CONFIG)%'
             $internalFilesUploadUri: '%env(INTERNAL_FILES_DOWNLOAD_URI)%'
             $internalRequestsToken: '%env(INTERNAL_REQUESTS_TOKEN)%'
@@ -20,6 +21,8 @@ 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)%'
 
     # makes classes in src/ available to be used as services
     # this creates a service per class whose id is the fully-qualified class name
@@ -71,6 +74,8 @@ services:
             tags: [ 'twig.extension' ]
         App\Service\Cron\CronjobInterface:
             tags: [ 'app.cronjob' ]
+        App\Service\File\Storage\FileStorageInterface:
+            tags: [ 'app.storage' ]
 
     App\Service\ServiceIterator\CurrentAccessExtensionIterator:
         - !tagged_iterator app.extensions.access
@@ -82,8 +87,8 @@ services:
         - !tagged_iterator app.encoder
     App\Service\ServiceIterator\Mailer\BuilderIterator:
         - !tagged_iterator app.mailer.builder
-    App\Service\ServiceIterator\CronjobIterator:
-        - !tagged_iterator app.cronjob
+    App\Service\ServiceIterator\StorageIterator:
+        - !tagged_iterator app.storage
 
     #########################################
     ##  SERIALIZER Decorates ##
@@ -102,9 +107,6 @@ services:
 
     #########################################
     ##  LISTENER ##
-    App\EventListener\DoctrineFilter\DoctrineFilterListener:
-        tags:
-            - { name: kernel.event_listener, event: kernel.request }
 
     #########################################
     ##  ELASTIC SERVICE ##

+ 37 - 0
doc/cron.md

@@ -0,0 +1,37 @@
+# Crons
+
+## La commande `ot:cron`
+
+Les taches planifiées (crons) sont exécutées au moyen de la commande suivante, où jobs est le nom du job 
+à effectuer (ou une liste de noms de séparés par des virgules): 
+
+    bin/console ot:cron run <jobs>
+
+Pour lister les jobs disponibles : 
+
+    bin/console ot:cron list
+
+Pour plus d'informations : 
+
+    bin/console ot:cron --help
+
+> À noter : tous les jobs implémentent une méthode preview qui peut être exécutée en passant l'option -p, --preview 
+> à la commande.
+
+## Créer un nouveau job
+
+Pour ajouter une nouvelle tâche exécutable, créer simplement une nouvelle classe dans le répertoire src/Service/Cron/Job. 
+Cette classe doit hériter de \App\Service\Cron\BaseCronJob.
+
+Le nom du job sera déduit du nom de ce nouvel objet (`MyCron` deviendra `my-cron`)
+
+Cette classe devra implémenter les méthodes `preview` et `execute` telles que définies dans 
+l'interface \App\Service\Cron\CronjobInterface.
+
+La commande `ot:cron` s'occupera pour vous de :
+
+* locker le process pour interdire l'exécution simultanée de deux jobs du même nom
+* mesurer les temps d'exécution
+* assurer la gestion d'erreur du job
+* le logging et l'envoi d'un mail en cas d'erreur critique
+* le retour d'une valeur de succès ou d'erreur selon le résultat du job

+ 51 - 6
doc/env.md

@@ -6,21 +6,66 @@ Les variables d'environnement sont définies dans les fichiers .env (dotenv)
 
 ### Principe général
 
+#### Les fichiers d'environnement
+
 Les fichiers dotenv s'organisent ainsi :
 
-Un fichier `.env` commun à tous les environnements, il définit des valeurs par défaut.
+* Un fichier `.env` commun à tous les environnements, il définit des valeurs par défaut.
+* Un fichier `.env.local`, non versionné, qui surcharge le fichier `.env` avec les données propres à l'environnement local.
+
+Il existe d'autres manières de surcharger le fichier d'environnement, mais elles ne nous seront pas utiles ici.
+
+#### Variables secrètes
+
+Certaines informations sensibles sont stockées de manière cryptée, telles que les informations permettant l'accès aux 
+bases de données. Toutes ces données sont stockées par environnement dans le répertoire `config/secrets`.
+
+Pour mettre à jour une variable secrète : 
+
+    bin/console secrets:set MY_SECRET_VAR
+
+Pour plus d'informations sur le fonctionnement des secrets : https://symfony.com/doc/current/configuration/secrets.html
+
+### Mise en pratique
+
+#### Génération du symlink vers le fichier d'environnement
+
+On trouve dans le répertoire `env` des fichiers `.env.<environnement>` correspondant aux différents environnements 
+de développement, test, production, etc.
 
-Un fichier `.env.local` : il ne doit **pas** être versionné et contiendra des variables propres à l'environnement local.
-C'est lui qui définit le nom de l'environnement, par exemple : 
+Lorsque la commande `composer install|update` est exécutée, la commande `bin/console ot:setup:env` s'exécute en post-
+script et génère un symlink `.env.local` à la racine du projet.
 
-    APP_ENV=prod
+Pour forcer la mise à jour du fichier d'environnement : 
 
-Un fichier `.env.<environnement>` qui ne s'appliquera qu'à l'environnement donné. Cet environnement est défini par la 
-variable d'environnement `APP_ENV` (voir plus haut).
+    bin/console ot:setup:env
 
+Ce symlink pointe vers le fichier d'environnement correspondant à la machine hôte.
+
+On peut forcer un nom d'hôte avec l'option `--host`. Ex : 
+
+    bin/console ot:setup:env --host=ci
+
+Ou en définissant une variable d'environnement `HOST` :
+
+    HOST=ci bin/console ot:setup:env
+
+#### Génération du fichier des variables secrètes
+
+Par ailleurs, la commande `bin/console secrets:decrypt-to-local --force` est aussi exécutée, et génère un fichier
+`.env.{env}.local` contenant les variables secrètes. (@see https://symfony.com/doc/current/configuration/secrets.html#deploy-secrets-to-production)
+secrètes
 
 ### Déboguer
 
 Les variables d'environnement actives peuvent être affichées au moyen de la commande :
 
     php bin/console debug:container --env-vars
+
+Les variables secrètes peuvent être lues avec :
+
+    php bin/console secrets:list --reveal
+
+Ou pour un autre environnement : 
+
+    APP_RUNTIME_ENV={env} php bin/console secrets:list --reveal

+ 0 - 20
docker-compose.override.yml

@@ -1,20 +0,0 @@
-version: '3'
-
-services:
-###> doctrine/doctrine-bundle ###
-  database:
-    ports:
-      - "5432"
-###< doctrine/doctrine-bundle ###
-
-###> symfony/mailer ###
-  mailer:
-    image: schickling/mailcatcher
-    ports: ["1025", "1080"]
-###< symfony/mailer ###
-
-###> symfony/mercure-bundle ###
-  mercure:
-    ports:
-      - "80"
-###< symfony/mercure-bundle ###

+ 0 - 44
docker-compose.yml

@@ -1,44 +0,0 @@
-version: '3'
-
-services:
-###> doctrine/doctrine-bundle ###
-  database:
-    image: postgres:${POSTGRES_VERSION:-15}-alpine
-    environment:
-      POSTGRES_DB: ${POSTGRES_DB:-app}
-      # You should definitely change the password in production
-      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
-      POSTGRES_USER: ${POSTGRES_USER:-app}
-    volumes:
-      - database_data:/var/lib/postgresql/data:rw
-      # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
-      # - ./docker/db/data:/var/lib/postgresql/data:rw
-###< doctrine/doctrine-bundle ###
-
-###> symfony/mercure-bundle ###
-  mercure:
-    image: dunglas/mercure
-    restart: unless-stopped
-    environment:
-      SERVER_NAME: ':80'
-      MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
-      MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
-      # Set the URL of your Symfony project (without trailing slash!) as value of the cors_origins directive
-      MERCURE_EXTRA_DIRECTIVES: |
-        cors_origins http://127.0.0.1:8000
-    # Comment the following line to disable the development mode
-    command: /usr/bin/caddy run --config /etc/caddy/Caddyfile.dev
-    volumes:
-      - mercure_data:/data
-      - mercure_config:/config
-###< symfony/mercure-bundle ###
-
-volumes:
-###> doctrine/doctrine-bundle ###
-  database_data:
-###< doctrine/doctrine-bundle ###
-
-###> symfony/mercure-bundle ###
-  mercure_data:
-  mercure_config:
-###< symfony/mercure-bundle ###

+ 7 - 21
.env.docker → env/.env.docker

@@ -1,33 +1,21 @@
 ###> symfony/framework-bundle ###
+APP_ENV=dev
 APP_DEBUG=1
 ###< symfony/framework-bundle ###
 
-###> doctrine/doctrine-bundle ###
-DATABASE_URL=mysql://root:mysql660@db:3306/opentalent?serverVersion=5.7
-###< doctrine/doctrine-bundle ###
-
 ###> nelmio/cors-bundle ###
-CORS_ALLOW_ORIGIN=^https?:\/\/(localhost|127\.0\.0\.1|(local.(admin|app|app\-v3|frames|frames_v3|agenda).opentalent.fr))(:[0-9]+)?$
+CORS_ALLOW_ORIGIN=^https?:\/\/(localhost|127\.0\.0\.1|(local.(admin|app|app|frames|agenda|maestro).opentalent.fr))(:[0-9]+)?$
 ###< nelmio/cors-bundle ###
 
 ###> api v1 ###
 API_LEG_BASE_URL=http://nginx/
+PUBLIC_API_LEG_BASE_URL=https://local.api.opentalent.fr
 ###< api v1 ###
 
-###> BlackFire configuration ###
-BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
-BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
-BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
-BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
-###< BlackFire configuration ###
-
-###> AdminAssos configuration ###
-DATABASE_ADMINASSOS_URL=mysql://root:mysql660@db:3306/adminassos?serverVersion=5.7
-###< AdminAssos configuration ###
-
-###> Audit configuration ###
-DATABASE_AUDIT_URL=mysql://root:mysql660@db:3306/audit?serverVersion=5.7
-###< Audit configuration ###
+###> api v2 ###
+API_BASE_URL=http://nginx_new/
+PUBLIC_API_BASE_URL=https://local.ap2i.opentalent.fr
+###< api v2 ###
 
 ###> typo3 client ###
 TYPO3_BASE_URI=http://docker.sub.opentalent.fr
@@ -39,8 +27,6 @@ TYPO3_BASE_URI=http://docker.sub.opentalent.fr
 MERCURE_URL=http://mercure/.well-known/mercure
 # The public URL of the Mercure hub, used by the browser to connect
 MERCURE_PUBLIC_URL=https://local.mercure.opentalent.fr/.well-known/mercure
-# The secret used to sign the JWTs
-MERCURE_JWT_SECRET=gEwnJpcR8k0xE2sfBpEJzzuP2b2TXhZnzImIqCUk3j4RStBZa2pQjbEMsnGE4iGM
 ###< symfony/mercure-bundle ###
 
 ###> bindfile populate buffer file

+ 36 - 0
env/.env.prod

@@ -0,0 +1,36 @@
+###> doctrine/doctrine-bundle ###
+APP_ENV=prod
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.opentalent.fr/api
+###
+
+###> url v2 ###
+API_BASE_URL=https://ap2i.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.opentalent.fr/api
+###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://ohcluses.opentalent.fr
+###< typo3 client ###
+
+###> dolibarr client ###
+DOLIBARR_API_BASE_URI=https://prod-erp.2iopenservice.com/api/index.php/
+###< dolibarr client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> bindfile populate buffer file
+BIND_FILE_BUFFER_FILE=/env/subdomain.txt
+###< bindfile populate buffer file
+
+###> filename log ###
+LOG_FILE_NAME=prod
+###< filename log ###

+ 35 - 0
env/.env.staging

@@ -0,0 +1,35 @@
+# Fichier d'env utilisé pour les tests fonctionnels et applicatifs
+APP_ENV=staging
+APP_DEBUG=1
+
+###> nelmio/cors-bundle ###
+CORS_ALLOW_ORIGIN=^$
+###< nelmio/cors-bundle ###
+
+####> api v1 ###
+API_LEG_BASE_URL=https://none
+PUBLIC_API_LEG_BASE_URL=https://none
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.ci.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.ci.opentalent.fr
+###< api v2 ###
+
+###> elasticsearch ###
+ELASTICSEARCH_HOST=es
+ELASTICSEARCH_PORT=9200
+###< elasticsearch ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=https://none
+###< typo3 client ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://none
+###
+
+###> filename log ###
+LOG_FILE_NAME=staging
+###< filename log ###
+

+ 34 - 0
env/.env.test

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test1

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test1.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test1.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test1.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test1.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test1.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test1.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test2

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test2.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test2.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test2.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test2.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test2.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test2.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test3

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test3.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test3.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test3.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test3.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test3.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test3.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test4

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test4.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test4.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test4.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test4.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test4.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test4.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test5

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test5.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test5.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test5.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test5.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test5.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test5.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test6

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test6.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test6.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test6.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test6.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test6.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test6.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test7

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test7.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test7.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test7.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test7.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test7.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test7.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test8

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test8.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test8.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test8.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test8.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test8.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test8.opentalent.fr/_internal/secure/files
+###

+ 34 - 0
env/.env.test9

@@ -0,0 +1,34 @@
+###> symfony/framework-bundle ###
+APP_ENV=test
+APP_DEBUG=1
+###< symfony/framework-bundle ###
+
+###> api v1 ###
+API_LEG_BASE_URL=https://api.test9.opentalent.fr/api
+PUBLIC_API_LEG_BASE_URL=https://api.test9.opentalent.fr/api
+###< api v1 ###
+
+###> api v2 ###
+API_BASE_URL=https://ap2i.test9.opentalent.fr/api
+PUBLIC_API_BASE_URL=https://ap2i.test9.opentalent.fr/api
+###< api v2 ###
+
+###> typo3 client ###
+TYPO3_BASE_URI=http://test9.opentalent.fr/ohcluses
+###< typo3 client ###
+
+###> symfony/mercure-bundle ###
+# See https://symfony.com/doc/current/mercure.html#configuration
+# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
+MERCURE_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+# The public URL of the Mercure hub, used by the browser to connect
+MERCURE_PUBLIC_URL=https://mercure.test.opentalent.fr/.well-known/mercure
+###< symfony/mercure-bundle ###
+
+###> filename log ###
+LOG_FILE_NAME=test
+###< filename log ###
+
+### Internal requests (@see doc/internal_requests.md)
+INTERNAL_FILES_DOWNLOAD_URI=https://api.test9.opentalent.fr/_internal/secure/files
+###

+ 3 - 0
env/readme.md

@@ -0,0 +1,3 @@
+# Env files
+
+> @see doc/env.md

File diff suppressed because it is too large
+ 0 - 0
icon.svg


+ 2 - 2
old/Entity/Awin/Product.php

@@ -153,14 +153,14 @@ class Product
      *
      *
      */
-    #[ORM\Column(name: 'price_mini', type: 'float', nullable: true)]
+    #[ORM\Column(name: 'priceMini', type: 'float', nullable: true)]
     protected $priceMini;
     /**
      * @var float
      *
      *
      */
-    #[ORM\Column(name: 'price_maxi', type: 'float', nullable: true)]
+    #[ORM\Column(name: 'priceMaxi', type: 'float', nullable: true)]
     protected $priceMaxi;
     /**
      * @var string

+ 0 - 1
phpstan.json

@@ -1 +0,0 @@
-[]

+ 10 - 9
phpstan.neon.dist

@@ -1,12 +1,13 @@
 # https://phpstan.org/config-reference
 parameters:
-	level: 6
-	treatPhpDocTypesAsCertain: false
-	checkGenericClassInNonGenericObjectType: false
+    level: 6
+    treatPhpDocTypesAsCertain: false
+    checkGenericClassInNonGenericObjectType: false
+    paths:
+        - src
+
+    # on ignore les erreurs qui proviennent d'un importe d'un attribut PhpStorm
+    # 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.#'
 
-# on ignore les erreurs qui proviennent d'un importe d'un attribut PhpStorm
-# 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.#'
-	paths:
-		- src

BIN
public/images/missing-file.png


+ 9 - 0
readme.md

@@ -47,3 +47,12 @@ Pour vider le cache (utiles entre chaque analyse si les modifications ne sont pa
 > Voir : https://phpstan.org/
 
 
+# CS Fixer
+
+## Vérifier le code
+
+    php vendor/bin/php-cs-fixer check --config=.php-cs-fixer.dist.php
+
+## Corriger le formatage du code automatiquement
+
+    php vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php

+ 50 - 48
sql/schema-extensions/001-view_public_events.sql

@@ -1,29 +1,30 @@
 CREATE OR REPLACE VIEW view_public_events
 AS
     SELECT
-        b.uuid, 
-        b.organization_id AS organizationId, 
-        b.name, 
-        b.description, 
-        b.url, 
-        b.datetimeStart, 
-        b.datetimeEnd, 
-        COALESCE(b.priceMini, 0) AS priceMini, 
-        COALESCE(b.priceMaxi, 0) AS priceMaxi, 
+        b.uuid,
+        b.organization_id AS organizationId,
+        b.name,
+        b.description,
+        b.url,
+        b.datetimeStart,
+        b.datetimeEnd,
+        b.gender_id as gender,
+        COALESCE(b.priceMini, 0) AS priceMini,
+        COALESCE(b.priceMaxi, 0) AS priceMaxi,
         null as categoryCode,
-        p.name AS placeName, 
-        p.description AS placeDescription, 
-        p.floorSize AS placeFloorSize, 
+        p.name AS placeName,
+        p.description AS placeDescription,
+        p.floorSize AS placeFloorSize,
         p.capacity AS placeCapacity,
-        ap.addressCity AS city, 
+        ap.addressCity AS city,
         ap.postalCode,
         TRIM(BOTH ' ' FROM CONCAT( IFNULL(ap.streetAddress, ''), ' ', IFNULL(ap.streetAddressSecond, ''), ' ', IFNULL(ap.streetAddressThird, ''))) AS streetAddress,
-        ap.longitude, 
+        ap.longitude,
         ap.latitude,
-        r.name AS roomName, 
-        r.description AS roomDescription, 
-        r.localisation AS roomLocalisation, 
-        r.capacity AS roomCapacity, 
+        r.name AS roomName,
+        r.description AS roomDescription,
+        r.localisation AS roomLocalisation,
+        r.capacity AS roomCapacity,
         r.floorSize AS roomFloorSize,
         IF(b.image_id is not null, CONCAT('https://api.opentalent.fr/app.php/_internal/secure/files/', b.image_id, '/raw'), null) AS imageUrl,
         IF(b.image_id is not null, CONCAT('https://api.opentalent.fr/app.php/_internal/secure/files/', b.image_id, '/0x120'), null) AS thumbnailUrl,
@@ -32,8 +33,8 @@ AS
             LEFT JOIN Categories AS cs ON(cs.id = ec.categories_id)
             LEFT JOIN Familly AS f ON(f.id = cs.familly_id)
          WHERE ec.event_id = b.id
-        ) AS categories, 
-        'opentalent' as origin, 
+        ) AS categories,
+        'opentalent' as origin,
         b.id as entityId
     FROM Booking AS b
         INNER JOIN Organization o ON o.id = b.organization_id
@@ -41,42 +42,43 @@ AS
         LEFT JOIN Place AS p ON (p.id = b.place_id)
         LEFT JOIN AddressPostal AS ap ON (ap.id = p.addressPostal_id)
         LEFT JOIN Room AS r ON (r.id = b.room_id)
-    WHERE b.discr = 'event' 
-        AND b.datetimeEnd >= NOW() 
-        AND b.visibility = 'PUBLIC_VISIBILITY' 
+    WHERE b.discr = 'event'
+        AND b.datetimeEnd >= NOW()
+        AND b.visibility = 'PUBLIC_VISIBILITY'
         AND b.isCanceled = 0
 UNION
     SELECT
-        aw.uuid, 
-        null AS organizationId, 
-        aw.name, 
-        aw.description, 
-        aw.deepLink AS url, 
-        aw.datetimeStart, 
-        aw.datetimeEnd, 
-        aw.priceMini, 
-        aw.priceMaxi, 
+        aw.uuid,
+        null AS organizationId,
+        aw.name,
+        aw.description,
+        aw.deepLink AS url,
+        aw.datetimeStart,
+        aw.datetimeEnd,
+        NULL as gender,
+        aw.priceMini,
+        aw.priceMaxi,
         aw.subCategory AS categoryCode,
-        aw.place AS placeName, 
-        NULL AS placeDescription, 
-        NULL AS placeFloorSize, 
+        aw.place AS placeName,
+        NULL AS placeDescription,
+        NULL AS placeFloorSize,
         NULL AS placeCapacity,
-        aw.city, 
-        aw.postalCode, 
-        aw.streetAddress, 
-        aw.longitude, 
+        aw.city,
+        aw.postalCode,
+        aw.streetAddress,
+        aw.longitude,
         aw.latitude,
-        NULL AS roomName, 
-        NULL AS roomDescription, 
-        NULL AS roomLocalisation, 
-        NULL AS roomCapacity, 
+        NULL AS roomName,
+        NULL AS roomDescription,
+        NULL AS roomLocalisation,
+        NULL AS roomCapacity,
         NULL AS roomFloorSize,
-        aw.largeimage AS imageUrl, 
-        aw.mediumimage as thumbnailUrl, 
-        aw.categoryCode AS categories, 
-        'awin' as origin, 
+        aw.largeimage AS imageUrl,
+        aw.mediumimage as thumbnailUrl,
+        aw.categoryCode AS categories,
+        'awin' as origin,
         aw.id as entityId
     FROM AwinProduct as aw
     WHERE
-        aw.datetimeEnd >= NOW() 
+        aw.datetimeEnd >= NOW()
         AND aw.datetimeStart IS NOT NULL;

+ 0 - 0
config/routes/prod/.gitkeep → src/ApiResource/.gitignore


+ 44 - 17
src/ApiResources/Access/AdminAccess.php

@@ -1,66 +1,93 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Access;
 
-use ApiPlatform\Metadata\Put;
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use ApiPlatform\Metadata\Put;
 use App\ApiResources\ApiResourcesInterface;
 use App\State\Processor\Access\AdminAccessProcessor;
 use App\State\Provider\Access\AdminAccessProvider;
-use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Validator\Constraints as Assert;
+
 /**
- * Classe resource qui contient les champs d'un compte admin
+ * Classe resource qui contient les champs d'un compte admin.
  */
-#[ApiResource(operations: [])]
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/admin-access/{id}',
+            defaults: ['id' => 0]
+        ),
+        new Put(
+            uriTemplate: '/admin-access/{id}',
+            defaults: ['id' => 0],
+            security: '(is_granted("ROLE_ADMIN_CORE") and object.getOrganizationId() == user.getOrganization().getId() )'
+        ),
+    ],
+    provider: AdminAccessProvider::class,
+    processor : AdminAccessProcessor::class
+)]
 class AdminAccess implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     public ?int $id = null;
 
+    private int $organizationId;
+
     private ?string $username = null;
 
     #[Assert\Email(message: 'invalid-email-format', mode: 'strict')]
     private ?string $email = null;
 
-    #[Pure]
-    public function __construct()
+    public function getId(): ?int
     {
+        return $this->id;
     }
 
-    public function getId() : ?int
+    public function setId(?int $id): self
     {
-        return $this->id;
+        $this->id = $id;
+
+        return $this;
     }
 
-    public function setId(?int $id) : self
+    public function getOrganizationId(): ?int
     {
-        $this->id = $id;
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(?int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+
         return $this;
     }
 
-    public function getUsername() : ?string
+    public function getUsername(): ?string
     {
         return $this->username;
     }
 
-    public function setUsername(?string $username) : self
+    public function setUsername(?string $username): self
     {
         $this->username = $username;
+
         return $this;
     }
 
-    public function getEmail() : ?string
+    public function getEmail(): ?string
     {
         return $this->email;
     }
 
-    public function setEmail(?string $email) : self
+    public function setEmail(?string $email): self
     {
         $this->email = $email;
+
         return $this;
     }
 }

+ 4 - 2
src/ApiResources/ApiResourcesInterface.php

@@ -1,7 +1,9 @@
 <?php
+
 declare(strict_types=1);
 
 namespace App\ApiResources;
 
-interface ApiResourcesInterface{
-}
+interface ApiResourcesInterface
+{
+}

+ 36 - 0
src/ApiResources/Core/File/Download.php

@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Core\File;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\State\Provider\Core\DownloadProvider;
+
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: 'file/download/{fileId}',
+            requirements: ['fileId' => '\\d+'],
+            security: 'is_granted("ROLE_FILE")',
+            provider: DownloadProvider::class
+        ),
+    ]
+)]
+class Download
+{
+    #[ApiProperty(identifier: true)]
+    private int $fileId;
+
+    public function getFileId(): int
+    {
+        return $this->fileId;
+    }
+
+    public function setFileId(int $fileId): void
+    {
+        $this->fileId = $fileId;
+    }
+}

+ 0 - 48
src/ApiResources/Core/File/DownloadRequest.php

@@ -1,48 +0,0 @@
-<?php
-declare (strict_types=1);
-
-namespace App\ApiResources\Core\File;
-
-use ApiPlatform\Metadata\ApiProperty;
-use ApiPlatform\Metadata\ApiResource;
-use ApiPlatform\Metadata\Get;
-use App\State\Provider\Core\DownloadRequestProvider;
-
-/**
- * A request for a file from the LocalStorage
- */
-#[ApiResource(
-    operations: [
-        new Get(
-            uriTemplate: '/download/{fileId}',
-            requirements: ['fileId' => '\\d+'],
-            security: 'is_granted("ROLE_FILE")',
-            provider: DownloadRequestProvider::class
-        ),
-        new Get(
-            uriTemplate: '/internal/download/{fileId}',
-            requirements: ['fileId' => '\\d+'],
-            provider: DownloadRequestProvider::class
-        )
-    ]
-)]
-class DownloadRequest
-{
-    #[ApiProperty(identifier: true)]
-    private int $fileId;
-
-    /**
-     * @return int
-     */
-    public function getFileId() : int
-    {
-        return $this->fileId;
-    }
-    /**
-     * @param int $fileId
-     */
-    public function setFileId(int $fileId) : void
-    {
-        $this->fileId = $fileId;
-    }
-}

+ 59 - 0
src/ApiResources/Core/File/Image.php

@@ -0,0 +1,59 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Core\File;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\Enum\Core\FileSizeEnum;
+use App\State\Provider\Core\ImageProvider;
+use Symfony\Component\Routing\Requirement\EnumRequirement;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * A request for a file from the LocalStorage.
+ */
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/image/download/{fileId}/{size}',
+            requirements: ['fileId' => '\\d+', 'size' => new EnumRequirement(FileSizeEnum::class)],
+            security: 'is_granted("ROLE_FILE")',
+            provider: ImageProvider::class
+        ),
+    ]
+)]
+class Image
+{
+    #[ApiProperty(identifier: true)]
+    private int $fileId;
+
+    #[Assert\Type(type: FileSizeEnum::class)]
+    private string $size;
+
+    public function getFileId(): int
+    {
+        return $this->fileId;
+    }
+
+    public function setFileId(int $fileId): self
+    {
+        $this->fileId = $fileId;
+
+        return $this;
+    }
+
+    public function getSize(): string
+    {
+        return $this->size;
+    }
+
+    public function setSize(string $size): self
+    {
+        $this->size = $size;
+
+        return $this;
+    }
+}

+ 164 - 0
src/ApiResources/Core/File/Upload.php

@@ -0,0 +1,164 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Core\File;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Post;
+use App\Enum\Core\FileTypeEnum;
+use App\Enum\Core\FileVisibilityEnum;
+use App\State\Processor\Core\UploadRequestProcessor;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * A request to upload the given content to a File.
+ */
+#[ApiResource(
+    operations: [
+        new Post(
+            uriTemplate: '/upload',
+            requirements: ['id' => '\\d+'],
+            security: 'is_granted("ROLE_FILE")',
+            processor: UploadRequestProcessor::class
+        ),
+    ]
+)]
+class Upload
+{
+    #[ApiProperty(identifier: true)]
+    private ?int $fileId = null;
+
+    /**
+     * Le nom du fichier.
+     */
+    private string $filename;
+
+    /**
+     * Le contenu du fichier uploadé encodé au format Base64.
+     */
+    private string $content;
+
+    /**
+     * Si vrai, le propriétaire du fichier ne sera pas l'utilisateur en cours, mais l'organisation à laquelle il
+     * appartient.
+     */
+    private bool $organizationOwned = false;
+
+    /**
+     * Le type de fichier uploadé, si connu.
+     */
+    #[Assert\Type(type: FileTypeEnum::class)]
+    private FileTypeEnum $type = FileTypeEnum::NONE;
+
+    /**
+     * Visibilité du fichier.
+     */
+    #[Assert\Type(type: FileVisibilityEnum::class)]
+    private FileVisibilityEnum $visibility = FileVisibilityEnum::NOBODY;
+
+    /**
+     * Type mime (il sera déduit automatiquement du nom du fichier s'il n'est pas fourni ici).
+     */
+    private ?string $mimeType = null;
+
+    /**
+     * Configuration du fichier (par exemple le cropping d'une image).
+     */
+    private ?string $config = null;
+
+    public function getFileId(): int
+    {
+        return $this->fileId;
+    }
+
+    public function setFileId(int $id): self
+    {
+        $this->fileId = $id;
+
+        return $this;
+    }
+
+    public function getContent(): string
+    {
+        return $this->content;
+    }
+
+    public function setContent(string $content): void
+    {
+        $this->content = $content;
+    }
+
+    public function isOrganizationOwned(): bool
+    {
+        return $this->organizationOwned;
+    }
+
+    public function setOrganizationOwned(bool $organizationOwned): self
+    {
+        $this->organizationOwned = $organizationOwned;
+
+        return $this;
+    }
+
+    public function getFilename(): string
+    {
+        return $this->filename;
+    }
+
+    public function setFilename(string $filename): self
+    {
+        $this->filename = $filename;
+
+        return $this;
+    }
+
+    public function getType(): FileTypeEnum
+    {
+        return $this->type;
+    }
+
+    public function setType(FileTypeEnum $type): self
+    {
+        $this->type = $type;
+
+        return $this;
+    }
+
+    public function getVisibility(): FileVisibilityEnum
+    {
+        return $this->visibility;
+    }
+
+    public function setVisibility(FileVisibilityEnum $visibility): self
+    {
+        $this->visibility = $visibility;
+
+        return $this;
+    }
+
+    public function getMimeType(): ?string
+    {
+        return $this->mimeType;
+    }
+
+    public function setMimeType(?string $mimeType): self
+    {
+        $this->mimeType = $mimeType;
+
+        return $this;
+    }
+
+    public function getConfig(): ?string
+    {
+        return $this->config;
+    }
+
+    public function setConfig(?string $config): self
+    {
+        $this->config = $config;
+
+        return $this;
+    }
+}

+ 15 - 9
src/ApiResources/Cotisation/Cotisation.php

@@ -1,19 +1,22 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Cotisation;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
+use App\Enum\Cotisation\AlertStateEnum;
 use App\State\Provider\Cotisation\CotisationProvider;
 use Symfony\Component\Validator\Constraints as Assert;
 
 /**
- * Classe resource qui contient les informations des cotisations de la 5.9
+ * Classe resource qui contient les informations des cotisations de la 5.9.
  *
  * Security :
+ *
  *   * @see App\Security\Voter\CotisationVoter
  */
 #[ApiResource(operations: [
@@ -21,15 +24,15 @@ use Symfony\Component\Validator\Constraints as Assert;
         uriTemplate: '/cotisations/{organizationId}',
         security: 'is_granted("ROLE_COTISATION", object) and object.getOrganizationId() == user.getOrganization().getId()',
         provider: CotisationProvider::class
-    )
+    ),
 ])]
 class Cotisation implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     private int $organizationId;
 
-    #[Assert\Choice(callback: ['\\App\\Enum\\Cotisation\\AlertStateEnum', 'toArray'], message: 'invalid-alert-state-enum')]
-    private ?string $alertState = null;
+    #[Assert\Type(type: AlertStateEnum::class)]
+    private ?AlertStateEnum $alertState = null;
 
     private ?int $cotisationYear = null;
 
@@ -41,17 +44,19 @@ class Cotisation implements ApiResourcesInterface
     public function setOrganizationId(?int $organizationId): self
     {
         $this->organizationId = $organizationId;
+
         return $this;
     }
 
-    public function getAlertState(): ?string
+    public function getAlertState(): ?AlertStateEnum
     {
         return $this->alertState;
     }
 
-    public function setAlertState(?string $alertState): self
+    public function setAlertState(?AlertStateEnum $alertState): self
     {
         $this->alertState = $alertState;
+
         return $this;
     }
 
@@ -63,6 +68,7 @@ class Cotisation implements ApiResourcesInterface
     public function setCotisationYear(?int $cotisationYear): self
     {
         $this->cotisationYear = $cotisationYear;
+
         return $this;
     }
 }

+ 20 - 13
src/ApiResources/Dolibarr/DolibarrAccount.php

@@ -1,12 +1,12 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Dolibarr;
 
-use ApiPlatform\Metadata\Link;
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use App\State\Provider\Dolibarr\DolibarrAccountProvider;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -16,7 +16,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
  * Données de l'organization retournées par l'API Dolibarr
- * (aussi nommé 'ThirdParty' ou 'Society' dans dolibarr)
+ * (aussi nommé 'ThirdParty' ou 'Society' dans dolibarr).
  */
 #[ApiResource(
     operations: [
@@ -30,7 +30,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
                             is_granted("ROLE_FINANCIAL_MANAGER_CORE")
                            ) and object.getOrganizationId() == user.getOrganization().getId()',
             provider: DolibarrAccountProvider::class
-        )
+        ),
     ]
 )]
 class DolibarrAccount implements ApiResourcesInterface
@@ -40,31 +40,31 @@ class DolibarrAccount implements ApiResourcesInterface
     private int $organizationId;
 
     /**
-     * Dolibarr societies pk
+     * Dolibarr societies pk.
      */
     #[Groups('dolibarr_get')]
     private ?int $socId = null;
 
     /**
-     * Opentalent client ref
+     * Opentalent client ref.
      */
     #[Groups('dolibarr_get')]
-    private string $clientNumber = "";
+    private string $clientNumber = '';
 
     /**
-     * Opentalent product owned
+     * Opentalent product owned.
      */
     #[Groups('dolibarr_get')]
-    private string $product = "";
+    private string $product = '';
 
     /**
-     * Contract and services currently active
+     * Contract and services currently active.
      */
     #[Groups('dolibarr_get')]
     private ?DolibarrContract $contract = null;
 
     /**
-     * Last bills
+     * Last bills.
      */
     #[Groups('dolibarr_get')]
     private Collection $bills;
@@ -83,6 +83,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setOrganizationId(int $organizationId): self
     {
         $this->organizationId = $organizationId;
+
         return $this;
     }
 
@@ -94,6 +95,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setSocId(?int $socId): self
     {
         $this->socId = $socId;
+
         return $this;
     }
 
@@ -105,6 +107,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setClientNumber(string $clientNumber): self
     {
         $this->clientNumber = $clientNumber;
+
         return $this;
     }
 
@@ -116,6 +119,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setProduct(string $product): self
     {
         $this->product = $product;
+
         return $this;
     }
 
@@ -127,6 +131,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setContract(?object $contract): self
     {
         $this->contract = $contract;
+
         return $this;
     }
 
@@ -138,12 +143,14 @@ class DolibarrAccount implements ApiResourcesInterface
     public function addBill(DolibarrBill $bill): self
     {
         $this->bills[] = $bill;
+
         return $this;
     }
 
     public function removeBill(DolibarrBill $bill): self
     {
         $this->bills->removeElement($bill);
+
         return $this;
     }
 }

+ 18 - 23
src/ApiResources/Dolibarr/DolibarrBill.php

@@ -1,57 +1,58 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Dolibarr;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
- * Bill of a society, retrieved from dolibarr
+ * Bill of a society, retrieved from dolibarr.
  */
 #[ApiResource(
     operations: [
-        new Get()
+        new Get(),
     ]
 )]
 class DolibarrBill implements ApiResourcesInterface
 {
     /**
-     * Id of the dolibarr bill ( = invoice)
+     * Id of the dolibarr bill ( = invoice).
      */
     #[ApiProperty(identifier: true)]
     #[Groups('dolibarr_get')]
     private int $id;
 
     /**
-     * Bill reference
+     * Bill reference.
      */
     #[Groups('dolibarr_get')]
     private string $ref;
 
     /**
-     * Date of the bill
+     * Date of the bill.
      */
     #[Groups('dolibarr_get')]
     private \DateTime $date;
 
     /**
-     * Amount (tax excluded)
+     * Amount (tax excluded).
      */
     #[Groups('dolibarr_get')]
     private float $taxExcludedAmount;
 
     /**
-     * Amount (tax included)
+     * Amount (tax included).
      */
     #[Groups('dolibarr_get')]
     private float $taxIncludedAmount;
 
     /**
-     * Is the bill paid or not
+     * Is the bill paid or not.
      */
     #[Groups('dolibarr_get')]
     private bool $paid;
@@ -64,6 +65,7 @@ class DolibarrBill implements ApiResourcesInterface
     public function setId(int $id): self
     {
         $this->id = $id;
+
         return $this;
     }
 
@@ -75,6 +77,7 @@ class DolibarrBill implements ApiResourcesInterface
     public function setRef(string $ref): self
     {
         $this->ref = $ref;
+
         return $this;
     }
 
@@ -86,40 +89,31 @@ class DolibarrBill implements ApiResourcesInterface
     public function setDate(\DateTime $date): self
     {
         $this->date = $date;
+
         return $this;
     }
 
-    /**
-     * @return float
-     */
     public function getTaxExcludedAmount(): float
     {
         return $this->taxExcludedAmount;
     }
 
-    /**
-     * @param float $taxExcludedAmount
-     */
     public function setTaxExcludedAmount(float $taxExcludedAmount): self
     {
         $this->taxExcludedAmount = $taxExcludedAmount;
+
         return $this;
     }
 
-    /**
-     * @return float
-     */
     public function getTaxIncludedAmount(): float
     {
         return $this->taxIncludedAmount;
     }
 
-    /**
-     * @param float $taxIncludedAmount
-     */
     public function setTaxIncludedAmount(float $taxIncludedAmount): self
     {
         $this->taxIncludedAmount = $taxIncludedAmount;
+
         return $this;
     }
 
@@ -131,6 +125,7 @@ class DolibarrBill implements ApiResourcesInterface
     public function setPaid(bool $paid): self
     {
         $this->paid = $paid;
+
         return $this;
     }
 }

+ 13 - 8
src/ApiResources/Dolibarr/DolibarrContract.php

@@ -1,11 +1,12 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Dolibarr;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
@@ -13,30 +14,30 @@ use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
- * Contract of a society, retrieved from dolibarr
+ * Contract of a society, retrieved from dolibarr.
  */
 #[ApiResource(
     operations: [
-        new Get()
+        new Get(),
     ]
 )]
 class DolibarrContract implements ApiResourcesInterface
 {
     /**
-     * Reference of the dolibarr contract
+     * Reference of the dolibarr contract.
      */
     #[ApiProperty(identifier: true)]
     #[Groups('dolibarr_get')]
     private string $ref;
 
     /**
-     * Id of the society
+     * Id of the society.
      */
     #[Groups('dolibarr_get')]
     private int $socId;
 
     /**
-     * Lines (services) included in the current contract
+     * Lines (services) included in the current contract.
      */
     #[Groups('dolibarr_get')]
     private Collection $lines;
@@ -55,6 +56,7 @@ class DolibarrContract implements ApiResourcesInterface
     public function setRef(string $ref): self
     {
         $this->ref = $ref;
+
         return $this;
     }
 
@@ -66,6 +68,7 @@ class DolibarrContract implements ApiResourcesInterface
     public function setSocId(int $socId): self
     {
         $this->socId = $socId;
+
         return $this;
     }
 
@@ -77,12 +80,14 @@ class DolibarrContract implements ApiResourcesInterface
     public function addLine(DolibarrContractLine $line): self
     {
         $this->lines[] = $line;
+
         return $this;
     }
 
     public function removeBill(DolibarrContractLine $line): self
     {
         $this->lines->removeElement($line);
+
         return $this;
     }
 }

+ 15 - 8
src/ApiResources/Dolibarr/DolibarrContractLine.php

@@ -1,20 +1,21 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Dolibarr;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
- *  Lines (services) included in a society contract, as retrieved from dolibarr
+ *  Lines (services) included in a society contract, as retrieved from dolibarr.
  */
 #[ApiResource(
     operations: [
-        new Get()
+        new Get(),
     ]
 )]
 class DolibarrContractLine implements ApiResourcesInterface
@@ -24,19 +25,19 @@ class DolibarrContractLine implements ApiResourcesInterface
     private int $id;
 
     /**
-     * Id of the contract's line
+     * Id of the contract's line.
      */
     #[Groups('dolibarr_get')]
     private int $contractId;
 
     /**
-     * Reference of the contracted service ( = product's reference)
+     * Reference of the contracted service ( = product's reference).
      */
     #[Groups('dolibarr_get')]
     private string $serviceRef;
 
     /**
-     * Label of the contracted service
+     * Label of the contracted service.
      */
     #[Groups('dolibarr_get')]
     private string $serviceLabel;
@@ -61,6 +62,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setId(int $id): self
     {
         $this->id = $id;
+
         return $this;
     }
 
@@ -72,6 +74,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setContractId(int $contractId): self
     {
         $this->contractId = $contractId;
+
         return $this;
     }
 
@@ -83,6 +86,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setServiceRef(string $serviceRef): self
     {
         $this->serviceRef = $serviceRef;
+
         return $this;
     }
 
@@ -94,6 +98,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setServiceLabel(string $serviceLabel): self
     {
         $this->serviceLabel = $serviceLabel;
+
         return $this;
     }
 
@@ -105,6 +110,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setDateStart(?\DateTime $dateStart): self
     {
         $this->dateStart = $dateStart;
+
         return $this;
     }
 
@@ -116,6 +122,7 @@ class DolibarrContractLine implements ApiResourcesInterface
     public function setDateEnd(?\DateTime $dateEnd): self
     {
         $this->dateEnd = $dateEnd;
+
         return $this;
     }
 }

+ 10 - 6
src/ApiResources/Enum/Enum.php

@@ -1,11 +1,12 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Enum;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use App\State\Provider\Enum\EnumProvider;
 
@@ -17,7 +18,7 @@ use App\State\Provider\Enum\EnumProvider;
         new Get(
             uriTemplate: '/enum/{name}',
             provider: EnumProvider::class
-        )
+        ),
     ]
 )]
 class Enum implements ApiResourcesInterface
@@ -25,7 +26,7 @@ class Enum implements ApiResourcesInterface
     #[ApiProperty(identifier: true)]
     private string $name;
 
-    /** @var list<string> $items */
+    /** @var list<string> */
     private array $items = [];
 
     public function __construct()
@@ -40,16 +41,19 @@ class Enum implements ApiResourcesInterface
     public function setName(string $name): self
     {
         $this->name = $name;
+
         return $this;
     }
 
     /**
      * @param list<string> $items
+     *
      * @return $this
      */
     public function setItems(array $items): self
     {
         $this->items = $items;
+
         return $this;
     }
 
@@ -60,4 +64,4 @@ class Enum implements ApiResourcesInterface
     {
         return $this->items;
     }
-}
+}

+ 12 - 44
src/ApiResources/Export/ExportRequest.php

@@ -1,119 +1,87 @@
 <?php
+
 declare(strict_types=1);
 
 namespace App\ApiResources\Export;
 
 use ApiPlatform\Metadata\ApiProperty;
-use Symfony\Component\Validator\Constraints as Assert;
 use App\Enum\Export\ExportFormatEnum;
+use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Demande d'export d'un fichier
- * -- C'est la classe de base des ressources de type ExportRequest --
+ * -- C'est la classe de base des ressources de type ExportRequest --.
  */
 abstract class ExportRequest
 {
     /**
      * Id 'bidon' ajouté par défaut pour permettre la construction
-     * de l'IRI par api platform
-     *
-     * @var int
+     * de l'IRI par api platform.
      */
     #[ApiProperty(identifier: true)]
     protected int $id = 0;
 
     /**
-     * Format de sortie attendu (pdf, txt...)
-     * @var string
+     * Format de sortie attendu (pdf, txt...).
      */
-    #[Assert\Choice(callback: [ExportFormatEnum::class, 'toArray'], message: 'invalid-output-format')]
-    protected string $format;
+    #[Assert\Type(type: ExportFormatEnum::class)]
+    protected ExportFormatEnum $format;
 
     /**
-     * The id of the access requesting this export
-     * @var int|null
+     * The id of the access requesting this export.
      */
     protected ?int $requesterId = null;
 
     /**
-     * Should the export be asynchrone
-     * @var bool
+     * Should the export be asynchrone.
      */
     protected bool $async = true;
 
     /**
-     * The id of the db record of the file
-     * @var int|null
+     * The id of the db record of the file.
      */
     protected ?int $fileId = null;
 
-    /**
-     * @return int
-     */
     public function getId(): int
     {
         return $this->id;
     }
 
-    /**
-     * @return string
-     */
-    public function getFormat(): string
+    public function getFormat(): ExportFormatEnum
     {
         return $this->format;
     }
 
-    /**
-     * @param string $format
-     */
-    public function setFormat(string $format): void
+    public function setFormat(ExportFormatEnum $format): void
     {
         $this->format = $format;
     }
 
-    /**
-     * @return int|null
-     */
     public function getRequesterId(): ?int
     {
         return $this->requesterId;
     }
 
-    /**
-     * @param int|null $requesterId
-     */
     public function setRequesterId(?int $requesterId): void
     {
         $this->requesterId = $requesterId;
     }
 
-    /**
-     * @return bool
-     */
     public function isAsync(): bool
     {
         return $this->async;
     }
 
-    /**
-     * @param bool $async
-     */
     public function setAsync(bool $async): void
     {
         $this->async = $async;
     }
 
-    /**
-     * @return int|null
-     */
     public function getFileId(): ?int
     {
         return $this->fileId;
     }
 
-    /**
-     * @param int|null $fileId
-     */
     public function setFileId(?int $fileId): void
     {
         $this->fileId = $fileId;

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

@@ -4,5 +4,4 @@ namespace App\ApiResources\Export;
 
 interface ExportRequestInterface
 {
-
 }

+ 22 - 31
src/ApiResources/Export/LicenceCmf/LicenceCmfOrganizationER.php

@@ -1,55 +1,46 @@
 <?php
 
-declare (strict_types=1);
+declare(strict_types=1);
 
 namespace App\ApiResources\Export\LicenceCmf;
 
-use ApiPlatform\Metadata\Post;
-use ApiPlatform\Metadata\Delete;
-use ApiPlatform\Metadata\Patch;
-use ApiPlatform\Metadata\Put;
-use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Post;
 use App\ApiResources\Export\ExportRequest;
-use App\ApiResources\Export\ExportRequestInterface;
+use App\Enum\Export\ExportFormatEnum;
 use App\State\Processor\Export\LicenceCmf\ExportRequestProcessor;
-use Symfony\Component\Validator\Constraints as Assert;
 
 /**
-* Requête d'export d'une licence CMF pour l'organization ciblée
-*
-* Appeler avec une requête POST à /export/licence-cmf/organization,
-* avec un body comme :
-*
-* {"organizationId" : 1}
-*/
+ * Requête d'export d'une licence CMF pour l'organization ciblée.
+ *
+ * Appeler avec une requête POST à /export/licence-cmf/organization,
+ * avec un body comme :
+ *
+ * {"organizationId" : 1}
+ */
 #[ApiResource(
     operations: [
-new Post(
-    uriTemplate: '/cmf-licence/organization',
-    security: '(is_granted("ROLE_ADMIN_CORE") or is_granted("ROLE_ADMINISTRATIF_MANAGER_CORE"))'
-),
-],
+        new Post(
+            uriTemplate: '/cmf-licence/organization',
+            security: '(is_granted("ROLE_ADMIN_CORE") or is_granted("ROLE_ADMINISTRATIF_MANAGER_CORE"))'
+        ),
+    ],
     routePrefix: '/export',
     processor: ExportRequestProcessor::class
 )]
 class LicenceCmfOrganizationER extends ExportRequest
 {
     /**
-    * Format de sortie attendu (pdf seulement ici)
-    * @var string
-    */
-    #[Assert\EqualTo('pdf')]
-    protected string $format = 'pdf';
+     * Format de sortie attendu (pdf seulement ici).
+     */
+    protected ExportFormatEnum $format = ExportFormatEnum::PDF;
 
     /**
-    * Retourne l'année de la licence
-    * (toujours l'année courante, sauf dans le cas des tests où on pourra mocker cette méthode)
-    *
-    * @return int
-    */
+     * Retourne l'année de la licence
+     * (toujours l'année courante, sauf dans le cas des tests où on pourra mocker cette méthode).
+     */
     public function getYear(): int
     {
-        return (int)date('Y');
+        return (int) date('Y');
     }
 }

+ 9 - 8
src/ApiResources/Mobyt/MobytUserStatus.php

@@ -1,16 +1,17 @@
 <?php
-declare (strict_types=1);
+
+declare(strict_types=1);
 
 namespace App\ApiResources\Mobyt;
 
-use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use App\State\Provider\Mobyt\MobytUserStatusProvider;
 
 /**
- * Statut de l'utilisateur Mobyt correspondant à l'organization donnée en paramètre
+ * Statut de l'utilisateur Mobyt correspondant à l'organization donnée en paramètre.
  */
 #[ApiResource(
     operations: [
@@ -24,7 +25,7 @@ use App\State\Provider\Mobyt\MobytUserStatusProvider;
                             is_granted("ROLE_TEXTO")
                            ) and object.getOrganizationId() == user.getOrganization().getId()',
             provider: MobytUserStatusProvider::class
-        )
+        ),
     ]
 )]
 class MobytUserStatus implements ApiResourcesInterface
@@ -33,17 +34,17 @@ class MobytUserStatus implements ApiResourcesInterface
     private int $organizationId;
 
     /**
-     * Is there a Mobyt account active for this user
+     * Is there a Mobyt account active for this user.
      */
     private bool $active = false;
 
     /**
-     * Amount of sms remaining
+     * Amount of sms remaining.
      */
     private int $amount = 0;
 
     /**
-     * Money remaining
+     * Money remaining.
      */
     private float $money = 0;
 

+ 1 - 1
src/ApiResources/OnlineRegistration/RegistrationAvailability.php

@@ -15,7 +15,7 @@ use App\State\Provider\OnlineRegistration\RegistrationAvailabilityProvider;
             requirements: ['accessId' => '\\d+'],
             defaults: ['accessId' => 0],
             provider: RegistrationAvailabilityProvider::class
-        )
+        ),
     ]
 )]
 class RegistrationAvailability implements ApiResourcesInterface

+ 7 - 5
src/ApiResources/OnlineRegistration/RegistrationStatus.php

@@ -6,8 +6,9 @@ use ApiPlatform\Metadata\ApiProperty;
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
+use App\Enum\OnlineRegistration\RegistrationStatusEnum;
 use App\State\Provider\OnlineRegistration\RegistrationStatusProvider;
-use Symfony\Component\Serializer\Annotation\Groups;
+use Symfony\Component\Validator\Constraints as Assert;
 
 #[ApiResource(
     operations: [
@@ -16,7 +17,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
             requirements: ['accessId' => '\\d+'],
             defaults: ['accessId' => 0],
             provider: RegistrationStatusProvider::class
-        )
+        ),
     ]
 )]
 class RegistrationStatus implements ApiResourcesInterface
@@ -24,7 +25,8 @@ class RegistrationStatus implements ApiResourcesInterface
     #[ApiProperty(identifier: true)]
     private int $accessId;
 
-    private ?string $status = null;
+    #[Assert\Type(type: RegistrationStatusEnum::class)]
+    private ?RegistrationStatusEnum $status = null;
 
     public function getAccessId(): int
     {
@@ -36,12 +38,12 @@ class RegistrationStatus implements ApiResourcesInterface
         $this->accessId = $accessId;
     }
 
-    public function getStatus(): ?string
+    public function getStatus(): ?RegistrationStatusEnum
     {
         return $this->status;
     }
 
-    public function setStatus(?string $status): void
+    public function setStatus(?RegistrationStatusEnum $status): void
     {
         $this->status = $status;
     }

+ 69 - 0
src/ApiResources/Organization/Subdomain/SubdomainAvailability.php

@@ -0,0 +1,69 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Organization\Subdomain;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\State\Provider\Organization\Subdomain\SubdomainAvailabilityProvider;
+
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/subdomains/is_available',
+            security: 'is_granted("ROLE_ORGANIZATION_VIEW") or is_granted("ROLE_ORGANIZATION")',
+            provider: SubdomainAvailabilityProvider::class
+        ),
+    ]
+)]
+class SubdomainAvailability
+{
+    /**
+     * Id 'bidon' ajouté par défaut pour permettre la construction
+     * de l'IRI par api platform.
+     */
+    #[ApiProperty(identifier: true)]
+    protected int $id = 0;
+
+    /**
+     * The subdomain.
+     */
+    private string $subdomain;
+
+    /**
+     * Is the subdomain available (not registered nor reserved).
+     */
+    private bool $available;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): void
+    {
+        $this->id = $id;
+    }
+
+    public function getSubdomain(): string
+    {
+        return $this->subdomain;
+    }
+
+    public function setSubdomain(string $subdomain): void
+    {
+        $this->subdomain = $subdomain;
+    }
+
+    public function isAvailable(): bool
+    {
+        return $this->available;
+    }
+
+    public function setAvailable(bool $available): void
+    {
+        $this->available = $available;
+    }
+}

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