From 052da9397bed84f5b1f76912102d349d7cf759d5 Mon Sep 17 00:00:00 2001 From: Vincent <407859+vincentchalamon@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:26:00 +0100 Subject: [PATCH] fix: fix Symfony 7.1 deprecation on DI component Extension class (#147) --- .github/workflows/ci.yml | 5 +- src/CoopTilleulsForgotPasswordBundle.php | 14 +++ src/DependencyInjection/BCExtensionTrait.php | 115 ++++++++++++++++++ .../CoopTilleulsForgotPasswordExtension.php | 99 +-------------- ...pTilleulsForgotPasswordLegacyExtension.php | 24 ++++ 5 files changed, 158 insertions(+), 99 deletions(-) create mode 100644 src/DependencyInjection/BCExtensionTrait.php create mode 100644 src/DependencyInjection/CoopTilleulsForgotPasswordLegacyExtension.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4caabce..d8374ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: - '8.1' - '8.2' - '8.3' + - '8.4' symfony: # Only Symfony supported versions: https://symfony.com/releases - '6.4.*' @@ -36,7 +37,7 @@ jobs: - '^3.4' - '^4.0' include: - - php: '8.3' + - php: '8.4' symfony: '7.1.*' api-platform: '^4.0' bootable: true @@ -87,7 +88,7 @@ jobs: - name: Run php-cs-fixer tests if: matrix.quality env: - # PHP CS Fixer does not support PHP 8.3 yet + # PHP CS Fixer may not support recent version(s) of PHP PHP_CS_FIXER_IGNORE_ENV: 1 run: php-cs-fixer fix --diff --dry-run - name: Bundle is bootable diff --git a/src/CoopTilleulsForgotPasswordBundle.php b/src/CoopTilleulsForgotPasswordBundle.php index 9319eeb..24c905f 100644 --- a/src/CoopTilleulsForgotPasswordBundle.php +++ b/src/CoopTilleulsForgotPasswordBundle.php @@ -16,6 +16,7 @@ use CoopTilleuls\ForgotPasswordBundle\DependencyInjection\CompilerPass\ApiPlatformCompilerPass; use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\HttpKernel\Bundle\Bundle; /** @@ -38,4 +39,17 @@ public function build(ContainerBuilder $container): void ])); } } + + /** + * {@inheritdoc} + */ + protected function getContainerExtensionClass(): string + { + return \sprintf( + '%s\\DependencyInjection\\%s%sExtension', + $this->getNamespace(), + preg_replace('/Bundle$/', '', $this->getName()), + class_exists(Extension::class) ? '' : 'Legacy' + ); + } } diff --git a/src/DependencyInjection/BCExtensionTrait.php b/src/DependencyInjection/BCExtensionTrait.php new file mode 100644 index 0000000..a5ab545 --- /dev/null +++ b/src/DependencyInjection/BCExtensionTrait.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace CoopTilleuls\ForgotPasswordBundle\DependencyInjection; + +use CoopTilleuls\ForgotPasswordBundle\Normalizer\JMSNormalizer; +use CoopTilleuls\ForgotPasswordBundle\Normalizer\SymfonyNormalizer; +use CoopTilleuls\ForgotPasswordBundle\Provider\Provider; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Vincent CHALAMON + */ +trait BCExtensionTrait +{ + public function load(array $configs, ContainerBuilder $container): void + { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + if (!$defaultProvider = $this->getDefaultProvider($config)) { + throw new InvalidConfigurationException('Multiple "ForgotPassword" providers have been defined but none of them is set as default. Did you forget to set "default" option?'); + } + + // Build parameters + $container->setParameter('coop_tilleuls_forgot_password.password_token_class', $defaultProvider['password_token']['class']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_class'); + $container->setParameter('coop_tilleuls_forgot_password.password_token_expires_in', $defaultProvider['password_token']['expires_in']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_expires_in'); + $container->setParameter('coop_tilleuls_forgot_password.password_token_user_field', $defaultProvider['password_token']['user_field']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_user_field'); + $container->setParameter('coop_tilleuls_forgot_password.password_token_serialization_groups', $defaultProvider['password_token']['serialization_groups']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_serialization_groups'); + $container->setParameter('coop_tilleuls_forgot_password.user_class', $defaultProvider['user']['class']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_class'); + $authorizedFields = array_unique(array_merge($defaultProvider['user']['authorized_fields'], [$defaultProvider['user']['email_field']])); + $container->setParameter('coop_tilleuls_forgot_password.user_authorized_fields', $authorizedFields); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_authorized_fields'); + $container->setParameter('coop_tilleuls_forgot_password.user_password_field', $defaultProvider['user']['password_field']); + trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_password_field'); + + $this->buildProvider($config, $container); + + $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../config')); + $loader->load('services.xml'); + + // Load API-Platform bridge + if (isset($container->getParameter('kernel.bundles')['ApiPlatformBundle'])) { + $loader->load('api_platform.xml'); + } + + $alias = $container->setAlias('coop_tilleuls_forgot_password.manager', $defaultProvider['manager']); + if (method_exists(Definition::class, 'getDeprecation')) { + $alias->setDeprecated('tilleuls/forgot-password-bundle', '1.5', 'Alias "%alias_id%" is deprecated and will be removed without replacement in 2.0.'); + } else { + $alias->setDeprecated(true, 'Alias "%alias_id%" is deprecated and will be removed without replacement in 2.0.'); + } + + // Build normalizer + $class = true === $config['use_jms_serializer'] ? JMSNormalizer::class : SymfonyNormalizer::class; + $serializerId = true === $config['use_jms_serializer'] ? 'jms_serializer.serializer' : 'serializer'; + $container->setDefinition('coop_tilleuls_forgot_password.normalizer', new Definition($class, [new Reference($serializerId)]))->setPublic(false); + + $container + ->getDefinition('coop_tilleuls_forgot_password.manager.password_token') + ->replaceArgument(1, new Reference($config['token_generator'])); + } + + private function buildProvider(array $config, ContainerBuilder $container): void + { + foreach ($config['providers'] as $key => $value) { + $container->setDefinition($key, new Definition(Provider::class, + [ + new Reference($value['manager']), + $key, + $value['password_token']['class'], + $value['password_token']['expires_in'], + $value['password_token']['user_field'], + $value['user']['class'], + $value['password_token']['serialization_groups'], + $value['user']['email_field'], + $value['user']['password_field'], + array_unique(array_merge($value['user']['authorized_fields'], [$value['user']['email_field']])), + $value['default'], + ]))->setPublic(false) + ->addTag('coop_tilleuls_forgot_password.provider'); + } + } + + private function getDefaultProvider(array $config): ?array + { + foreach ($config['providers'] as $value) { + if (true === $value['default']) { + return $value; + } + } + + return null; + } +} diff --git a/src/DependencyInjection/CoopTilleulsForgotPasswordExtension.php b/src/DependencyInjection/CoopTilleulsForgotPasswordExtension.php index 1da5abd..dcab0c6 100644 --- a/src/DependencyInjection/CoopTilleulsForgotPasswordExtension.php +++ b/src/DependencyInjection/CoopTilleulsForgotPasswordExtension.php @@ -13,107 +13,12 @@ namespace CoopTilleuls\ForgotPasswordBundle\DependencyInjection; -use CoopTilleuls\ForgotPasswordBundle\Normalizer\JMSNormalizer; -use CoopTilleuls\ForgotPasswordBundle\Normalizer\SymfonyNormalizer; -use CoopTilleuls\ForgotPasswordBundle\Provider\Provider; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\Extension\Extension; /** * @author Vincent CHALAMON */ final class CoopTilleulsForgotPasswordExtension extends Extension { - /** - * {@inheritdoc} - */ - public function load(array $configs, ContainerBuilder $container): void - { - $configuration = new Configuration(); - $config = $this->processConfiguration($configuration, $configs); - - if (!$defaultProvider = $this->getDefaultProvider($config)) { - throw new InvalidConfigurationException('Multiple "ForgotPassword" providers have been defined but none of them is set as default. Did you forget to set "default" option?'); - } - - // Build parameters - $container->setParameter('coop_tilleuls_forgot_password.password_token_class', $defaultProvider['password_token']['class']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_class'); - $container->setParameter('coop_tilleuls_forgot_password.password_token_expires_in', $defaultProvider['password_token']['expires_in']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_expires_in'); - $container->setParameter('coop_tilleuls_forgot_password.password_token_user_field', $defaultProvider['password_token']['user_field']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_user_field'); - $container->setParameter('coop_tilleuls_forgot_password.password_token_serialization_groups', $defaultProvider['password_token']['serialization_groups']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.password_token_serialization_groups'); - $container->setParameter('coop_tilleuls_forgot_password.user_class', $defaultProvider['user']['class']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_class'); - $authorizedFields = array_unique(array_merge($defaultProvider['user']['authorized_fields'], [$defaultProvider['user']['email_field']])); - $container->setParameter('coop_tilleuls_forgot_password.user_authorized_fields', $authorizedFields); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_authorized_fields'); - $container->setParameter('coop_tilleuls_forgot_password.user_password_field', $defaultProvider['user']['password_field']); - trigger_deprecation('tilleuls/forgot-password-bundle', '1.5', 'Container parameter "%s" is deprecated since 1.5 and will be removed without replacement in 2.0.', 'coop_tilleuls_forgot_password.user_password_field'); - - $this->buildProvider($config, $container); - - $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../config')); - $loader->load('services.xml'); - - // Load API-Platform bridge - if (isset($container->getParameter('kernel.bundles')['ApiPlatformBundle'])) { - $loader->load('api_platform.xml'); - } - - $alias = $container->setAlias('coop_tilleuls_forgot_password.manager', $defaultProvider['manager']); - if (method_exists(Definition::class, 'getDeprecation')) { - $alias->setDeprecated('tilleuls/forgot-password-bundle', '1.5', 'Alias "%alias_id%" is deprecated and will be removed without replacement in 2.0.'); - } else { - $alias->setDeprecated(true, 'Alias "%alias_id%" is deprecated and will be removed without replacement in 2.0.'); - } - - // Build normalizer - $class = true === $config['use_jms_serializer'] ? JMSNormalizer::class : SymfonyNormalizer::class; - $serializerId = true === $config['use_jms_serializer'] ? 'jms_serializer.serializer' : 'serializer'; - $container->setDefinition('coop_tilleuls_forgot_password.normalizer', new Definition($class, [new Reference($serializerId)]))->setPublic(false); - - $container - ->getDefinition('coop_tilleuls_forgot_password.manager.password_token') - ->replaceArgument(1, new Reference($config['token_generator'])); - } - - private function buildProvider(array $config, ContainerBuilder $container): void - { - foreach ($config['providers'] as $key => $value) { - $container->setDefinition($key, new Definition(Provider::class, - [ - new Reference($value['manager']), - $key, - $value['password_token']['class'], - $value['password_token']['expires_in'], - $value['password_token']['user_field'], - $value['user']['class'], - $value['password_token']['serialization_groups'], - $value['user']['email_field'], - $value['user']['password_field'], - array_unique(array_merge($value['user']['authorized_fields'], [$value['user']['email_field']])), - $value['default'], - ]))->setPublic(false) - ->addTag('coop_tilleuls_forgot_password.provider'); - } - } - - private function getDefaultProvider(array $config): ?array - { - foreach ($config['providers'] as $value) { - if (true === $value['default']) { - return $value; - } - } - - return null; - } + use BCExtensionTrait; } diff --git a/src/DependencyInjection/CoopTilleulsForgotPasswordLegacyExtension.php b/src/DependencyInjection/CoopTilleulsForgotPasswordLegacyExtension.php new file mode 100644 index 0000000..fa959fa --- /dev/null +++ b/src/DependencyInjection/CoopTilleulsForgotPasswordLegacyExtension.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace CoopTilleuls\ForgotPasswordBundle\DependencyInjection; + +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +/** + * @author Vincent CHALAMON + */ +final class CoopTilleulsForgotPasswordLegacyExtension extends Extension +{ + use BCExtensionTrait; +}