diff --git a/.github/expected-missing-return-types.diff b/.github/expected-missing-return-types.diff index 5f3b6f4a91f56..2545ad099f7a1 100644 --- a/.github/expected-missing-return-types.diff +++ b/.github/expected-missing-return-types.diff @@ -2389,10 +2389,10 @@ index cecce6c01b..f2e0c7fdf5 100644 { parent::newLine($count); diff --git a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php -index 6ad89dc522..40020baee7 100644 +index 10bed7d031..e26109851f 100644 --- a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php +++ b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php -@@ -141,5 +141,5 @@ class NonStringInput extends Input +@@ -128,5 +128,5 @@ class NonStringInput extends Input } - public function parse() @@ -9981,17 +9981,17 @@ index eabfe17bba..5a41823338 100644 { throw new \BadMethodCallException('Cannot add attribute to NullToken.'); diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php -index 0ec6b1cfb9..2e235a6069 100644 +index 8acc31bca2..25779a31b5 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php @@ -41,5 +41,5 @@ class TokenStorage implements TokenStorageInterface, ResetInterface * @return void */ -- public function setToken(TokenInterface $token = null) -+ public function setToken(TokenInterface $token = null): void +- public function setToken(?TokenInterface $token) ++ public function setToken(?TokenInterface $token): void { - if (1 > \func_num_args()) { -@@ -64,5 +64,5 @@ class TokenStorage implements TokenStorageInterface, ResetInterface + if ($token) { +@@ -60,5 +60,5 @@ class TokenStorage implements TokenStorageInterface, ResetInterface * @return void */ - public function reset() @@ -10172,23 +10172,16 @@ index a493b00e79..377dcacc09 100644 { } diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php -index e0aef90a14..651578d1f1 100644 +index 13441bc758..e2bc96ff48 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php -@@ -55,5 +55,5 @@ class InMemoryUserProvider implements UserProviderInterface - * @throws \LogicException +@@ -53,5 +53,5 @@ class InMemoryUserProvider implements UserProviderInterface + * @return void */ - public function createUser(UserInterface $user) + public function createUser(UserInterface $user): void { if (!$user instanceof InMemoryUser) { -@@ -100,5 +100,5 @@ class InMemoryUserProvider implements UserProviderInterface - * @throws UserNotFoundException if user whose given username does not exist - */ -- private function getUser(string $username): UserInterface -+ private function getUser(string $username): InMemoryUser - { - if (!isset($this->users[strtolower($username)])) { diff --git a/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php b/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php index 91f21c71d0..95e818392e 100644 --- a/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php diff --git a/.github/patch-types.php b/.github/patch-types.php index da7f508219140..7cf5d80d64345 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -24,6 +24,7 @@ // no break; case false !== strpos($file, '/vendor/'): case false !== strpos($file, '/src/Symfony/Bridge/PhpUnit/'): + case false !== strpos($file, '/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/ContainerAwareController.php'): case false !== strpos($file, '/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php'): case false !== strpos($file, '/src/Symfony/Component/Cache/Tests/Fixtures/DriverWrapper.php'): case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadFileName.php'): diff --git a/UPGRADE-6.4.md b/UPGRADE-6.4.md index 58cbb0d322ada..b9d6020dbbfde 100644 --- a/UPGRADE-6.4.md +++ b/UPGRADE-6.4.md @@ -1,6 +1,11 @@ UPGRADE FROM 6.3 to 6.4 ======================= +Cache +----- + + * `EarlyExpirationHandler` no longer implements `MessageHandlerInterface`, rely on `AsMessageHandler` instead + DependencyInjection ------------------- @@ -14,6 +19,11 @@ DoctrineBridge * Deprecate `DoctrineDataCollector::addLogger()`, use a `DebugDataHolder` instead * Deprecate `ContainerAwareLoader`, use dependency injection in your fixtures instead +ErrorHandler +------------ + + * `FlattenExceptionNormalizer` no longer implements `ContextAwareNormalizerInterface` + Form ---- @@ -24,3 +34,13 @@ HttpFoundation -------------- * Make `HeaderBag::getDate()`, `Response::getDate()`, `getExpires()` and `getLastModified()` return a `DateTimeImmutable` + +HttpKernel +---------- + + * `BundleInterface` no longer extends `ContainerAwareInterface` + +Security +-------- + + * `UserValueResolver` no longer implements `ArgumentValueResolverInterface` diff --git a/UPGRADE-7.0.md b/UPGRADE-7.0.md index 4c294b66bffc8..d8c88af9916bb 100644 --- a/UPGRADE-7.0.md +++ b/UPGRADE-7.0.md @@ -4,6 +4,7 @@ UPGRADE FROM 6.4 to 7.0 Symfony 6.4 and Symfony 7.0 will be released simultaneously at the end of November 2023. According to the Symfony release process, both versions will have the same features, but Symfony 7.0 won't include any deprecated features. To upgrade, make sure to resolve all deprecation notices. +Read more about this in the [Symfony documentation](https://symfony.com/doc/current/setup/upgrade_major.html). Cache ----- @@ -14,6 +15,32 @@ Console ------- * Remove `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead + + *Before* + ```php + use Symfony\Component\Console\Command\Command; + + class CreateUserCommand extends Command + { + protected static $defaultName = 'app:create-user'; + protected static $defaultDescription = 'Creates users'; + + // ... + } + ``` + + *After* + ```php + use Symfony\Component\Console\Attribute\AsCommand; + use Symfony\Component\Console\Command\Command; + + #[AsCommand(name: 'app:create-user', description: 'Creates users')] + class CreateUserCommand extends Command + { + // ... + } + ``` + * Passing null to `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()` and `Question::setAutocompleterCallback/setValidator()` must be done explicitly * Remove `StringInput::REGEX_STRING` * Add method `__toString()` to `InputInterface` @@ -45,6 +72,11 @@ DoctrineBridge * DoctrineBridge now requires `doctrine/event-manager:^2` * Add parameter `$isSameDatabase` to `DoctrineTokenProvider::configureSchema()` +ExpressionLanguage +------------------ + + * The `in` and `not in` operators now use strict comparison + Filesystem ---------- @@ -68,21 +100,38 @@ HttpFoundation * Remove `Request::getContentType()`, use `Request::getContentTypeFormat()` instead * Throw an `InvalidArgumentException` when calling `Request::create()` with a malformed URI +HttpClient +---------- + + * Remove implementing `Http\Message\RequestFactory` from `HttplugClient` + HttpKernel ---------- * Add argument `$reflector` to `ArgumentResolverInterface::getArguments()` and `ArgumentMetadataFactoryInterface::createArgumentMetadata()` + * Remove `ArgumentValueResolverInterface`, use `ValueResolverInterface` instead + * Remove `StreamedResponseListener` + * Remove `AbstractSurrogate::$phpEscapeMap` + * Remove `HttpKernelInterface::MASTER_REQUEST` + * Remove `terminate_on_cache_hit` option from `HttpCache` Lock ---- * Add parameter `$isSameDatabase` to `DoctrineDbalStore::configureSchema()` + * Remove the `gcProbablity` (notice the typo) option, use `gcProbability` instead Messenger --------- * Add parameter `$isSameDatabase` to `DoctrineTransport::configureSchema()` +Mime +---- + + * Remove `Email::attachPart()` method, use `Email::addPart()` instead + * Parameter `$body` is now required (at least null) in `Message::setBody()` + PropertyAccess -------------- @@ -107,7 +156,7 @@ Security SecurityBundle -------------- - * Enabling SecurityBundle and not configuring it is not allowed + * Enabling SecurityBundle and not configuring it is not allowed, either remove the bundle or configure at least one firewall Serializer ---------- @@ -115,9 +164,75 @@ Serializer * Add method `getSupportedTypes()` to `DenormalizerInterface` and `NormalizerInterface` * Remove denormalization support for `AbstractUid` in `UidNormalizer`, use one of `AbstractUid` child class instead * Denormalizing to an abstract class in `UidNormalizer` now throws an `\Error` - * Remove `ContextAwareDenormalizerInterface`, use `DenormalizerInterface` instead - * Remove `ContextAwareNormalizerInterface`, use `NormalizerInterface` instead + * Remove `ContextAwareDenormalizerInterface` and `ContextAwareNormalizerInterface`, use `DenormalizerInterface` and `NormalizerInterface` instead + + *Before* + ```php + use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; + + class TopicNormalizer implements ContextAwareNormalizerInterface + { + public function normalize($topic, string $format = null, array $context = []) + { + } + } + ``` + + *After* + ```php + use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + + class TopicNormalizer implements NormalizerInterface + { + public function normalize($topic, string $format = null, array $context = []) + { + } + } + ``` * Remove `CacheableSupportsMethodInterface`, use `NormalizerInterface` and `DenormalizerInterface` instead + + *Before* + ```php + use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; + + class TopicNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface + { + public function supportsNormalization($data, string $format = null, array $context = []): bool + { + return $data instanceof Topic; + } + + public function hasCacheableSupportsMethod(): bool + { + return true; + } + + // ... + } + ``` + + *After* + ```php + use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + + class TopicNormalizer implements NormalizerInterface + { + public function supportsNormalization($data, string $format = null, array $context = []): bool + { + return $data instanceof Topic; + } + + public function getSupportedTypes(?string $format): array + { + return [ + Topic::class => true, + ]; + } + + // ... + } + ``` * First argument of `AttributeMetadata::setSerializedName()` is now required * Add argument `$context` to `NormalizerInterface::supportsNormalization()` and `DenormalizerInterface::supportsDenormalization()` @@ -127,6 +242,9 @@ Validator * Add methods `getConstraint()`, `getCause()` and `__toString()` to `ConstraintViolationInterface` * Add method `__toString()` to `ConstraintViolationListInterface` * Add method `disableTranslation()` to `ConstraintViolationBuilderInterface` + * Remove static property `$errorNames` from all constraints, use const `ERROR_NAMES` instead + * Remove `VALIDATION_MODE_LOOSE` from `Email` constraint, use `VALIDATION_MODE_HTML5` instead + * Remove constraint `ExpressionLanguageSyntax`, use `ExpressionSyntax` instead VarDumper --------- diff --git a/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php index f4f7075dff7ed..c2d1c9b3df3b4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php @@ -275,5 +275,7 @@ public function testWithoutStopwatch(callable $sqlMethod, callable $endTransacti $this->conn->beginTransaction(); $sqlMethod($this->conn, 'SELECT * FROM products'); $endTransactionMethod($this->conn); + + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php index 2dd5c7125aa2d..14d7b39d162ed 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php @@ -39,11 +39,6 @@ class UniqueEntity extends Constraint public $errorPath; public $ignoreNull = true; - /** - * @deprecated since Symfony 6.1, use const ERROR_NAMES instead - */ - protected static $errorNames = self::ERROR_NAMES; - /** * @param array|string $fields The combination of fields that must contain unique values or a set of options * @param bool|array|string $ignoreNull The combination of fields that ignore null values diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4b79ab73634fc..f5ddf2fac6aa3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -95,7 +95,6 @@ use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -596,8 +595,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('container.service_locator'); $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) ->addTag('container.service_subscriber'); - $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) - ->addTag('controller.argument_value_resolver'); $container->registerForAutoconfiguration(ValueResolverInterface::class) ->addTag('controller.argument_value_resolver'); $container->registerForAutoconfiguration(AbstractController::class) diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 02c014bbfb70d..4f0821acef087 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -5,6 +5,12 @@ CHANGELOG --- * Enabling SecurityBundle and not configuring it is not allowed + * Remove configuration options `enable_authenticator_manager` and `csrf_token_generator` + +6.4 +--- + + * Deprecate `Security::ACCESS_DENIED_ERROR`, `AUTHENTICATION_ERROR` and `LAST_USERNAME` constants, use the ones on `SecurityRequestAttributes` instead 6.3 --- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index e982fc1871940..1e4d0d95bf3f2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -65,7 +65,6 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->booleanNode('hide_user_not_found')->defaultTrue()->end() ->booleanNode('erase_credentials')->defaultTrue()->end() - ->booleanNode('enable_authenticator_manager')->setDeprecated('symfony/security-bundle', '6.2', 'The "%node%" option at "%path%" is deprecated.')->defaultTrue()->end() ->arrayNode('access_decision_manager') ->addDefaultsIfNotSet() ->children() @@ -216,14 +215,6 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->arrayNode('logout') ->treatTrueLike([]) ->canBeUnset() - ->beforeNormalization() - ->ifTrue(fn ($v): bool => isset($v['csrf_token_generator']) && !isset($v['csrf_token_manager'])) - ->then(function (array $v): array { - $v['csrf_token_manager'] = $v['csrf_token_generator']; - - return $v; - }) - ->end() ->beforeNormalization() ->ifTrue(fn ($v): bool => \is_array($v) && (isset($v['csrf_token_manager']) xor isset($v['enable_csrf']))) ->then(function (array $v): array { @@ -240,13 +231,6 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->booleanNode('enable_csrf')->defaultNull()->end() ->scalarNode('csrf_token_id')->defaultValue('logout')->end() ->scalarNode('csrf_parameter')->defaultValue('_csrf_token')->end() - ->scalarNode('csrf_token_generator') - ->setDeprecated( - 'symfony/security-bundle', - '6.3', - 'The "%node%" option is deprecated. Use "csrf_token_manager" instead.' - ) - ->end() ->scalarNode('csrf_token_manager')->end() ->scalarNode('path')->defaultValue('/logout')->end() ->scalarNode('target')->defaultValue('/')->end() diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php index 177fda4feb5a4..fdcdb3a2e8d85 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php @@ -11,8 +11,6 @@ namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory; -use Symfony\Component\Config\Definition\Builder\NodeDefinition; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -50,23 +48,8 @@ public function getKey(): string return 'form-login'; } - public function addConfiguration(NodeDefinition $node): void - { - parent::addConfiguration($node); - - $node - ->children() - ->scalarNode('csrf_token_generator')->cannotBeEmpty()->end() - ->end() - ; - } - public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string { - if (isset($config['csrf_token_generator'])) { - throw new InvalidConfigurationException('The "csrf_token_generator" on "form_login" does not exist, use "enable_csrf" instead.'); - } - $authenticatorId = 'security.authenticator.form_login.'.$firewallName; $options = array_intersect_key($config, $this->options); $authenticator = $container diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 2224aab17be8e..8718844202d07 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -54,7 +54,6 @@ use Symfony\Component\Security\Core\Authorization\Strategy\PriorityStrategy; use Symfony\Component\Security\Core\Authorization\Strategy\UnanimousStrategy; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; -use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\User\ChainUserChecker; use Symfony\Component\Security\Core\User\ChainUserProvider; use Symfony\Component\Security\Core\User\UserCheckerInterface; @@ -91,7 +90,7 @@ public function prepend(ContainerBuilder $container): void public function load(array $configs, ContainerBuilder $container): void { if (!array_filter($configs)) { - throw new InvalidArgumentException(sprintf('Enabling bundle "%s" and not configuring it is not allowed.', SecurityBundle::class)); + throw new InvalidConfigurationException(sprintf('Enabling bundle "%s" and not configuring it is not allowed.', SecurityBundle::class)); } $mainConfig = $this->getConfiguration($configs, $container); @@ -104,11 +103,6 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('security.php'); $loader->load('password_hasher.php'); $loader->load('security_listeners.php'); - - if (!$config['enable_authenticator_manager']) { - throw new InvalidConfigurationException('"security.enable_authenticator_manager" must be set to "true".'); - } - $loader->load('security_authenticator.php'); $loader->load('security_authenticator_access_token.php'); @@ -177,16 +171,8 @@ public function load(array $configs, ContainerBuilder $container): void $container->registerForAutoconfiguration(VoterInterface::class) ->addTag('security.voter'); - - // required for compatibility with Symfony 5.4 - $container->getDefinition('security.access_listener')->setArgument(3, false); - $container->getDefinition('security.authorization_checker')->setArgument(2, false); - $container->getDefinition('security.authorization_checker')->setArgument(3, false); } - /** - * @throws \InvalidArgumentException if the $strategy is invalid - */ private function createStrategyDefinition(string $strategy, bool $allowIfAllAbstainDecisions, bool $allowIfEqualGrantedDeniedDecisions): Definition { return match ($strategy) { @@ -194,7 +180,7 @@ private function createStrategyDefinition(string $strategy, bool $allowIfAllAbst MainConfiguration::STRATEGY_CONSENSUS => new Definition(ConsensusStrategy::class, [$allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions]), MainConfiguration::STRATEGY_UNANIMOUS => new Definition(UnanimousStrategy::class, [$allowIfAllAbstainDecisions]), MainConfiguration::STRATEGY_PRIORITY => new Definition(PriorityStrategy::class, [$allowIfAllAbstainDecisions]), - default => throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy)), + default => throw new InvalidConfigurationException(sprintf('The strategy "%s" is not supported.', $strategy)), }; } @@ -669,15 +655,11 @@ private function getUserProvider(ContainerBuilder $container, string $id, array return $this->createMissingUserProvider($container, $id, $factoryKey); } - if ('remember_me' === $factoryKey || 'anonymous' === $factoryKey || 'custom_authenticators' === $factoryKey) { - if ('custom_authenticators' === $factoryKey) { - trigger_deprecation('symfony/security-bundle', '5.4', 'Not configuring explicitly the provider for the "%s" firewall is deprecated because it\'s ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.', $id); - } - + if ('remember_me' === $factoryKey || 'anonymous' === $factoryKey) { return 'security.user_providers'; } - throw new InvalidConfigurationException(sprintf('Not configuring explicitly the provider for the "%s" authenticator on "%s" firewall is ambiguous as there is more than one registered provider.', $factoryKey, $id)); + throw new InvalidConfigurationException(sprintf('Not configuring explicitly the provider for the "%s" authenticator on "%s" firewall is ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.', $factoryKey, $id)); } private function createMissingUserProvider(ContainerBuilder $container, string $id, string $factoryKey): string diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php index 27cc0ce51e9c3..7ed2738936e45 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php @@ -35,7 +35,6 @@ use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; -use Symfony\Component\Security\Core\Security as LegacySecurity; use Symfony\Component\Security\Core\User\ChainUserProvider; use Symfony\Component\Security\Core\User\InMemoryUserChecker; use Symfony\Component\Security\Core\User\InMemoryUserProvider; @@ -94,8 +93,6 @@ abstract_arg('authenticators'), ]) ->alias(Security::class, 'security.helper') - ->alias(LegacySecurity::class, 'security.helper') - ->deprecate('symfony/security-bundle', '6.2', 'The "%alias_id%" service alias is deprecated, use "'.Security::class.'" instead.') ->set('security.user_value_resolver', UserValueResolver::class) ->args([ diff --git a/src/Symfony/Bundle/SecurityBundle/Security.php b/src/Symfony/Bundle/SecurityBundle/Security.php index d5cd800e020a8..43398786ac24f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security.php +++ b/src/Symfony/Bundle/SecurityBundle/Security.php @@ -16,15 +16,15 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\LogicException; use Symfony\Component\Security\Core\Exception\LogoutException; -use Symfony\Component\Security\Core\Security as LegacySecurity; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; use Symfony\Component\Security\Http\Event\LogoutEvent; use Symfony\Component\Security\Http\ParameterBagUtils; -use Symfony\Component\Security\Http\SecurityRequestAttributes; use Symfony\Contracts\Service\ServiceProviderInterface; /** @@ -36,15 +36,35 @@ * * @final */ -class Security extends LegacySecurity +class Security implements AuthorizationCheckerInterface { - public const ACCESS_DENIED_ERROR = SecurityRequestAttributes::ACCESS_DENIED_ERROR; - public const AUTHENTICATION_ERROR = SecurityRequestAttributes::AUTHENTICATION_ERROR; - public const LAST_USERNAME = SecurityRequestAttributes::LAST_USERNAME; + public function __construct( + private readonly ContainerInterface $container, + private readonly array $authenticators = [], + ) { + } + + public function getUser(): ?UserInterface + { + if (!$token = $this->getToken()) { + return null; + } + + return $token->getUser(); + } + + /** + * Checks if the attributes are granted against the current authentication token and optionally supplied subject. + */ + public function isGranted(mixed $attributes, mixed $subject = null): bool + { + return $this->container->get('security.authorization_checker') + ->isGranted($attributes, $subject); + } - public function __construct(private readonly ContainerInterface $container, private readonly array $authenticators = []) + public function getToken(): ?TokenInterface { - parent::__construct($container, false); + return $this->container->get('security.token_storage')->getToken(); } public function getFirewallConfig(Request $request): ?FirewallConfig diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 170bce8169c64..cc93d323df7e9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -30,7 +30,6 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\User\InMemoryUserChecker; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -38,7 +37,6 @@ use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; use Symfony\Component\Security\Http\Authenticator\HttpBasicAuthenticator; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; -use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; class SecurityExtensionTest extends TestCase { @@ -162,8 +160,6 @@ public function testPerListenerProvider() public function testMissingProviderForListener() { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('Not configuring explicitly the provider for the "http_basic" authenticator on "ambiguous" firewall is ambiguous as there is more than one registered provider.'); $container = $this->getRawContainer(); $container->loadFromExtension('security', [ 'providers' => [ @@ -179,6 +175,9 @@ public function testMissingProviderForListener() ], ]); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('Not configuring explicitly the provider for the "http_basic" authenticator on "ambiguous" firewall is ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.'); + $container->compile(); } @@ -476,31 +475,6 @@ public function testDoNotRegisterTheUserProviderAliasWithMultipleProviders() $this->assertFalse($container->has(UserProviderInterface::class)); } - /** - * @group legacy - */ - public function testFirewallWithNoUserProviderTriggerDeprecation() - { - $container = $this->getRawContainer(); - - $container->loadFromExtension('security', [ - 'providers' => [ - 'first' => ['id' => 'foo'], - 'second' => ['id' => 'foo'], - ], - - 'firewalls' => [ - 'some_firewall' => [ - 'custom_authenticator' => 'my_authenticator', - ], - ], - ]); - - $this->expectDeprecation('Since symfony/security-bundle 5.4: Not configuring explicitly the provider for the "some_firewall" firewall is deprecated because it\'s ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.'); - - $container->compile(); - } - /** * @dataProvider acceptableIpsProvider */ @@ -878,7 +852,7 @@ public function testNothingDoneWithEmptyConfiguration() $container->loadFromExtension('security'); - $this->expectException(InvalidArgumentException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('Enabling bundle "Symfony\Bundle\SecurityBundle\SecurityBundle" and not configuring it is not allowed.'); $container->compile(); @@ -923,13 +897,6 @@ public function authenticate(Request $request): Passport { } - /** - * @internal for compatibility with Symfony 5.4 - */ - public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface - { - } - public function createToken(Passport $passport, string $firewallName): TokenInterface { } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php index ca99dbf3eadab..a3f539a59c57a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php @@ -13,21 +13,6 @@ class AuthenticatorTest extends AbstractWebTestCase { - /** - * @group legacy - * - * @dataProvider provideEmails - */ - public function testLegacyGlobalUserProvider($email) - { - $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'implicit_user_provider.yml']); - - $client->request('GET', '/profile', [], [], [ - 'HTTP_X-USER-EMAIL' => $email, - ]); - $this->assertJsonStringEqualsJsonString('{"email":"'.$email.'"}', $client->getResponse()->getContent()); - } - /** * @dataProvider provideEmails */ diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 58aa921686204..7b15ebf3e2276 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -125,7 +125,7 @@ public function process(ContainerBuilder $container): void $container->getDefinition('twig.extension.expression')->addTag('twig.extension'); } - if (!class_exists(Workflow::class) || !$container->has('workflow.registry')) { + if (!class_exists(Workflow::class) || !$container->has('.workflow.registry')) { $container->removeDefinition('workflow.twig_extension'); } else { $container->getDefinition('workflow.twig_extension')->addTag('twig.extension'); diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index 5a22ec4d032a2..a21f3dece03f8 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -6,6 +6,11 @@ CHANGELOG * Add parameter `$isSameDatabase` to `DoctrineDbalAdapter::configureSchema()` +6.4 +--- + + * `EarlyExpirationHandler` no longer implements `MessageHandlerInterface`, rely on `AsMessageHandler` instead + 6.3 --- diff --git a/src/Symfony/Component/Cache/Messenger/EarlyExpirationHandler.php b/src/Symfony/Component/Cache/Messenger/EarlyExpirationHandler.php index 38b594c289252..b7155fbf97218 100644 --- a/src/Symfony/Component/Cache/Messenger/EarlyExpirationHandler.php +++ b/src/Symfony/Component/Cache/Messenger/EarlyExpirationHandler.php @@ -13,12 +13,13 @@ use Symfony\Component\Cache\CacheItem; use Symfony\Component\DependencyInjection\ReverseContainer; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; +use Symfony\Component\Messenger\Attribute\AsMessageHandler; /** * Computes cached values sent to a message bus. */ -class EarlyExpirationHandler implements MessageHandlerInterface +#[AsMessageHandler] +class EarlyExpirationHandler { private ReverseContainer $reverseContainer; private array $processedNonces = []; diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index e851f20b76fe9..ef7a9b420fbdd 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -175,6 +175,9 @@ public function testEventSubscriber() $this->assertTrue($res->isFresh(0)); } + /** + * @group legacy + */ public function testMessageSubscriber() { $res = new ReflectionClassResource(new \ReflectionClass(TestMessageSubscriber::class)); @@ -229,18 +232,20 @@ public static function getSubscribedEvents(): array } } -class TestMessageSubscriber implements MessageSubscriberInterface -{ - public static function getHandledMessages(): iterable +if (interface_exists(MessageSubscriberInterface::class)) { + class TestMessageSubscriber implements MessageSubscriberInterface { - foreach (TestMessageSubscriberConfigHolder::$handledMessages as $key => $subscribedMessage) { - yield $key => $subscribedMessage; + public static function getHandledMessages(): iterable + { + foreach (TestMessageSubscriberConfigHolder::$handledMessages as $key => $subscribedMessage) { + yield $key => $subscribedMessage; + } } } -} -class TestMessageSubscriberConfigHolder -{ - public static $handledMessages = []; + class TestMessageSubscriberConfigHolder + { + public static $handledMessages = []; + } } class TestServiceSubscriber implements ServiceSubscriberInterface diff --git a/src/Symfony/Component/ErrorHandler/CHANGELOG.md b/src/Symfony/Component/ErrorHandler/CHANGELOG.md index d753991b3a2f9..6a5e8fb60e035 100644 --- a/src/Symfony/Component/ErrorHandler/CHANGELOG.md +++ b/src/Symfony/Component/ErrorHandler/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.4 +--- + + * `FlattenExceptionNormalizer` no longer implements `ContextAwareNormalizerInterface` + 6.3 --- diff --git a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md index b06620cd79acb..f54f943ac15de 100644 --- a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md +++ b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * The `in` and `not in` operators now use strict comparison + 6.3 --- diff --git a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php index 48331167bd275..d1a98a04fde31 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php @@ -30,8 +30,8 @@ class BinaryNode extends Node private const FUNCTIONS = [ '**' => 'pow', '..' => 'range', - 'in' => '\\'.self::class.'::inArray', - 'not in' => '!\\'.self::class.'::inArray', + 'in' => '\\in_array', + 'not in' => '!\\in_array', 'contains' => 'str_contains', 'starts with' => 'str_starts_with', 'ends with' => 'str_ends_with', @@ -71,9 +71,14 @@ public function compile(Compiler $compiler): void ->compile($this->nodes['left']) ->raw(', ') ->compile($this->nodes['right']) - ->raw(')') ; + if ('in' === $operator || 'not in' === $operator) { + $compiler->raw(', true'); + } + + $compiler->raw(')'); + return; } @@ -100,12 +105,11 @@ public function evaluate(array $functions, array $values): mixed if (isset(self::FUNCTIONS[$operator])) { $right = $this->nodes['right']->evaluate($functions, $values); - if ('not in' === $operator) { - return !self::inArray($left, $right); - } - $f = self::FUNCTIONS[$operator]; - - return $f($left, $right); + return match ($operator) { + 'in' => \in_array($left, $right, true), + 'not in' => !\in_array($left, $right, true), + default => self::FUNCTIONS[$operator]($left, $right), + }; } switch ($operator) { @@ -143,9 +147,9 @@ public function evaluate(array $functions, array $values): mixed case '<=': return $left <= $right; case 'not in': - return !self::inArray($left, $right); + return !\in_array($left, $right, true); case 'in': - return self::inArray($left, $right); + return \in_array($left, $right, true); case '+': return $left + $right; case '-': @@ -176,22 +180,6 @@ public function toArray(): array return ['(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')']; } - /** - * @internal to be replaced by an inline strict call to in_array() in version 7.0 - */ - public static function inArray($value, array $array): bool - { - if (false === $key = array_search($value, $array)) { - return false; - } - - if (!\in_array($value, $array, true)) { - trigger_deprecation('symfony/expression-language', '6.3', 'The "in" operator will use strict comparisons in Symfony 7.0. Loose match found with key "%s" for value %s. Normalize the array parameter so it only has the expected types or implement loose matching in your own expression function.', $key, json_encode($value)); - } - - return true; - } - private function evaluateMatches(string $regexp, ?string $str): int { set_error_handler(function ($t, $m) use ($regexp) { diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index bef2395e859c6..b2e072b5785bc 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -269,7 +269,7 @@ public function testOperatorCollisions() $expressionLanguage = new ExpressionLanguage(); $expression = 'foo.not in [bar]'; $compiled = $expressionLanguage->compile($expression, ['foo', 'bar']); - $this->assertSame('\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray($foo->not, [0 => $bar])', $compiled); + $this->assertSame('\in_array($foo->not, [0 => $bar], true)', $compiled); $result = $expressionLanguage->evaluate($expression, ['foo' => (object) ['not' => 'test'], 'bar' => 'test']); $this->assertTrue($result); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php index 610c6b0dd289b..bfbcd2dd5b75f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\ExpressionLanguage\Compiler; use Symfony\Component\ExpressionLanguage\Node\ArrayNode; use Symfony\Component\ExpressionLanguage\Node\BinaryNode; @@ -21,8 +20,6 @@ class BinaryNodeTest extends AbstractNodeTestCase { - use ExpectDeprecationTrait; - public static function getEvaluateData(): array { $array = new ArrayNode(); @@ -116,10 +113,10 @@ public static function getCompileData(): array ['pow(5, 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))], ['("a" . "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))], - ['\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("a", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('a'), $array)], - ['\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("c", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('c'), $array)], - ['!\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("c", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)], - ['!\Symfony\Component\ExpressionLanguage\Node\BinaryNode::inArray("a", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)], + ['\in_array("a", [0 => "a", 1 => "b"], true)', new BinaryNode('in', new ConstantNode('a'), $array)], + ['\in_array("c", [0 => "a", 1 => "b"], true)', new BinaryNode('in', new ConstantNode('c'), $array)], + ['!\in_array("c", [0 => "a", 1 => "b"], true)', new BinaryNode('not in', new ConstantNode('c'), $array)], + ['!\in_array("a", [0 => "a", 1 => "b"], true)', new BinaryNode('not in', new ConstantNode('a'), $array)], ['range(1, 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))], @@ -219,17 +216,17 @@ public function testCompileMatchesWithInvalidRegexpAsExpression() } /** - * @group legacy + * @testWith [1] + * ["true"] */ - public function testInOperatorStrictness() + public function testInOperatorStrictness(mixed $value) { $array = new ArrayNode(); - $array->addElement(new ConstantNode('a')); + $array->addElement(new ConstantNode('1')); $array->addElement(new ConstantNode(true)); - $node = new BinaryNode('in', new ConstantNode('b'), $array); + $node = new BinaryNode('in', new ConstantNode($value), $array); - $this->expectDeprecation('Since symfony/expression-language 6.3: The "in" operator will use strict comparisons in Symfony 7.0. Loose match found with key "1" for value "b". Normalize the array parameter so it only has the expected types or implement loose matching in your own expression function.'); - $this->assertTrue($node->evaluate([], [])); + $this->assertFalse($node->evaluate([], [])); } } diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index a516235ae9c32..b1652e8c8ee6f 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/cache": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php index 6dec01be224e6..8be25c0b8bd8a 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/Form.php @@ -26,11 +26,6 @@ class Form extends Constraint self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR', ]; - /** - * @deprecated since Symfony 6.1, use const ERROR_NAMES instead - */ - protected static $errorNames = self::ERROR_NAMES; - public function getTargets(): string|array { return self::CLASS_CONSTRAINT; diff --git a/src/Symfony/Component/HttpClient/CHANGELOG.md b/src/Symfony/Component/HttpClient/CHANGELOG.md index d24e0c2cc430b..88a5cc4b533b3 100644 --- a/src/Symfony/Component/HttpClient/CHANGELOG.md +++ b/src/Symfony/Component/HttpClient/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove implementing `Http\Message\RequestFactory` from `HttplugClient` + 6.4 --- diff --git a/src/Symfony/Component/HttpClient/HttplugClient.php b/src/Symfony/Component/HttpClient/HttplugClient.php index 9179b0ed4007c..392a6e1b0e4c1 100644 --- a/src/Symfony/Component/HttpClient/HttplugClient.php +++ b/src/Symfony/Component/HttpClient/HttplugClient.php @@ -32,7 +32,6 @@ use Psr\Http\Message\UriFactoryInterface; use Psr\Http\Message\UriInterface; use Symfony\Component\HttpClient\Internal\HttplugWaitLoop; -use Symfony\Component\HttpClient\Internal\LegacyHttplugInterface; use Symfony\Component\HttpClient\Response\HttplugPromise; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -57,7 +56,7 @@ * * @author Nicolas Grekas
*/
-final class HttplugClient implements ClientInterface, HttpAsyncClient, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface, LegacyHttplugInterface
+final class HttplugClient implements ClientInterface, HttpAsyncClient, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface
{
private HttpClientInterface $client;
private ResponseFactoryInterface $responseFactory;
@@ -150,14 +149,10 @@ public function wait(float $maxDuration = null, float $idleTimeout = null): int
}
/**
- * @param string $method
* @param UriInterface|string $uri
*/
- public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface
+ public function createRequest(string $method, $uri = ''): RequestInterface
{
- if (2 < \func_num_args()) {
- trigger_deprecation('symfony/http-client', '6.2', 'Passing more than 2 arguments to "%s()" is deprecated.', __METHOD__);
- }
if ($this->responseFactory instanceof RequestFactoryInterface) {
$request = $this->responseFactory->createRequest($method, $uri);
} elseif (class_exists(Psr17FactoryDiscovery::class)) {
@@ -168,44 +163,12 @@ public function createRequest($method, $uri, array $headers = [], $body = null,
throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
}
- $request = $request
- ->withProtocolVersion($protocolVersion)
- ->withBody($this->createStream($body ?? ''))
- ;
-
- foreach ($headers as $name => $value) {
- $request = $request->withAddedHeader($name, $value);
- }
-
return $request;
}
- /**
- * @param string $content
- */
- public function createStream($content = ''): StreamInterface
+ public function createStream(string $content = ''): StreamInterface
{
- if (!\is_string($content)) {
- trigger_deprecation('symfony/http-client', '6.2', 'Passing a "%s" to "%s()" is deprecated, use "createStreamFrom*()" instead.', get_debug_type($content), __METHOD__);
- }
-
- if ($content instanceof StreamInterface) {
- return $content;
- }
-
- if (\is_string($content ?? '')) {
- $stream = $this->streamFactory->createStream($content ?? '');
- } elseif (\is_resource($content)) {
- $stream = $this->streamFactory->createStreamFromResource($content);
- } else {
- throw new \InvalidArgumentException(sprintf('"%s()" expects string, resource or StreamInterface, "%s" given.', __METHOD__, get_debug_type($content)));
- }
-
- if ($stream->isSeekable()) {
- $stream->seek(0);
- }
-
- return $stream;
+ return $this->streamFactory->createStream($content);
}
public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface
@@ -218,25 +181,14 @@ public function createStreamFromResource($resource): StreamInterface
return $this->streamFactory->createStreamFromResource($resource);
}
- /**
- * @param string $uri
- */
- public function createUri($uri = ''): UriInterface
+ public function createUri(string $uri = ''): UriInterface
{
- if (!\is_string($uri)) {
- trigger_deprecation('symfony/http-client', '6.2', 'Passing a "%s" to "%s()" is deprecated, pass a string instead.', get_debug_type($uri), __METHOD__);
- }
-
- if ($uri instanceof UriInterface) {
- return $uri;
- }
-
if ($this->responseFactory instanceof UriFactoryInterface) {
return $this->responseFactory->createUri($uri);
}
if (class_exists(Psr17FactoryDiscovery::class)) {
- return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
+ return Psr17FactoryDiscovery::findUriFactory()->createUri($uri);
}
if (class_exists(Uri::class)) {
diff --git a/src/Symfony/Component/HttpClient/Internal/LegacyHttplugInterface.php b/src/Symfony/Component/HttpClient/Internal/LegacyHttplugInterface.php
deleted file mode 100644
index 44512cb512495..0000000000000
--- a/src/Symfony/Component/HttpClient/Internal/LegacyHttplugInterface.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\HttpClient\Internal;
-
-use Http\Client\HttpClient;
-use Http\Message\RequestFactory;
-use Http\Message\StreamFactory;
-use Http\Message\UriFactory;
-
-if (interface_exists(RequestFactory::class)) {
- /**
- * @internal
- *
- * @deprecated since Symfony 6.3
- */
- interface LegacyHttplugInterface extends HttpClient, RequestFactory, StreamFactory, UriFactory
- {
- }
-} else {
- /**
- * @internal
- *
- * @deprecated since Symfony 6.3
- */
- interface LegacyHttplugInterface extends HttpClient
- {
- }
-}
diff --git a/src/Symfony/Component/HttpClient/composer.json b/src/Symfony/Component/HttpClient/composer.json
index 31fa946a06a20..6a2e4bc15d11a 100644
--- a/src/Symfony/Component/HttpClient/composer.json
+++ b/src/Symfony/Component/HttpClient/composer.json
@@ -24,7 +24,6 @@
"require": {
"php": ">=8.2",
"psr/log": "^1|^2|^3",
- "symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-client-contracts": "^3",
"symfony/service-contracts": "^2.5|^3"
},
diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md
index 2fa31e8350eb0..3a15ecfd0d195 100644
--- a/src/Symfony/Component/HttpKernel/CHANGELOG.md
+++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md
@@ -5,10 +5,16 @@ CHANGELOG
---
* Add argument `$reflector` to `ArgumentResolverInterface::getArguments()` and `ArgumentMetadataFactoryInterface::createArgumentMetadata()`
+ * Remove `ArgumentValueResolverInterface`, use `ValueResolverInterface` instead
+ * Remove `StreamedResponseListener`
+ * Remove `AbstractSurrogate::$phpEscapeMap`
+ * Remove `HttpKernelInterface::MASTER_REQUEST`
+ * Remove `terminate_on_cache_hit` option from `HttpCache`
6.4
---
+ * `BundleInterface` no longer extends `ContainerAwareInterface`
* Add optional `$className` parameter to `ControllerEvent::getAttributes()`
6.3
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php
index 3b0f89509f65c..58131225a6386 100644
--- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php
@@ -18,7 +18,6 @@
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
-use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
@@ -37,7 +36,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
private ?ContainerInterface $namedResolvers;
/**
- * @param iterable
*/
-final class ServiceValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
+final class ServiceValueResolver implements ValueResolverInterface
{
private ContainerInterface $container;
@@ -32,32 +31,6 @@ public function __construct(ContainerInterface $container)
$this->container = $container;
}
- /**
- * @deprecated since Symfony 6.2, use resolve() instead
- */
- public function supports(Request $request, ArgumentMetadata $argument): bool
- {
- @trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
-
- $controller = $request->attributes->get('_controller');
-
- if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
- $controller = $controller[0].'::'.$controller[1];
- } elseif (!\is_string($controller) || '' === $controller) {
- return false;
- }
-
- if ('\\' === $controller[0]) {
- $controller = ltrim($controller, '\\');
- }
-
- if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) {
- $controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
- }
-
- return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
- }
-
public function resolve(Request $request, ArgumentMetadata $argument): array
{
$controller = $request->attributes->get('_controller');
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/SessionValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/SessionValueResolver.php
index c8e7575d5397a..30b7f1d7493c7 100644
--- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/SessionValueResolver.php
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/SessionValueResolver.php
@@ -13,7 +13,6 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
-use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
@@ -22,27 +21,8 @@
*
* @author Iltar van der Berg ', '', '', ''],
- ];
-
/**
* @param array $contentTypes An array of content-type that should be parsed for Surrogate information
* (default: text/html, text/xml, application/xhtml+xml, and application/xml)
diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
index eabacfec6272c..1698c3d21ff85 100644
--- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
+++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php
@@ -83,11 +83,6 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
* the cache can serve a stale response when an error is encountered (default: 60).
* This setting is overridden by the stale-if-error HTTP Cache-Control extension
* (see RFC 5861).
- *
- * * terminate_on_cache_hit Specifies if the kernel.terminate event should be dispatched even when the cache
- * was hit (default: true).
- * Unless your application needs to process events on cache hits, it is recommended
- * to set this to false to avoid having to bootstrap the Symfony framework on a cache hit.
*/
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = [])
{
@@ -109,7 +104,6 @@ public function __construct(HttpKernelInterface $kernel, StoreInterface $store,
'stale_if_error' => 60,
'trace_level' => 'none',
'trace_header' => 'X-Symfony-Cache',
- 'terminate_on_cache_hit' => true,
], $options);
if (!isset($options['trace_level'])) {
@@ -250,9 +244,7 @@ public function terminate(Request $request, Response $response)
// Do not call any listeners in case of a cache hit.
// This ensures identical behavior as if you had a separate
// reverse caching proxy such as Varnish and the like.
- if ($this->options['terminate_on_cache_hit']) {
- trigger_deprecation('symfony/http-kernel', '6.2', 'Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0.');
- } elseif (\in_array('fresh', $this->traces[$this->getTraceKey($request)] ?? [], true)) {
+ if (\in_array('fresh', $this->traces[$this->getTraceKey($request)] ?? [], true)) {
return;
}
diff --git a/src/Symfony/Component/HttpKernel/HttpKernelInterface.php b/src/Symfony/Component/HttpKernel/HttpKernelInterface.php
index f6c017a4c5e4f..e9415677f72f2 100644
--- a/src/Symfony/Component/HttpKernel/HttpKernelInterface.php
+++ b/src/Symfony/Component/HttpKernel/HttpKernelInterface.php
@@ -24,12 +24,6 @@ interface HttpKernelInterface
public const MAIN_REQUEST = 1;
public const SUB_REQUEST = 2;
- /**
- * @deprecated since symfony/http-kernel 5.3, use MAIN_REQUEST instead.
- * To ease the migration, this constant won't be removed until Symfony 7.0.
- */
- public const MASTER_REQUEST = self::MAIN_REQUEST;
-
/**
* Handles a Request to convert it to a Response.
*
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 76205bc0b8312..563b663262484 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -678,30 +678,14 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container
}
}
- $inlineFactories = false;
- if (isset($buildParameters['.container.dumper.inline_factories'])) {
- $inlineFactories = $buildParameters['.container.dumper.inline_factories'];
- } elseif ($container->hasParameter('container.dumper.inline_factories')) {
- trigger_deprecation('symfony/http-kernel', '6.3', 'Parameter "%s" is deprecated, use ".%1$s" instead.', 'container.dumper.inline_factories');
- $inlineFactories = $container->getParameter('container.dumper.inline_factories');
- }
-
- $inlineClassLoader = $this->debug;
- if (isset($buildParameters['.container.dumper.inline_class_loader'])) {
- $inlineClassLoader = $buildParameters['.container.dumper.inline_class_loader'];
- } elseif ($container->hasParameter('container.dumper.inline_class_loader')) {
- trigger_deprecation('symfony/http-kernel', '6.3', 'Parameter "%s" is deprecated, use ".%1$s" instead.', 'container.dumper.inline_class_loader');
- $inlineClassLoader = $container->getParameter('container.dumper.inline_class_loader');
- }
-
$content = $dumper->dump([
'class' => $class,
'base_class' => $baseClass,
'file' => $cache->getPath(),
'as_files' => true,
'debug' => $this->debug,
- 'inline_factories' => $inlineFactories,
- 'inline_class_loader' => $inlineClassLoader,
+ 'inline_factories' => $buildParameters['.container.dumper.inline_factories'] ?? false,
+ 'inline_class_loader' => $buildParameters['.container.dumper.inline_class_loader'] ?? $this->debug,
'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(),
'preload_classes' => array_map('get_class', $this->bundles),
]);
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/BackedEnumValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/BackedEnumValueResolverTest.php
index 9e2986273653a..5c6b5d065726f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/BackedEnumValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/BackedEnumValueResolverTest.php
@@ -21,20 +21,13 @@
class BackedEnumValueResolverTest extends TestCase
{
/**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- *
* @dataProvider provideTestSupportsData
*/
public function testSupports(Request $request, ArgumentMetadata $metadata, bool $expectedSupport)
{
$resolver = new BackedEnumValueResolver();
- if (!$expectedSupport) {
- $this->assertSame([], $resolver->resolve($request, $metadata));
- }
- self::assertSame($expectedSupport, $resolver->supports($request, $metadata));
+ $this->assertCount((int) $expectedSupport, $resolver->resolve($request, $metadata));
}
public static function provideTestSupportsData(): iterable
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/DateTimeValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/DateTimeValueResolverTest.php
index 6529ca9f7640b..636c811f98264 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/DateTimeValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/DateTimeValueResolverTest.php
@@ -50,26 +50,6 @@ public static function getClasses()
yield [FooDateTime::class];
}
- /**
- * @group legacy
- */
- public function testSupports()
- {
- $resolver = new DateTimeValueResolver();
-
- $argument = new ArgumentMetadata('dummy', \DateTime::class, false, false, null);
- $request = self::requestWithAttributes(['dummy' => 'now']);
- $this->assertTrue($resolver->supports($request, $argument));
-
- $argument = new ArgumentMetadata('dummy', FooDateTime::class, false, false, null);
- $request = self::requestWithAttributes(['dummy' => 'now']);
- $this->assertTrue($resolver->supports($request, $argument));
-
- $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null);
- $request = self::requestWithAttributes(['dummy' => 'now']);
- $this->assertFalse($resolver->supports($request, $argument));
- }
-
public function testUnsupportedArgument()
{
$resolver = new DateTimeValueResolver();
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php
index e28f8d513092c..3fc74a1d701f5 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php
@@ -20,23 +20,6 @@
class NotTaggedControllerValueResolverTest extends TestCase
{
- /**
- * @group legacy
- */
- public function testDoSupportWhenControllerDoNotExists()
- {
- $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([]));
- $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null);
- $request = $this->requestWithAttributes(['_controller' => 'my_controller']);
-
- $this->assertTrue($resolver->supports($request, $argument));
- }
-
- /**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- */
public function testDoNotSupportWhenControllerExists()
{
$resolver = new NotTaggedControllerValueResolver(new ServiceLocator([
@@ -47,21 +30,14 @@ public function testDoNotSupportWhenControllerExists()
$argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null);
$request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::method']);
$this->assertSame([], $resolver->resolve($request, $argument));
- $this->assertFalse($resolver->supports($request, $argument));
}
- /**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- */
public function testDoNotSupportEmptyController()
{
$resolver = new NotTaggedControllerValueResolver(new ServiceLocator([]));
$argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null);
$request = $this->requestWithAttributes(['_controller' => '']);
$this->assertSame([], $resolver->resolve($request, $argument));
- $this->assertFalse($resolver->supports($request, $argument));
}
public function testController()
@@ -104,11 +80,6 @@ public function testControllerNameIsAnArray()
$resolver->resolve($request, $argument);
}
- /**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- */
public function testInvokableController()
{
$this->expectException(RuntimeException::class);
@@ -116,7 +87,6 @@ public function testInvokableController()
$resolver = new NotTaggedControllerValueResolver(new ServiceLocator([]));
$argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null);
$request = $this->requestWithAttributes(['_controller' => 'App\Controller\Mine']);
- $this->assertTrue($resolver->supports($request, $argument));
$resolver->resolve($request, $argument);
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php
index 63a35b41246ae..df248047d0ea1 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php
@@ -22,11 +22,6 @@
class ServiceValueResolverTest extends TestCase
{
- /**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- */
public function testDoNotSupportWhenControllerDoNotExists()
{
$resolver = new ServiceValueResolver(new ServiceLocator([]));
@@ -34,7 +29,6 @@ public function testDoNotSupportWhenControllerDoNotExists()
$request = $this->requestWithAttributes(['_controller' => 'my_controller']);
$this->assertSame([], $resolver->resolve($request, $argument));
- $this->assertFalse($resolver->supports($request, $argument));
}
public function testExistingController()
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php
index bf5c42f8c2cfa..5ede33ccb3974 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php
@@ -14,28 +14,12 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
-use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Stopwatch\Stopwatch;
class TraceableValueResolverTest extends TestCase
{
- /**
- * @group legacy
- */
- public function testTimingsInSupports()
- {
- $stopwatch = new Stopwatch();
- $resolver = new TraceableValueResolver(new ResolverStub(), $stopwatch);
- $argument = new ArgumentMetadata('dummy', 'string', false, false, null);
- $request = new Request();
-
- $this->assertTrue($resolver->supports($request, $argument));
-
- $event = $stopwatch->getEvent(ResolverStub::class.'::supports');
- $this->assertCount(1, $event->getPeriods());
- }
-
public function testTimingsInResolve()
{
$stopwatch = new Stopwatch();
@@ -64,13 +48,8 @@ public function testTimingsInResolve()
}
}
-class ResolverStub implements ArgumentValueResolverInterface
+class ResolverStub implements ValueResolverInterface
{
- public function supports(Request $request, ArgumentMetadata $argument): bool
- {
- return true;
- }
-
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
yield 'first';
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UidValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UidValueResolverTest.php
index cc43417508e52..1da4d976a2083 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UidValueResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UidValueResolverTest.php
@@ -25,19 +25,11 @@
class UidValueResolverTest extends TestCase
{
/**
- * In Symfony 7, keep this test case but remove the call to supports().
- *
- * @group legacy
- *
* @dataProvider provideSupports
*/
public function testSupports(bool $expected, Request $request, ArgumentMetadata $argument)
{
- if (!$expected) {
- $this->assertSame([], (new UidValueResolver())->resolve($request, $argument));
- }
-
- $this->assertSame($expected, (new UidValueResolver())->supports($request, $argument));
+ $this->assertCount((int) $expected, (new UidValueResolver())->resolve($request, $argument));
}
public static function provideSupports()
@@ -50,10 +42,8 @@ public static function provideSupports()
'Argument type is not a class' => [false, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', 'string', false, false, null)],
'Argument type is not a subclass of AbstractUid' => [false, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', UlidFactory::class, false, false, null)],
'AbstractUid is not supported' => [false, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', AbstractUid::class, false, false, null)],
- 'Custom abstract subclass is supported but will fail in resolve' => [true, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', TestAbstractCustomUid::class, false, false, null)],
'Known subclass' => [true, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', UuidV4::class, false, false, null)],
'Format does not matter' => [true, new Request([], [], ['foo' => (string) $uuidV4]), new ArgumentMetadata('foo', Ulid::class, false, false, null)],
- 'Custom subclass' => [true, new Request([], [], ['foo' => '01FPND7BD15ZV07X5VGDXAJ8VD']), new ArgumentMetadata('foo', TestCustomUid::class, false, false, null)],
];
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php
index ef44f45bae078..34c0028d1511f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php
@@ -21,7 +21,6 @@
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
-use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use Symfony\Component\HttpKernel\Exception\ResolverNotFoundException;
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest;
@@ -176,25 +175,6 @@ public function testGetVariadicArgumentsWithoutArrayInRequest()
self::getResolver()->getArguments($request, $controller);
}
- /**
- * @group legacy
- */
- public function testGetArgumentWithoutArray()
- {
- $this->expectException(\InvalidArgumentException::class);
- $valueResolver = $this->createMock(ArgumentValueResolverInterface::class);
- $resolver = self::getResolver([$valueResolver]);
-
- $valueResolver->expects($this->any())->method('supports')->willReturn(true);
- $valueResolver->expects($this->any())->method('resolve')->willReturn([]);
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $request->attributes->set('bar', 'foo');
- $controller = $this->controllerWithFooAndDefaultBar(...);
- $resolver->getArguments($request, $controller);
- }
-
public function testIfExceptionIsThrownWhenMissingAnArgument()
{
$this->expectException(\RuntimeException::class);
diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php
index ae1ff9e2a54e8..b3e096d11e5d5 100644
--- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php
@@ -37,7 +37,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
// does not implement TerminableInterface
$kernel = new TestKernel();
- $httpCache = new HttpCache($kernel, $storeMock, null, ['terminate_on_cache_hit' => false]);
+ $httpCache = new HttpCache($kernel, $storeMock);
$httpCache->terminate(Request::create('/'), new Response());
$this->assertFalse($kernel->terminateCalled, 'terminate() is never called if the kernel class does not implement TerminableInterface');
@@ -51,7 +51,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
$kernelMock->expects($this->once())
->method('terminate');
- $kernel = new HttpCache($kernelMock, $storeMock, null, ['terminate_on_cache_hit' => false]);
+ $kernel = new HttpCache($kernelMock, $storeMock);
$kernel->terminate(Request::create('/'), new Response());
}
@@ -101,58 +101,6 @@ public function testDoesNotCallTerminateOnFreshResponse()
$this->assertCount(1, $terminateEvents);
}
- /**
- * @group legacy
- */
- public function testDoesCallTerminateOnFreshResponseIfConfigured()
- {
- $this->expectDeprecation('Since symfony/http-kernel 6.2: Setting "terminate_on_cache_hit" to "true" is deprecated and will be changed to "false" in Symfony 7.0.');
-
- $terminateEvents = [];
-
- $eventDispatcher = $this->createMock(EventDispatcher::class);
- $eventDispatcher
- ->expects($this->any())
- ->method('dispatch')
- ->with($this->callback(function ($event) use (&$terminateEvents) {
- if ($event instanceof TerminateEvent) {
- $terminateEvents[] = $event;
- }
-
- return true;
- }));
-
- $this->setNextResponse(
- 200,
- [
- 'ETag' => '1234',
- 'Cache-Control' => 'public, s-maxage=60',
- ],
- 'Hello World',
- null,
- $eventDispatcher
- );
- $this->cacheConfig['terminate_on_cache_hit'] = true;
-
- $this->request('GET', '/');
- $this->assertHttpKernelIsCalled();
- $this->assertEquals(200, $this->response->getStatusCode());
- $this->assertTraceContains('miss');
- $this->assertTraceContains('store');
- $this->cache->terminate($this->request, $this->response);
-
- sleep(2);
-
- $this->request('GET', '/');
- $this->assertHttpKernelIsNotCalled();
- $this->assertEquals(200, $this->response->getStatusCode());
- $this->assertTraceContains('fresh');
- $this->assertEquals(2, $this->response->headers->get('Age'));
- $this->cache->terminate($this->request, $this->response);
-
- $this->assertCount(2, $terminateEvents);
- }
-
public function testPassesOnNonGetHeadRequests()
{
$this->setNextResponse(200);
diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
index a5a240a6265ec..7fc0e49ef0c03 100644
--- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
@@ -51,7 +51,7 @@ public function testRequestStackIsNotBrokenWhenControllerThrowsAnExceptionAndCat
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }, $requestStack);
try {
- $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
+ $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true);
} catch (\Throwable $exception) {
}
@@ -64,7 +64,7 @@ public function testRequestStackIsNotBrokenWhenControllerThrowsAnExceptionAndCat
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }, $requestStack);
try {
- $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
+ $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, false);
} catch (\Throwable $exception) {
}
@@ -77,7 +77,7 @@ public function testRequestStackIsNotBrokenWhenControllerThrowsAnThrowable()
$kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \Error(); }, $requestStack);
try {
- $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
+ $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true);
} catch (\Throwable $exception) {
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
index 7ec9fa33133cb..92cb6fcbbf985 100644
--- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
@@ -13,14 +13,11 @@
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
-use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
-use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
@@ -39,8 +36,6 @@
class KernelTest extends TestCase
{
- use ExpectDeprecationTrait;
-
protected function tearDown(): void
{
try {
@@ -628,45 +623,6 @@ public function getContainerClass(): string
$this->assertMatchesRegularExpression('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*TestDebugContainer$/', $kernel->getContainerClass());
}
- /**
- * @group legacy
- */
- public function testKernelWithParameterDeprecation()
- {
- $kernel = new class('test', true) extends Kernel {
- public function __construct(string $env, bool $debug)
- {
- $this->container = new ContainerBuilder(new ParameterBag(['container.dumper.inline_factories' => true, 'container.dumper.inline_class_loader' => true]));
- parent::__construct($env, $debug);
- }
-
- public function registerBundles(): iterable
- {
- return [];
- }
-
- public function registerContainerConfiguration(LoaderInterface $loader): void
- {
- }
-
- public function boot(): void
- {
- $this->container->compile();
- parent::dumpContainer(new ConfigCache(tempnam(sys_get_temp_dir(), 'symfony-kernel-deprecated-parameter'), true), $this->container, Container::class, $this->getContainerBaseClass());
- }
-
- public function getContainerClass(): string
- {
- return parent::getContainerClass();
- }
- };
-
- $this->expectDeprecation('Since symfony/http-kernel 6.3: Parameter "container.dumper.inline_factories" is deprecated, use ".container.dumper.inline_factories" instead.');
- $this->expectDeprecation('Since symfony/http-kernel 6.3: Parameter "container.dumper.inline_class_loader" is deprecated, use ".container.dumper.inline_class_loader" instead.');
-
- $kernel->boot();
- }
-
/**
* Returns a mock for the BundleInterface.
*/
diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json
index 2c8475f00b28c..ccebe6d793e2f 100644
--- a/src/Symfony/Component/HttpKernel/composer.json
+++ b/src/Symfony/Component/HttpKernel/composer.json
@@ -17,7 +17,6 @@
],
"require": {
"php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3",
"symfony/error-handler": "^6.4|^7.0",
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md
index eb4df15c95e57..ad134e0fb20c0 100644
--- a/src/Symfony/Component/Ldap/CHANGELOG.md
+++ b/src/Symfony/Component/Ldap/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+7.0
+---
+
+ * Remove `{username}` parameter, use `{user_identifier}` instead
+
6.2
---
diff --git a/src/Symfony/Component/Ldap/Security/LdapBadge.php b/src/Symfony/Component/Ldap/Security/LdapBadge.php
index 2f8b1d7bd307d..f51ff4ee8cf6b 100644
--- a/src/Symfony/Component/Ldap/Security/LdapBadge.php
+++ b/src/Symfony/Component/Ldap/Security/LdapBadge.php
@@ -34,18 +34,10 @@ class LdapBadge implements BadgeInterface
public function __construct(string $ldapServiceId, string $dnString = '{user_identifier}', string $searchDn = '', string $searchPassword = '', string $queryString = null)
{
$this->ldapServiceId = $ldapServiceId;
- $dnString = str_replace('{username}', '{user_identifier}', $dnString, $replaceCount);
- if ($replaceCount > 0) {
- trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.');
- }
$this->dnString = $dnString;
$this->searchDn = $searchDn;
$this->searchPassword = $searchPassword;
- $queryString = str_replace('{username}', '{user_identifier}', $queryString ?? '', $replaceCount);
- if ($replaceCount > 0) {
- trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.');
- }
- $this->queryString = $queryString;
+ $this->queryString = $queryString ?? '';
}
public function getLdapServiceId(): string
diff --git a/src/Symfony/Component/Ldap/Security/LdapUser.php b/src/Symfony/Component/Ldap/Security/LdapUser.php
index abc293ac90132..1cc750677e495 100644
--- a/src/Symfony/Component/Ldap/Security/LdapUser.php
+++ b/src/Symfony/Component/Ldap/Security/LdapUser.php
@@ -62,14 +62,6 @@ public function getSalt(): ?string
return null;
}
- /**
- * @internal for compatibility with Symfony 5.4
- */
- public function getUsername(): string
- {
- return $this->getUserIdentifier();
- }
-
public function getUserIdentifier(): string
{
return $this->identifier;
diff --git a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php
index eef59c28308a3..4d9f2f6e44075 100644
--- a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php
+++ b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php
@@ -59,14 +59,6 @@ public function __construct(LdapInterface $ldap, string $baseDn, string $searchD
$this->extraFields = $extraFields;
}
- /**
- * @internal for compatibility with Symfony 5.4
- */
- public function loadUserByUsername(string $username): UserInterface
- {
- return $this->loadUserByIdentifier($username);
- }
-
public function loadUserByIdentifier(string $identifier): UserInterface
{
try {
@@ -76,11 +68,7 @@ public function loadUserByIdentifier(string $identifier): UserInterface
}
$identifier = $this->ldap->escape($identifier, '', LdapInterface::ESCAPE_FILTER);
- $query = str_replace('{username}', '{user_identifier}', $this->defaultSearch, $replaceCount);
- if ($replaceCount > 0) {
- trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.');
- }
- $query = str_replace('{user_identifier}', $identifier, $query);
+ $query = str_replace('{user_identifier}', $identifier, $this->defaultSearch);
$search = $this->ldap->query($this->baseDn, $query, ['filter' => 0 == \count($this->extraFields) ? '*' : $this->extraFields]);
$entries = $search->execute();
diff --git a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php
index 495072ca6816b..00731d03557cb 100644
--- a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php
+++ b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php
@@ -30,7 +30,6 @@
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
-use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
use Symfony\Contracts\Service\ServiceLocatorTrait;
@@ -127,49 +126,6 @@ public function testBindFailureShouldThrowAnException()
$listener->onCheckPassport($this->createEvent());
}
- /**
- * @group legacy
- *
- * @dataProvider queryForDnProvider
- */
- public function testLegacyQueryForDn(string $dnString, string $queryString)
- {
- $collection = new class([new Entry('')]) extends \ArrayObject implements CollectionInterface {
- public function toArray(): array
- {
- return $this->getArrayCopy();
- }
- };
-
- $query = $this->createMock(QueryInterface::class);
- $query->expects($this->once())->method('execute')->willReturn($collection);
-
- $this->ldap
- ->method('bind')
- ->willReturnCallback(function (...$args) {
- static $series = [
- ['elsa', 'test1234A$'],
- ['', 's3cr3t'],
- ];
-
- $this->assertSame(array_shift($series), $args);
- })
- ;
- $this->ldap->expects($this->any())->method('escape')->with('Wouter', '', LdapInterface::ESCAPE_FILTER)->willReturn('wouter');
- $this->ldap->expects($this->once())->method('query')->with('{user_identifier}', 'wouter_test')->willReturn($query);
-
- $listener = $this->createListener();
- $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', $dnString, 'elsa', 'test1234A$', $queryString)));
- }
-
- public static function queryForDnProvider(): iterable
- {
- yield ['{username}', '{username}_test'];
- yield ['{user_identifier}', '{username}_test'];
- yield ['{username}', '{user_identifier}_test'];
- yield ['{user_identifier}', '{user_identifier}_test'];
- }
-
public function testQueryForDn()
{
$collection = new class([new Entry('')]) extends \ArrayObject implements CollectionInterface {
@@ -257,13 +213,6 @@ public function authenticate(Request $request): Passport
{
}
- /**
- * @internal for compatibility with Symfony 5.4
- */
- public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
- {
- }
-
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
}
diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json
index 2867afa5457e3..5ed2995736e11 100644
--- a/src/Symfony/Component/Ldap/composer.json
+++ b/src/Symfony/Component/Ldap/composer.json
@@ -18,7 +18,6 @@
"require": {
"php": ">=8.2",
"ext-ldap": "*",
- "symfony/deprecation-contracts": "^2.5|^3",
"symfony/options-resolver": "^6.4|^7.0"
},
"require-dev": {
diff --git a/src/Symfony/Component/Lock/CHANGELOG.md b/src/Symfony/Component/Lock/CHANGELOG.md
index adbb2a20e1cb1..7fa12f38b8c1e 100644
--- a/src/Symfony/Component/Lock/CHANGELOG.md
+++ b/src/Symfony/Component/Lock/CHANGELOG.md
@@ -5,6 +5,7 @@ CHANGELOG
---
* Add parameter `$isSameDatabase` to `DoctrineDbalStore::configureSchema()`
+ * Remove the `gcProbablity` (notice the typo) option, use `gcProbability` instead
6.3
---
diff --git a/src/Symfony/Component/Lock/Store/MongoDbStore.php b/src/Symfony/Component/Lock/Store/MongoDbStore.php
index ada843883c0d3..20ef3bc4acd77 100644
--- a/src/Symfony/Component/Lock/Store/MongoDbStore.php
+++ b/src/Symfony/Component/Lock/Store/MongoDbStore.php
@@ -90,13 +90,6 @@ class MongoDbStore implements PersistingStoreInterface
*/
public function __construct(Collection|Client|string $mongo, array $options = [], float $initialTtl = 300.0)
{
- if (isset($options['gcProbablity'])) {
- trigger_deprecation('symfony/lock', '6.3', 'The "gcProbablity" option (notice the typo in its name) is deprecated in "%s"; use the "gcProbability" option instead.', __CLASS__);
-
- $options['gcProbability'] = $options['gcProbablity'];
- unset($options['gcProbablity']);
- }
-
$this->options = array_merge([
'gcProbability' => 0.001,
'database' => null,
diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Fixtures/long_receiver.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Fixtures/long_receiver.php
index 7a224a5c0b2c1..5aaca31e88cd0 100644
--- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Fixtures/long_receiver.php
+++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Fixtures/long_receiver.php
@@ -17,7 +17,7 @@
use Symfony\Component\Messenger\Bridge\Amqp\Transport\Connection;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EventListener\DispatchPcntlSignalListener;
-use Symfony\Component\Messenger\EventListener\StopWorkerOnSigtermSignalListener;
+use Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
use Symfony\Component\Messenger\Worker;
@@ -33,7 +33,7 @@
$connection = Connection::fromDsn(getenv('DSN'));
$receiver = new AmqpReceiver($connection, $serializer);
$eventDispatcher = new EventDispatcher();
-$eventDispatcher->addSubscriber(new StopWorkerOnSigtermSignalListener());
+$eventDispatcher->addSubscriber(new StopWorkerOnSignalsListener());
$eventDispatcher->addSubscriber(new DispatchPcntlSignalListener());
$worker = new Worker(['the_receiver' => $receiver], new class() implements MessageBusInterface {
diff --git a/src/Symfony/Component/Mime/CHANGELOG.md b/src/Symfony/Component/Mime/CHANGELOG.md
index 41eb14a4ec1cf..810018ba32327 100644
--- a/src/Symfony/Component/Mime/CHANGELOG.md
+++ b/src/Symfony/Component/Mime/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========
+7.0
+---
+
+ * Remove `Email::attachPart()`, use `Email::addPart()` instead
+ * Argument `$body` is now required (at least null) in `Message::setBody()`
+
6.3
---
diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php
index 7f3496d1fcb6a..67eea6c87713a 100644
--- a/src/Symfony/Component/Mime/Email.php
+++ b/src/Symfony/Component/Mime/Email.php
@@ -356,18 +356,6 @@ public function embedFromPath(string $path, string $name = null, string $content
return $this->addPart((new DataPart(new File($path), $name, $contentType))->asInline());
}
- /**
- * @return $this
- *
- * @deprecated since Symfony 6.2, use addPart() instead
- */
- public function attachPart(DataPart $part): static
- {
- @trigger_deprecation('symfony/mime', '6.2', 'The "%s()" method is deprecated, use "addPart()" instead.', __METHOD__);
-
- return $this->addPart($part);
- }
-
/**
* @return $this
*/
diff --git a/src/Symfony/Component/Mime/Message.php b/src/Symfony/Component/Mime/Message.php
index e636c2e8e5546..6b78316606d6c 100644
--- a/src/Symfony/Component/Mime/Message.php
+++ b/src/Symfony/Component/Mime/Message.php
@@ -42,11 +42,8 @@ public function __clone()
/**
* @return $this
*/
- public function setBody(AbstractPart $body = null): static
+ public function setBody(?AbstractPart $body): static
{
- if (1 > \func_num_args()) {
- trigger_deprecation('symfony/mime', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
- }
$this->body = $body;
return $this;
diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php
index 0ec6b1cfb972b..8acc31bca2c8e 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php
+++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php
@@ -40,12 +40,8 @@ public function getToken(): ?TokenInterface
/**
* @return void
*/
- public function setToken(TokenInterface $token = null)
+ public function setToken(?TokenInterface $token)
{
- if (1 > \func_num_args()) {
- trigger_deprecation('symfony/security-core', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
- }
-
if ($token) {
// ensure any initializer is called
$this->getToken();
diff --git a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php
index 3827f8b91ee38..c748697c494f9 100644
--- a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php
+++ b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php
@@ -24,17 +24,10 @@
*/
class AuthorizationChecker implements AuthorizationCheckerInterface
{
- private TokenStorageInterface $tokenStorage;
- private AccessDecisionManagerInterface $accessDecisionManager;
-
- public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, bool $exceptionOnNoToken = false)
- {
- if ($exceptionOnNoToken) {
- throw new \LogicException(sprintf('Argument $exceptionOnNoToken of "%s()" must be set to "false".', __METHOD__));
- }
-
- $this->tokenStorage = $tokenStorage;
- $this->accessDecisionManager = $accessDecisionManager;
+ public function __construct(
+ private TokenStorageInterface $tokenStorage,
+ private AccessDecisionManagerInterface $accessDecisionManager,
+ ) {
}
final public function isGranted(mixed $attribute, mixed $subject = null): bool
diff --git a/src/Symfony/Component/Security/Core/Security.php b/src/Symfony/Component/Security/Core/Security.php
index 97f1c8ce1f568..bb2576a7ab9dc 100644
--- a/src/Symfony/Component/Security/Core/Security.php
+++ b/src/Symfony/Component/Security/Core/Security.php
@@ -24,19 +24,8 @@
*/
class Security implements AuthorizationCheckerInterface
{
- /**
- * @deprecated since Symfony 6.2, use \Symfony\Bundle\SecurityBundle\Security::ACCESS_DENIED_ERROR instead
- */
public const ACCESS_DENIED_ERROR = '_security.403_error';
-
- /**
- * @deprecated since Symfony 6.2, use \Symfony\Bundle\SecurityBundle\Security::AUTHENTICATION_ERROR instead
- */
public const AUTHENTICATION_ERROR = '_security.last_error';
-
- /**
- * @deprecated since Symfony 6.2, use \Symfony\Bundle\SecurityBundle\Security::LAST_USERNAME instead
- */
public const LAST_USERNAME = '_security.last_username';
/**
diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php
index 5b260b50a18c7..26d20ae4a92fa 100644
--- a/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php
@@ -12,31 +12,12 @@
namespace Symfony\Component\Security\Core\Tests\Authentication\Token\Storage;
use PHPUnit\Framework\TestCase;
-use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\User\InMemoryUser;
class TokenStorageTest extends TestCase
{
- use ExpectDeprecationTrait;
-
- /**
- * @group legacy
- */
- public function testGetSetTokenLegacy()
- {
- $tokenStorage = new TokenStorage();
- $token = new UsernamePasswordToken(new InMemoryUser('username', 'password'), 'provider');
- $tokenStorage->setToken($token);
- $this->assertSame($token, $tokenStorage->getToken());
-
- $this->expectDeprecation('Since symfony/security-core 6.2: Calling "Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage::setToken()" without any arguments is deprecated, pass null explicitly instead.');
-
- $tokenStorage->setToken();
- $this->assertNull($tokenStorage->getToken());
- }
-
public function testGetSetToken()
{
$tokenStorage = new TokenStorage();
diff --git a/src/Symfony/Component/Security/Core/Tests/SecurityTest.php b/src/Symfony/Component/Security/Core/Tests/SecurityTest.php
deleted file mode 100644
index 00436895df05d..0000000000000
--- a/src/Symfony/Component/Security/Core/Tests/SecurityTest.php
+++ /dev/null
@@ -1,98 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Security\Core\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Psr\Container\ContainerInterface;
-use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
-use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
-use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
-use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
-use Symfony\Component\Security\Core\Security;
-use Symfony\Component\Security\Core\User\InMemoryUser;
-
-/**
- * @group legacy
- */
-class SecurityTest extends TestCase
-{
- public function testGetToken()
- {
- $token = new UsernamePasswordToken(new InMemoryUser('foo', 'bar'), 'provider');
- $tokenStorage = $this->createMock(TokenStorageInterface::class);
-
- $tokenStorage->expects($this->once())
- ->method('getToken')
- ->willReturn($token);
-
- $container = $this->createContainer('security.token_storage', $tokenStorage);
-
- $security = new Security($container);
- $this->assertSame($token, $security->getToken());
- }
-
- /**
- * @dataProvider getUserTests
- */
- public function testGetUser($userInToken, $expectedUser)
- {
- $token = $this->createMock(TokenInterface::class);
- $token->expects($this->any())
- ->method('getUser')
- ->willReturn($userInToken);
- $tokenStorage = $this->createMock(TokenStorageInterface::class);
-
- $tokenStorage->expects($this->once())
- ->method('getToken')
- ->willReturn($token);
-
- $container = $this->createContainer('security.token_storage', $tokenStorage);
-
- $security = new Security($container);
- $this->assertSame($expectedUser, $security->getUser());
- }
-
- public static function getUserTests()
- {
- yield [null, null];
-
- $user = new InMemoryUser('nice_user', 'foo');
- yield [$user, $user];
- }
-
- public function testIsGranted()
- {
- $authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
-
- $authorizationChecker->expects($this->once())
- ->method('isGranted')
- ->with('SOME_ATTRIBUTE', 'SOME_SUBJECT')
- ->willReturn(true);
-
- $container = $this->createContainer('security.authorization_checker', $authorizationChecker);
-
- $security = new Security($container);
- $this->assertTrue($security->isGranted('SOME_ATTRIBUTE', 'SOME_SUBJECT'));
- }
-
- private function createContainer($serviceId, $serviceObject)
- {
- $container = $this->createMock(ContainerInterface::class);
-
- $container->expects($this->atLeastOnce())
- ->method('get')
- ->with($serviceId)
- ->willReturn($serviceObject);
-
- return $container;
- }
-}
diff --git a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php
index 47ebbc1a8e339..045697fb76eba 100644
--- a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php
+++ b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php
@@ -46,14 +46,6 @@ public function getProviders(): array
return $this->providers;
}
- /**
- * @internal for compatibility with Symfony 5.4
- */
- public function loadUserByUsername(string $username): UserInterface
- {
- return $this->loadUserByIdentifier($username);
- }
-
public function loadUserByIdentifier(string $identifier): UserInterface
{
foreach ($this->providers as $provider) {
diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php
index e0aef90a14147..13441bc758511 100644
--- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php
+++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php
@@ -51,13 +51,11 @@ public function __construct(array $users = [])
* Adds a new User to the provider.
*
* @return void
- *
- * @throws \LogicException
*/
public function createUser(UserInterface $user)
{
if (!$user instanceof InMemoryUser) {
- trigger_deprecation('symfony/security-core', '6.3', 'Passing users that are not instance of "%s" to "%s" is deprecated, "%s" given.', InMemoryUser::class, __METHOD__, get_debug_type($user));
+ throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user)));
}
$userIdentifier = strtolower($user->getUserIdentifier());
@@ -93,13 +91,11 @@ public function supportsClass(string $class): bool
}
/**
- * Returns the user by given username.
- *
- * @return InMemoryUser change return type on 7.0
+ * Returns the user by given user.
*
* @throws UserNotFoundException if user whose given username does not exist
*/
- private function getUser(string $username): UserInterface
+ private function getUser(string $username): InMemoryUser
{
if (!isset($this->users[strtolower($username)])) {
$ex = new UserNotFoundException(sprintf('Username "%s" does not exist.', $username));
diff --git a/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php
index 3eaafc7aebb93..990903c8ae8b6 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php
@@ -148,8 +148,8 @@ private function getCredentials(\stdClass $data): array
try {
$credentials['username'] = $this->propertyAccessor->getValue($data, $this->options['username_path']);
- if (!\is_string($credentials['username'])) {
- throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['username_path']));
+ if (!\is_string($credentials['username']) || '' === $credentials['username']) {
+ throw new BadRequestHttpException(sprintf('The key "%s" must be a non-empty string.', $this->options['username_path']));
}
} catch (AccessException $e) {
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['username_path']), $e);
@@ -159,17 +159,13 @@ private function getCredentials(\stdClass $data): array
$credentials['password'] = $this->propertyAccessor->getValue($data, $this->options['password_path']);
$this->propertyAccessor->setValue($data, $this->options['password_path'], null);
- if (!\is_string($credentials['password'])) {
- throw new BadRequestHttpException(sprintf('The key "%s" must be a string.', $this->options['password_path']));
+ if (!\is_string($credentials['password']) || '' === $credentials['password']) {
+ throw new BadRequestHttpException(sprintf('The key "%s" must be a non-empty string.', $this->options['password_path']));
}
} catch (AccessException $e) {
throw new BadRequestHttpException(sprintf('The key "%s" must be provided.', $this->options['password_path']), $e);
}
- if ('' === $credentials['username'] || '' === $credentials['password']) {
- trigger_deprecation('symfony/security', '6.2', 'Passing an empty string as username or password parameter is deprecated.');
- }
-
return $credentials;
}
}
diff --git a/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php b/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php
index 5421301ef2fbe..5a9c08d61071c 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/Token/PostAuthenticationToken.php
@@ -33,12 +33,6 @@ public function __construct(UserInterface $user, string $firewallName, array $ro
$this->setUser($user);
$this->firewallName = $firewallName;
-
- // required for compatibility with Symfony 5.4
- if (method_exists($this, 'setAuthenticated')) {
- // this token is meant to be used after authentication success, so it is always authenticated
- $this->setAuthenticated(true, false);
- }
}
/**
diff --git a/src/Symfony/Component/Security/Http/CHANGELOG.md b/src/Symfony/Component/Security/Http/CHANGELOG.md
index db025d494a101..99eae79465498 100644
--- a/src/Symfony/Component/Security/Http/CHANGELOG.md
+++ b/src/Symfony/Component/Security/Http/CHANGELOG.md
@@ -7,6 +7,11 @@ CHANGELOG
* Add argument `$badgeFqcn` to `Passport::addBadge()`
* Add argument `$lifetime` to `LoginLinkHandlerInterface::createLoginLink()`
+6.4
+---
+
+ * `UserValueResolver` no longer implements `ArgumentValueResolverInterface`
+
6.3
---
diff --git a/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php b/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php
index 520515e465745..e35c2a73dc0a5 100644
--- a/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php
+++ b/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\Security\Http\Controller;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@@ -25,7 +24,7 @@
*
* @author Iltar van der Berg