From d9a47fdee949a4bfb4540284e7128f4d51ba41a9 Mon Sep 17 00:00:00 2001 From: Julie Lenaerts Date: Thu, 22 May 2025 17:45:52 +0200 Subject: [PATCH] Update configuration to comply with symfony 7.2 --- composer.json | 104 +++++++-------- config/bundles.php | 1 - config/packages/framework.yaml | 10 ++ config/packages/messenger.yaml | 2 - config/packages/security.yaml | 10 +- config/packages/sensio_framework_extra.yaml | 3 - config/routes/annotations.yaml | 2 +- config/services.yaml | 4 + .../DependencyInjection/Configuration.php | 2 +- .../src/DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- ...ConfigureOpenstackObjectStorageCommand.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../Authenticator/DavOnUrlTokenExtractor.php | 57 ++++++++ .../JWTOnDavUrlAuthenticator.php | 77 +++++++++++ .../DependencyInjection/Configuration.php | 2 +- .../src/DependencyInjection/Configuration.php | 2 +- .../src/DependencyInjection/Configuration.php | 2 +- .../ArgumentResolver/EntityValueResolver.php | 125 ++++++++++++++++++ .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 2 +- .../src/DependencyInjection/Configuration.php | 2 +- .../DependencyInjection/Configuration.php | 37 ++++++ .../ContainerAwareTrait.php | 25 ++++ 30 files changed, 408 insertions(+), 83 deletions(-) delete mode 100644 config/packages/sensio_framework_extra.yaml create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authenticator/DavOnUrlTokenExtractor.php create mode 100644 src/Bundle/ChillDocStoreBundle/Security/Authenticator/JWTOnDavUrlAuthenticator.php create mode 100644 src/Bundle/ChillMainBundle/ArgumentResolver/EntityValueResolver.php create mode 100644 src/ChampsLibres/WopiBundle/DependencyInjection/Configuration.php create mode 100644 src/Symfony/Component/DependencyInjection/ContainerAwareTrait.php diff --git a/composer.json b/composer.json index 8d36d4d07..024819124 100644 --- a/composer.json +++ b/composer.json @@ -16,13 +16,14 @@ "ext-zlib": "*", "champs-libres/wopi-bundle": "dev-master@dev", "champs-libres/wopi-lib": "dev-master@dev", + "doctrine/annotations": "^2.0", "doctrine/data-fixtures": "^1.8", "doctrine/doctrine-bundle": "^2.1", "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.13.0", "erusev/parsedown": "^1.7", "knplabs/knp-menu-bundle": "^3.0", - "knplabs/knp-time-bundle": "^1.12", + "knplabs/knp-time-bundle": "^2.0", "knpuniversity/oauth2-client-bundle": "^2.10", "league/csv": "^9.7.1", "lexik/jwt-authentication-bundle": "^2.16", @@ -32,54 +33,51 @@ "ovh/ovh": "^3.0", "phpoffice/phpspreadsheet": "^1.16", "ramsey/uuid-doctrine": "^1.7", - "sensio/framework-extra-bundle": "^5.5", "smalot/pdfparser": "^2.10", "spomky-labs/base64url": "^2.0", - "symfony/asset": "^5.4", - "symfony/browser-kit": "^5.4", - "symfony/cache": "^5.4", - "symfony/clock": "^6.2", - "symfony/config": "^5.4", - "symfony/console": "^5.4", - "symfony/css-selector": "^5.4", - "symfony/dom-crawler": "^5.4", - "symfony/error-handler": "^5.4", - "symfony/event-dispatcher": "^5.4", - "symfony/event-dispatcher-contracts": "^2.4", - "symfony/expression-language": "^5.4", - "symfony/filesystem": "^5.4", - "symfony/finder": "^5.4", - "symfony/form": "^5.4", - "symfony/framework-bundle": "^5.4", - "symfony/http-client": "^5.4", - "symfony/http-foundation": "^5.4", - "symfony/intl": "^5.4", - "symfony/mailer": "^5.4", - "symfony/messenger": "^5.4", - "symfony/mime": "^5.4", + "symfony/asset": "^7.2", + "symfony/browser-kit": "^7.2", + "symfony/cache": "^7.2", + "symfony/clock": "^7.2", + "symfony/config": "^7.2", + "symfony/console": "^7.2", + "symfony/css-selector": "^7.2", + "symfony/dom-crawler": "^7.2", + "symfony/error-handler": "^7.2", + "symfony/event-dispatcher": "^7.2", + "symfony/event-dispatcher-contracts": "^3.0", + "symfony/expression-language": "^7.2", + "symfony/filesystem": "^7.2", + "symfony/finder": "^7.2", + "symfony/form": "^7.2", + "symfony/framework-bundle": "^7.2", + "symfony/http-client": "^7.2", + "symfony/http-foundation": "^7.2", + "symfony/intl": "^7.2", + "symfony/mailer": "^7.2", + "symfony/messenger": "^7.2", + "symfony/mime": "^7.2", "symfony/monolog-bundle": "^3.5", - "symfony/notifier": "^5.4", - "symfony/options-resolver": "^5.4", - "symfony/ovh-cloud-notifier": "^5.4", - "symfony/process": "^5.4", - "symfony/property-access": "^5.4", - "symfony/property-info": "^5.4", - "symfony/routing": "^5.4", - "symfony/security-bundle": "^5.4", - "symfony/security-core": "^5.4", - "symfony/security-csrf": "^5.4", - "symfony/security-guard": "^5.4", - "symfony/security-http": "^5.4", - "symfony/serializer": "^5.4", - "symfony/string": "^5.4", - "symfony/templating": "^5.4", - "symfony/translation": "^5.4", - "symfony/twig-bundle": "^5.4", + "symfony/notifier": "^7.2", + "symfony/options-resolver": "^7.2", + "symfony/ovh-cloud-notifier": "^7.2", + "symfony/process": "^7.2", + "symfony/property-access": "^7.2", + "symfony/property-info": "^7.2", + "symfony/routing": "^7.2", + "symfony/security-bundle": "^7.2", + "symfony/security-core": "^7.2", + "symfony/security-csrf": "^7.2", + "symfony/security-http": "^7.2", + "symfony/serializer": "^7.2", + "symfony/string": "^7.2", + "symfony/translation": "^7.2", + "symfony/twig-bundle": "^7.2", "symfony/ux-translator": "^2.22", - "symfony/validator": "^5.4", - "symfony/webpack-encore-bundle": "^1.11", - "symfony/workflow": "^5.4", - "symfony/yaml": "^5.4", + "symfony/validator": "^7.2", + "symfony/webpack-encore-bundle": "^2.0", + "symfony/workflow": "^7.2", + "symfony/yaml": "^7.2", "thenetworg/oauth2-azure": "^2.0", "twig/extra-bundle": "^3.0", "twig/intl-extra": "^3.0", @@ -101,22 +99,24 @@ "phpstan/phpstan-strict-rules": "^1.0", "phpunit/phpunit": "^10.5.24", "rector/rector": "^1.1.0", - "symfony/amqp-messenger": "^5.4.45", - "symfony/debug-bundle": "^5.4", - "symfony/dotenv": "^5.4", + "symfony/amqp-messenger": "^7.2", + "symfony/debug-bundle": "^7.2", + "symfony/dotenv": "^7.2", "symfony/flex": "^2.4", "symfony/maker-bundle": "^1.20", "symfony/phpunit-bridge": "^7.1", - "symfony/runtime": "^5.4", - "symfony/stopwatch": "^5.4", - "symfony/var-dumper": "^5.4", - "symfony/web-profiler-bundle": "^5.4" + "symfony/runtime": "^7.2", + "symfony/stopwatch": "^7.2", + "symfony/var-dumper": "^7.2", + "symfony/web-profiler-bundle": "^7.2" }, "conflict": { "symfony/symfony": "*" }, "autoload": { "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "src/Symfony/Component/DependencyInjection", + "ChampsLibres\\WopiBundle\\": "src/ChampsLibres/WopiBundle", "Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle", "Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src", "Chill\\BudgetBundle\\": "src/Bundle/ChillBudgetBundle", diff --git a/config/bundles.php b/config/bundles.php index ec11bc0b6..362edeaa2 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -14,7 +14,6 @@ return [ Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true], Misd\PhoneNumberBundle\MisdPhoneNumberBundle::class => ['all' => true], - Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 33a27cd5c..eff6fd08f 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -4,6 +4,16 @@ framework: #csrf_protection: true http_method_override: false + + # Enable EntityValueResolver for automatic entity injection in controllers + # This replaces the functionality previously provided by SensioFrameworkExtraBundle + http_client: + enabled: true + + request: + formats: + json: ['application/json'] + # Enables session support. Note that the session will ONLY be started if you read or write from it. # Remove or comment this section to explicitly disable session support. session: diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml index b460fd60c..72808c9a4 100644 --- a/config/packages/messenger.yaml +++ b/config/packages/messenger.yaml @@ -1,7 +1,5 @@ framework: messenger: - # reset services after consuming messages - reset_on_message: true # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling. failure_transport: failed diff --git a/config/packages/security.yaml b/config/packages/security.yaml index af2385ba9..3bbb58480 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,5 +1,4 @@ security: - enable_authenticator_manager: true # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' @@ -28,16 +27,13 @@ security: pattern: ^/wopi provider: chill_chain_provider stateless: true - guard: - authenticators: - - lexik_jwt_authentication.jwt_token_authenticator + jwt: ~ dav: pattern: ^/dav provider: chill_chain_provider stateless: true - guard: - authenticators: - - Chill\DocStoreBundle\Security\Guard\JWTOnDavUrlAuthenticator + custom_authenticator: + - Chill\DocStoreBundle\Security\Authenticator\JWTOnDavUrlAuthenticator # this firewall is the main firewall for chill. It should be the last one in the stack, # unless you have specific needs chill_main: diff --git a/config/packages/sensio_framework_extra.yaml b/config/packages/sensio_framework_extra.yaml deleted file mode 100644 index 1821ccc07..000000000 --- a/config/packages/sensio_framework_extra.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sensio_framework_extra: - router: - annotations: false diff --git a/config/routes/annotations.yaml b/config/routes/annotations.yaml index 9e01b60cd..4a6607377 100644 --- a/config/routes/annotations.yaml +++ b/config/routes/annotations.yaml @@ -1,3 +1,3 @@ kernel: resource: ../../src/app/Kernel.php - type: annotation + type: attribute diff --git a/config/services.yaml b/config/services.yaml index 11c095d99..12e740109 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -11,3 +11,7 @@ services: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + # Custom entity value resolver to replace SensioFrameworkExtraBundle functionality + Chill\MainBundle\ArgumentResolver\EntityValueResolver: + tags: + - { name: controller.argument_value_resolver, priority: 50 } diff --git a/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php index 112d49f60..b6d0d3f62 100644 --- a/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillActivityBundle/DependencyInjection/Configuration.php @@ -22,7 +22,7 @@ use function is_int; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_activity'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php index 241a545a8..431591a30 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillAsideActivityBundle/src/DependencyInjection/Configuration.php @@ -16,7 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_aside_activity'); diff --git a/src/Bundle/ChillBudgetBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillBudgetBundle/DependencyInjection/Configuration.php index ff9931f2d..24efa96e5 100644 --- a/src/Bundle/ChillBudgetBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillBudgetBundle/DependencyInjection/Configuration.php @@ -16,7 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_budget'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php index a3e4ae391..2e322566a 100644 --- a/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_calendar'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillCustomFieldsBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillCustomFieldsBundle/DependencyInjection/Configuration.php index e68fdd2c4..39baff71d 100644 --- a/src/Bundle/ChillCustomFieldsBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillCustomFieldsBundle/DependencyInjection/Configuration.php @@ -22,7 +22,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_custom_fields'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php index 495121f91..7800105ae 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php @@ -16,7 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('chill_doc_generator'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillDocStoreBundle/AsyncUpload/Driver/OpenstackObjectStore/ConfigureOpenstackObjectStorageCommand.php b/src/Bundle/ChillDocStoreBundle/AsyncUpload/Driver/OpenstackObjectStore/ConfigureOpenstackObjectStorageCommand.php index 13e0a6bbe..f9c633db7 100644 --- a/src/Bundle/ChillDocStoreBundle/AsyncUpload/Driver/OpenstackObjectStore/ConfigureOpenstackObjectStorageCommand.php +++ b/src/Bundle/ChillDocStoreBundle/AsyncUpload/Driver/OpenstackObjectStore/ConfigureOpenstackObjectStorageCommand.php @@ -19,6 +19,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; +#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:doc-store:configure-openstack')] class ConfigureOpenstackObjectStorageCommand extends Command { protected static $defaultDescription = 'Configure openstack container to store documents'; @@ -39,7 +40,6 @@ class ConfigureOpenstackObjectStorageCommand extends Command protected function configure() { $this - ->setName('chill:doc-store:configure-openstack') ->addOption('os_token', 'o', InputOption::VALUE_REQUIRED, 'Openstack token') ->addOption('domain', 'd', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Domain name') ; diff --git a/src/Bundle/ChillDocStoreBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillDocStoreBundle/DependencyInjection/Configuration.php index 2e046a810..af5263c67 100644 --- a/src/Bundle/ChillDocStoreBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillDocStoreBundle/DependencyInjection/Configuration.php @@ -22,7 +22,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_doc_store'); /** @var ArrayNodeDefinition $rootNode */ diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authenticator/DavOnUrlTokenExtractor.php b/src/Bundle/ChillDocStoreBundle/Security/Authenticator/DavOnUrlTokenExtractor.php new file mode 100644 index 000000000..71fee073a --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Security/Authenticator/DavOnUrlTokenExtractor.php @@ -0,0 +1,57 @@ +getRequestUri(); + + $segments = array_values( + array_filter( + explode('/', $uri), + fn ($item) => '' !== trim($item) + ) + ); + + if (2 > count($segments)) { + $this->logger->info('not enough segment for parsing URL'); + + return false; + } + + if ('dav' !== $segments[0]) { + $this->logger->info('the first segment of the url must be DAV'); + + return false; + } + + return $segments[1]; + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authenticator/JWTOnDavUrlAuthenticator.php b/src/Bundle/ChillDocStoreBundle/Security/Authenticator/JWTOnDavUrlAuthenticator.php new file mode 100644 index 000000000..6d9dbbea5 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Security/Authenticator/JWTOnDavUrlAuthenticator.php @@ -0,0 +1,77 @@ +davOnUrlTokenExtractor->extract($request); + } + + public function authenticate(Request $request): Passport + { + $token = $this->davOnUrlTokenExtractor->extract($request); + + if (false === $token) { + throw new MissingTokenException('JWT Token not found'); + } + + try { + $payload = $this->jwtManager->parse($token); + } catch (JWTDecodeFailureException $e) { + throw new InvalidTokenException('Invalid JWT Token', 0, $e); + } + + $username = $payload['username'] ?? $payload['email'] ?? $payload['user_id'] ?? null; + + if (null === $username) { + throw new InvalidTokenException('Invalid JWT Token: Username not found'); + } + + return new SelfValidatingPassport(new UserBadge($username)); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + // On success, let the request continue + return null; + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + throw $exception; + } +} diff --git a/src/Bundle/ChillEventBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillEventBundle/DependencyInjection/Configuration.php index fe42ad99a..f37ae1557 100644 --- a/src/Bundle/ChillEventBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillEventBundle/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_event'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/Configuration.php index 2d94678d4..ef3b36428 100644 --- a/src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillFranceTravailApiBundle/src/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_france_travail_api'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillJobBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillJobBundle/src/DependencyInjection/Configuration.php index f4140defa..b7ee2b51d 100644 --- a/src/Bundle/ChillJobBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillJobBundle/src/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_job'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillMainBundle/ArgumentResolver/EntityValueResolver.php b/src/Bundle/ChillMainBundle/ArgumentResolver/EntityValueResolver.php new file mode 100644 index 000000000..403820fa6 --- /dev/null +++ b/src/Bundle/ChillMainBundle/ArgumentResolver/EntityValueResolver.php @@ -0,0 +1,125 @@ +getType(); + if (null === $type || !class_exists($type) || !$this->isEntity($type)) { + return []; + } + + $name = $argument->getName(); + + // If the argument name is 'id', we don't want to resolve it as an entity + if ('id' === $name) { + return []; + } + + // Try to find the entity ID from various possible parameter names + $id = $this->findEntityId($request, $name, $type); + + if (null === $id) { + return []; + } + + $entity = $this->doctrine->getRepository($type)->find($id); + + if (null === $entity) { + return []; + } + + return [$entity]; + } + + /** + * Tries to find the entity ID from various possible parameter names. + * + * This method checks for the following parameter names in order: + * 1. The parameter name specified in the route (e.g., 'id', 'person_id', 'household_id') + * 2. A parameter named after the entity with 'Id' suffix (e.g., 'personId' for Person entity) + * 3. A parameter named after the entity with '_id' suffix (e.g., 'person_id' for Person entity) + * 4. The 'id' parameter as a fallback + */ + private function findEntityId(Request $request, string $name, string $type): mixed + { + // Common parameter naming patterns + $possibleNames = [ + $name . 'Id', + $name . '_id', + $this->getShortClassName($type) . '_id', + $this->getShortClassName($type) . 'Id', + 'id', + ]; + + // Special cases based on observed @ParamConverter usage + $specialCases = [ + 'Household' => ['household_id'], + 'AccompanyingCourse' => ['accompanying_period_id'], + 'AccompanyingPeriod' => ['accompanying_period_id'], + 'Event' => ['event_id'], + 'User' => ['userId'], + 'Person' => ['person_id'], + 'Action' => ['action_id'], + ]; + + // Add special cases if applicable + $shortClassName = $this->getShortClassName($type); + if (isset($specialCases[$shortClassName])) { + $possibleNames = array_merge($specialCases[$shortClassName], $possibleNames); + } + + // Try each possible parameter name + foreach ($possibleNames as $paramName) { + if ($request->attributes->has($paramName)) { + return $request->attributes->get($paramName); + } + } + + return null; + } + + /** + * Gets the short class name (without namespace) from a fully qualified class name. + */ + private function getShortClassName(string $class): string + { + $parts = explode('\\', $class); + return end($parts); + } + + private function isEntity(string $class): bool + { + if (!$this->doctrine->getManagerForClass($class) instanceof EntityManagerInterface) { + return false; + } + + return !$this->doctrine->getManagerForClass($class)->getMetadataFactory()->isTransient($class); + } +} diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php index 6625488dd..fc4fbb7c3 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php @@ -31,7 +31,7 @@ class Configuration implements ConfigurationInterface $this->setWidgetFactories($widgetFactories); } - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_main'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php index 12c8b4c5b..bcf450b48 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/Configuration.php @@ -25,7 +25,7 @@ class Configuration implements ConfigurationInterface .' any birthdate is not allowed. The birthdate is expressed as ISO8601 : ' .'https://en.wikipedia.org/wiki/ISO_8601#Durations'; - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('cl_chill_person'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillReportBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillReportBundle/DependencyInjection/Configuration.php index 70c9f532b..557283056 100644 --- a/src/Bundle/ChillReportBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillReportBundle/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_report'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillTaskBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillTaskBundle/DependencyInjection/Configuration.php index f01050684..cb70d4fd8 100644 --- a/src/Bundle/ChillTaskBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillTaskBundle/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_task'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillThirdPartyBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillThirdPartyBundle/DependencyInjection/Configuration.php index d4c2cd598..f3623c0e4 100644 --- a/src/Bundle/ChillThirdPartyBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillThirdPartyBundle/DependencyInjection/Configuration.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; */ class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_third_party'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/Bundle/ChillWopiBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillWopiBundle/src/DependencyInjection/Configuration.php index 50397ee62..55acfb5e7 100644 --- a/src/Bundle/ChillWopiBundle/src/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillWopiBundle/src/DependencyInjection/Configuration.php @@ -16,7 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; final class Configuration implements ConfigurationInterface { - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): \Symfony\Component\Config\Definition\Builder\TreeBuilder { $treeBuilder = new TreeBuilder('chill_wopi'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/ChampsLibres/WopiBundle/DependencyInjection/Configuration.php b/src/ChampsLibres/WopiBundle/DependencyInjection/Configuration.php new file mode 100644 index 000000000..4f8d4c267 --- /dev/null +++ b/src/ChampsLibres/WopiBundle/DependencyInjection/Configuration.php @@ -0,0 +1,37 @@ +getRootNode(); + + /** @phpstan-ignore-next-line */ + $rootNode + ->children() + ->scalarNode('server')->end() + ->enumNode('version_management')->values(['version', 'timestamp']) + ->info('Manager document versioning through version (Office 365) or last modified time (Collabora Online, CODE, etc.)') + ->defaultValue('timestamp') + ->end() + ->booleanNode('enable_lock')->defaultTrue()->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/Symfony/Component/DependencyInjection/ContainerAwareTrait.php b/src/Symfony/Component/DependencyInjection/ContainerAwareTrait.php new file mode 100644 index 000000000..397c19615 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/ContainerAwareTrait.php @@ -0,0 +1,25 @@ +container = $container; + } +}