diff --git a/.github/expected-missing-return-types.diff b/.github/expected-missing-return-types.diff index 2545ad099f7a1..e0c0131a2631a 100644 --- a/.github/expected-missing-return-types.diff +++ b/.github/expected-missing-return-types.diff @@ -7,17 +7,6 @@ git checkout src/Symfony/Contracts/Service/ResetInterface.php (echo "$head" && echo && git diff -U2 src/) > .github/expected-missing-return-types.diff git checkout composer.json src/ -diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php -index 4b79ab7363..b72ff1d63b 100644 ---- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php -+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php -@@ -2902,5 +2902,5 @@ class FrameworkExtension extends Extension - * @return void - */ -- public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig) -+ public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig): void - { - trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s()" method is deprecated.', __METHOD__); diff --git a/src/Symfony/Component/Asset/Packages.php b/src/Symfony/Component/Asset/Packages.php index cffea43c49..0645fbd756 100644 --- a/src/Symfony/Component/Asset/Packages.php @@ -607,10 +596,10 @@ index bb40307e17..998fb85b27 100644 + public function setBuilder(NodeBuilder $builder): void; } diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php -index 7cda0bc7d8..b2311826f4 100644 +index 49b73c8045..51b0719782 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php -@@ -111,5 +111,5 @@ class NodeBuilder implements NodeParentInterface +@@ -108,5 +108,5 @@ class NodeBuilder implements NodeParentInterface * @return NodeDefinition&ParentNodeDefinitionInterface */ - public function end() @@ -2935,7 +2924,7 @@ index 2d6542660b..20287f9286 100644 { $this->extensionConfig = []; diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php -index 3ea2228b94..f1d7078383 100644 +index 2b9eeb84cc..29905ed51b 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -83,5 +83,5 @@ class Container implements ContainerInterface, ResetInterface @@ -3811,7 +3800,7 @@ index f1b982315c..ed8ad1fab4 100644 { } diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php -index c86f438d41..3bfb39db57 100644 +index 47fa9ce841..67d01c3c5b 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -52,5 +52,5 @@ class RegisterListenersPass implements CompilerPassInterface @@ -4371,7 +4360,7 @@ index 422f28bf33..b1d608fd4d 100644 { } diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php -index 20a30968d4..dbded1d7f3 100644 +index 2c8c12ce23..8c484d7275 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -57,5 +57,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface @@ -4447,151 +4436,151 @@ index 20a30968d4..dbded1d7f3 100644 @@ -221,5 +221,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ -- public function setDataMapper(DataMapperInterface $dataMapper = null): static -+ public function setDataMapper(DataMapperInterface $dataMapper = null): never +- public function setDataMapper(?DataMapperInterface $dataMapper): static ++ public function setDataMapper(?DataMapperInterface $dataMapper): never { - if (1 > \func_num_args()) { -@@ -249,5 +249,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface + throw new BadMethodCallException('Buttons do not support data mappers.'); +@@ -245,5 +245,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setEmptyData(mixed $emptyData): static + public function setEmptyData(mixed $emptyData): never { throw new BadMethodCallException('Buttons do not support empty data.'); -@@ -261,5 +261,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -257,5 +257,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setErrorBubbling(bool $errorBubbling): static + public function setErrorBubbling(bool $errorBubbling): never { throw new BadMethodCallException('Buttons do not support error bubbling.'); -@@ -273,5 +273,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -269,5 +269,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setRequired(bool $required): static + public function setRequired(bool $required): never { throw new BadMethodCallException('Buttons cannot be required.'); -@@ -285,5 +285,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -281,5 +281,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setPropertyPath(string|PropertyPathInterface|null $propertyPath): static + public function setPropertyPath(string|PropertyPathInterface|null $propertyPath): never { throw new BadMethodCallException('Buttons do not support property paths.'); -@@ -297,5 +297,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -293,5 +293,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setMapped(bool $mapped): static + public function setMapped(bool $mapped): never { throw new BadMethodCallException('Buttons do not support data mapping.'); -@@ -309,5 +309,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -305,5 +305,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setByReference(bool $byReference): static + public function setByReference(bool $byReference): never { throw new BadMethodCallException('Buttons do not support data mapping.'); -@@ -321,5 +321,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -317,5 +317,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setCompound(bool $compound): static + public function setCompound(bool $compound): never { throw new BadMethodCallException('Buttons cannot be compound.'); -@@ -345,5 +345,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -341,5 +341,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setData(mixed $data): static + public function setData(mixed $data): never { throw new BadMethodCallException('Buttons do not support data.'); -@@ -357,5 +357,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -353,5 +353,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setDataLocked(bool $locked): static + public function setDataLocked(bool $locked): never { throw new BadMethodCallException('Buttons do not support data locking.'); -@@ -369,5 +369,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -365,5 +365,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setFormFactory(FormFactoryInterface $formFactory) + public function setFormFactory(FormFactoryInterface $formFactory): never { throw new BadMethodCallException('Buttons do not support form factories.'); -@@ -381,5 +381,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -377,5 +377,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setAction(string $action): static + public function setAction(string $action): never { throw new BadMethodCallException('Buttons do not support actions.'); -@@ -393,5 +393,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -389,5 +389,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setMethod(string $method): static + public function setMethod(string $method): never { throw new BadMethodCallException('Buttons do not support methods.'); -@@ -405,5 +405,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -401,5 +401,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setRequestHandler(RequestHandlerInterface $requestHandler): static + public function setRequestHandler(RequestHandlerInterface $requestHandler): never { throw new BadMethodCallException('Buttons do not support request handlers.'); -@@ -433,5 +433,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -429,5 +429,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setInheritData(bool $inheritData): static + public function setInheritData(bool $inheritData): never { throw new BadMethodCallException('Buttons do not support data inheritance.'); -@@ -457,5 +457,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -453,5 +453,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function setIsEmptyCallback(?callable $isEmptyCallback): static + public function setIsEmptyCallback(?callable $isEmptyCallback): never { throw new BadMethodCallException('Buttons do not support "is empty" callback.'); -@@ -469,5 +469,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -465,5 +465,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function getEventDispatcher(): EventDispatcherInterface + public function getEventDispatcher(): never { throw new BadMethodCallException('Buttons do not support event dispatching.'); -@@ -628,5 +628,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -624,5 +624,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @return never */ - public function getFormFactory(): FormFactoryInterface + public function getFormFactory(): never { throw new BadMethodCallException('Buttons do not support adding children.'); -@@ -640,5 +640,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -636,5 +636,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function getAction(): string + public function getAction(): never { throw new BadMethodCallException('Buttons do not support actions.'); -@@ -652,5 +652,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -648,5 +648,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function getMethod(): string + public function getMethod(): never { throw new BadMethodCallException('Buttons do not support methods.'); -@@ -664,5 +664,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -660,5 +660,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function getRequestHandler(): RequestHandlerInterface + public function getRequestHandler(): never { throw new BadMethodCallException('Buttons do not support request handlers.'); -@@ -716,5 +716,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +@@ -712,5 +712,5 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @throws BadMethodCallException */ - public function getIsEmptyCallback(): ?callable @@ -4955,7 +4944,7 @@ index 655ef6682f..0e525d09f6 100644 { $compound = static fn (Options $options) => 'single_text' !== $options['widget']; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php -index 9ec4c9cca4..28a33fb6d6 100644 +index 73ae5708c9..90815a20cf 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -53,5 +53,5 @@ class DateTimeType extends AbstractType @@ -4965,14 +4954,14 @@ index 9ec4c9cca4..28a33fb6d6 100644 + public function buildForm(FormBuilderInterface $builder, array $options): void { $parts = ['year', 'month', 'day', 'hour']; -@@ -217,5 +217,5 @@ class DateTimeType extends AbstractType +@@ -216,5 +216,5 @@ class DateTimeType extends AbstractType * @return void */ - public function buildView(FormView $view, FormInterface $form, array $options) + public function buildView(FormView $view, FormInterface $form, array $options): void { $view->vars['widget'] = $options['widget']; -@@ -245,5 +245,5 @@ class DateTimeType extends AbstractType +@@ -244,5 +244,5 @@ class DateTimeType extends AbstractType * @return void */ - public function configureOptions(OptionsResolver $resolver) @@ -4980,7 +4969,7 @@ index 9ec4c9cca4..28a33fb6d6 100644 { $compound = static fn (Options $options) => 'single_text' !== $options['widget']; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php -index 480afc315f..e9f6364b07 100644 +index d204a914bd..7ae99cbfa6 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -49,5 +49,5 @@ class DateType extends AbstractType @@ -4990,14 +4979,14 @@ index 480afc315f..e9f6364b07 100644 + public function buildForm(FormBuilderInterface $builder, array $options): void { $dateFormat = \is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; -@@ -201,5 +201,5 @@ class DateType extends AbstractType +@@ -200,5 +200,5 @@ class DateType extends AbstractType * @return void */ - public function finishView(FormView $view, FormInterface $form, array $options) + public function finishView(FormView $view, FormInterface $form, array $options): void { $view->vars['widget'] = $options['widget']; -@@ -241,5 +241,5 @@ class DateType extends AbstractType +@@ -240,5 +240,5 @@ class DateType extends AbstractType * @return void */ - public function configureOptions(OptionsResolver $resolver) @@ -5347,7 +5336,7 @@ index 40e7580d80..18c58e30c0 100644 { $view->vars['pattern'] = null; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php -index 623259f17a..1b7bd9a33f 100644 +index 7788290d7a..fff39fbc5d 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -38,5 +38,5 @@ class TimeType extends AbstractType @@ -5357,14 +5346,14 @@ index 623259f17a..1b7bd9a33f 100644 + public function buildForm(FormBuilderInterface $builder, array $options): void { $parts = ['hour']; -@@ -229,5 +229,5 @@ class TimeType extends AbstractType +@@ -228,5 +228,5 @@ class TimeType extends AbstractType * @return void */ - public function buildView(FormView $view, FormInterface $form, array $options) + public function buildView(FormView $view, FormInterface $form, array $options): void { $view->vars = array_replace($view->vars, [ -@@ -260,5 +260,5 @@ class TimeType extends AbstractType +@@ -259,5 +259,5 @@ class TimeType extends AbstractType * @return void */ - public function configureOptions(OptionsResolver $resolver) @@ -5822,10 +5811,10 @@ index ed363a7b15..967d95cc27 100644 { return $this->path->mapsForm($this->key()); diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php -index 9fed3d1a0a..5cd4eb5f16 100644 +index 29e643680e..ef10087b80 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php -@@ -537,5 +537,5 @@ class FormConfigBuilder implements FormConfigBuilderInterface +@@ -534,5 +534,5 @@ class FormConfigBuilder implements FormConfigBuilderInterface * @return $this */ - public function setFormFactory(FormFactoryInterface $formFactory) @@ -6757,7 +6746,7 @@ index ebe4b748ad..059a6b5ac8 100644 { $this->name = $name; diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php -index d30b56d691..0f002902bd 100644 +index 65f06c69e4..8f51fbbacd 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -72,5 +72,5 @@ class MockArraySessionStorage implements SessionStorageInterface @@ -6805,11 +6794,11 @@ index d30b56d691..0f002902bd 100644 @@ -193,5 +193,5 @@ class MockArraySessionStorage implements SessionStorageInterface * @return void */ -- public function setMetadataBag(MetadataBag $bag = null) -+ public function setMetadataBag(MetadataBag $bag = null): void +- public function setMetadataBag(?MetadataBag $bag) ++ public function setMetadataBag(?MetadataBag $bag): void { - if (1 > \func_num_args()) { -@@ -223,5 +223,5 @@ class MockArraySessionStorage implements SessionStorageInterface + $this->metadataBag = $bag ?? new MetadataBag(); +@@ -220,5 +220,5 @@ class MockArraySessionStorage implements SessionStorageInterface * @return void */ - protected function loadSession() @@ -6828,7 +6817,7 @@ index 95f69f2e13..971b890f0f 100644 { if (!$this->started) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php -index 7c6b6f9296..0b63abb810 100644 +index e2e6f9f1f9..5c08f6f102 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -187,5 +187,5 @@ class NativeSessionStorage implements SessionStorageInterface @@ -6869,25 +6858,25 @@ index 7c6b6f9296..0b63abb810 100644 @@ -318,5 +318,5 @@ class NativeSessionStorage implements SessionStorageInterface * @return void */ -- public function setMetadataBag(MetadataBag $metaBag = null) -+ public function setMetadataBag(MetadataBag $metaBag = null): void +- public function setMetadataBag(?MetadataBag $metaBag) ++ public function setMetadataBag(?MetadataBag $metaBag): void { - if (1 > \func_num_args()) { -@@ -351,5 +351,5 @@ class NativeSessionStorage implements SessionStorageInterface + $this->metadataBag = $metaBag ?? new MetadataBag(); +@@ -348,5 +348,5 @@ class NativeSessionStorage implements SessionStorageInterface * @return void */ - public function setOptions(array $options) + public function setOptions(array $options): void { if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { -@@ -397,5 +397,5 @@ class NativeSessionStorage implements SessionStorageInterface +@@ -394,5 +394,5 @@ class NativeSessionStorage implements SessionStorageInterface * @throws \InvalidArgumentException */ -- public function setSaveHandler(AbstractProxy|\SessionHandlerInterface $saveHandler = null) -+ public function setSaveHandler(AbstractProxy|\SessionHandlerInterface $saveHandler = null): void +- public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler) ++ public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler): void { - if (1 > \func_num_args()) { -@@ -430,5 +430,5 @@ class NativeSessionStorage implements SessionStorageInterface + // Wrap $saveHandler in proxy and prevent double wrapping of proxy +@@ -423,5 +423,5 @@ class NativeSessionStorage implements SessionStorageInterface * @return void */ - protected function loadSession(array &$session = null) @@ -7487,17 +7476,17 @@ index 47027233a7..2be5cfc7de 100644 { $this->fragmentPath = $path; diff --git a/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php b/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php -index 95518bed2b..2f7d5ee3b5 100644 +index e3f4d9552d..723e2c2f9c 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/AbstractSurrogate.php -@@ -63,5 +63,5 @@ abstract class AbstractSurrogate implements SurrogateInterface +@@ -55,5 +55,5 @@ abstract class AbstractSurrogate implements SurrogateInterface * @return void */ - public function addSurrogateCapability(Request $request) + public function addSurrogateCapability(Request $request): void { $current = $request->headers->get('Surrogate-Capability'); -@@ -112,5 +112,5 @@ abstract class AbstractSurrogate implements SurrogateInterface +@@ -104,5 +104,5 @@ abstract class AbstractSurrogate implements SurrogateInterface * @return void */ - protected function removeFromControl(Response $response) @@ -7516,31 +7505,31 @@ index 5db840a802..c16398a8ea 100644 { if (str_contains($response->getContent(), 'surrogate?->addSurrogateCapability($request); -@@ -600,5 +600,5 @@ class HttpCache implements HttpKernelInterface, TerminableInterface +@@ -592,5 +592,5 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * @throws \Exception */ - protected function store(Request $request, Response $response) + protected function store(Request $request, Response $response): void { try { -@@ -678,5 +678,5 @@ class HttpCache implements HttpKernelInterface, TerminableInterface +@@ -670,5 +670,5 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * @return void */ - protected function processResponseBody(Request $request, Response $response) @@ -7697,7 +7686,7 @@ index 0f3630e7fe..ddf77b8a19 100644 { return <<<'EOF' diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php -index 76205bc0b8..f4240cdd1b 100644 +index 563b663262..6118d09871 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -107,5 +107,5 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl @@ -8534,31 +8523,31 @@ index 88233655f9..abfb1fe7a6 100644 { $token = $this->getUniqueToken($key); diff --git a/src/Symfony/Component/Lock/Store/MongoDbStore.php b/src/Symfony/Component/Lock/Store/MongoDbStore.php -index ada843883c..afebb3f3d8 100644 +index 20ef3bc4ac..1417a5d84c 100644 --- a/src/Symfony/Component/Lock/Store/MongoDbStore.php +++ b/src/Symfony/Component/Lock/Store/MongoDbStore.php -@@ -194,5 +194,5 @@ class MongoDbStore implements PersistingStoreInterface +@@ -187,5 +187,5 @@ class MongoDbStore implements PersistingStoreInterface * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function createTtlIndex(int $expireAfterSeconds = 0) + public function createTtlIndex(int $expireAfterSeconds = 0): void { $this->getCollection()->createIndex( -@@ -211,5 +211,5 @@ class MongoDbStore implements PersistingStoreInterface +@@ -204,5 +204,5 @@ class MongoDbStore implements PersistingStoreInterface * @throws LockExpiredException when save is called on an expired lock */ - public function save(Key $key) + public function save(Key $key): void { $key->reduceLifetime($this->initialTtl); -@@ -237,5 +237,5 @@ class MongoDbStore implements PersistingStoreInterface +@@ -230,5 +230,5 @@ class MongoDbStore implements PersistingStoreInterface * @throws LockExpiredException */ - public function putOffExpiration(Key $key, float $ttl) + public function putOffExpiration(Key $key, float $ttl): void { $key->reduceLifetime($ttl); -@@ -256,5 +256,5 @@ class MongoDbStore implements PersistingStoreInterface +@@ -249,5 +249,5 @@ class MongoDbStore implements PersistingStoreInterface * @return void */ - public function delete(Key $key) @@ -8799,10 +8788,10 @@ index 3b6d6b8a39..98bc75ecd7 100644 { $this diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php -index 86fa255015..08cbde055f 100644 +index f6f26d6946..5a98a6a0dc 100644 --- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php +++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php -@@ -37,5 +37,5 @@ class MessengerPass implements CompilerPassInterface +@@ -34,5 +34,5 @@ class MessengerPass implements CompilerPassInterface * @return void */ - public function process(ContainerBuilder $container) @@ -8898,10 +8887,10 @@ index 70fa786331..f27afd0f01 100644 { if ($container->has('mime_types')) { diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php -index 7f3496d1fc..be6a1eff61 100644 +index 67eea6c877..101d432675 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php -@@ -400,5 +400,5 @@ class Email extends Message +@@ -388,5 +388,5 @@ class Email extends Message * @return void */ - public function ensureValidity() @@ -8984,10 +8973,10 @@ index 61c06d8f50..883293f6e0 100644 { $this->value = $value; diff --git a/src/Symfony/Component/Mime/Message.php b/src/Symfony/Component/Mime/Message.php -index e636c2e8e5..4c0597d16f 100644 +index 6b78316606..91797a13d2 100644 --- a/src/Symfony/Component/Mime/Message.php +++ b/src/Symfony/Component/Mime/Message.php -@@ -129,5 +129,5 @@ class Message extends RawMessage +@@ -126,5 +126,5 @@ class Message extends RawMessage * @return void */ - public function ensureValidity() @@ -9196,7 +9185,7 @@ index 40dbd41620..ac31fdc922 100644 { if (self::STATUS_STARTED !== $this->status) { diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php -index 0bf5c0afa9..dc0f2eae19 100644 +index ac45dbe3b0..24bd3924f2 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -123,5 +123,5 @@ class PropertyAccessor implements PropertyAccessorInterface @@ -10340,16 +10329,6 @@ index c925e00050..95d5bd4321 100644 + public function setTranslator(?TranslatorInterface $translator): void { $this->translator = $translator; -diff --git a/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php b/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php -index 91271d14a3..100c2fb549 100644 ---- a/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php -+++ b/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php -@@ -43,4 +43,4 @@ interface AuthenticationEntryPointInterface - * @return Response - */ -- public function start(Request $request, AuthenticationException $authException = null); -+ public function start(Request $request, AuthenticationException $authException = null): Response; - } diff --git a/src/Symfony/Component/Security/Http/Event/LoginFailureEvent.php b/src/Symfony/Component/Security/Http/Event/LoginFailureEvent.php index 3b7c5086f2..97fb99f0b5 100644 --- a/src/Symfony/Component/Security/Http/Event/LoginFailureEvent.php @@ -10726,10 +10705,10 @@ index 7cb1164034..b3feecc078 100644 /** diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php -index 3d11567a7b..22e873b151 100644 +index 7873f651a2..2778c8d3bf 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php -@@ -131,5 +131,5 @@ class GetSetMethodNormalizer extends AbstractObjectNormalizer +@@ -129,5 +129,5 @@ final class GetSetMethodNormalizer extends AbstractObjectNormalizer * @return void */ - protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []) @@ -10787,10 +10766,10 @@ index 533c07e6dd..66f30c7f93 100644 { try { diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php -index cfe93bc10b..7f1d8e5e13 100644 +index d4c5a97e89..c64626e1d6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php -@@ -171,5 +171,5 @@ class PropertyNormalizer extends AbstractObjectNormalizer +@@ -169,5 +169,5 @@ final class PropertyNormalizer extends AbstractObjectNormalizer * @return void */ - protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []) @@ -11273,31 +11252,6 @@ index 642130af75..c9ae2693a4 100644 - public function setPrefix(string $prefix); + public function setPrefix(string $prefix): void; } -diff --git a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php -index 7ff27f7c80..495067ed2e 100644 ---- a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php -+++ b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php -@@ -136,5 +136,5 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface - * @return void - */ -- public function extract(string|iterable $resource, MessageCatalogue $catalog) -+ public function extract(string|iterable $resource, MessageCatalogue $catalog): void - { - $files = $this->extractFiles($resource); -@@ -149,5 +149,5 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface - * @return void - */ -- public function setPrefix(string $prefix) -+ public function setPrefix(string $prefix): void - { - $this->prefix = $prefix; -@@ -265,5 +265,5 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface - * @return void - */ -- protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename) -+ protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename): void - { - $tokenIterator = new \ArrayIterator($tokens); diff --git a/src/Symfony/Component/Translation/Loader/CsvFileLoader.php b/src/Symfony/Component/Translation/Loader/CsvFileLoader.php index 7f2f96be64..266c7f48c9 100644 --- a/src/Symfony/Component/Translation/Loader/CsvFileLoader.php @@ -11591,38 +11545,38 @@ index acb00d7242..37cc40a06f 100644 { $this diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php -index d53bbb196f..4eecf85f8e 100644 +index 8156c99196..cfab6055f1 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php -@@ -236,5 +236,5 @@ abstract class Constraint +@@ -225,5 +225,5 @@ abstract class Constraint * @return void */ - public function addImplicitGroupName(string $group) + public function addImplicitGroupName(string $group): void { if (null === $this->groups && \array_key_exists('groups', (array) $this)) { -@@ -256,5 +256,5 @@ abstract class Constraint +@@ -245,5 +245,5 @@ abstract class Constraint * @see __construct() */ - public function getDefaultOption() + public function getDefaultOption(): ?string { return null; -@@ -270,5 +270,5 @@ abstract class Constraint +@@ -259,5 +259,5 @@ abstract class Constraint * @see __construct() */ - public function getRequiredOptions() + public function getRequiredOptions(): array { return []; -@@ -284,5 +284,5 @@ abstract class Constraint +@@ -273,5 +273,5 @@ abstract class Constraint * @return string */ - public function validatedBy() + public function validatedBy(): string { return static::class.'Validator'; -@@ -298,5 +298,5 @@ abstract class Constraint +@@ -287,5 +287,5 @@ abstract class Constraint * @return string|string[] One or more constant values */ - public function getTargets() @@ -11810,10 +11764,10 @@ index 5528252c52..de7c2c1257 100644 { if (!$constraint instanceof Choice) { diff --git a/src/Symfony/Component/Validator/Constraints/Collection.php b/src/Symfony/Component/Validator/Constraints/Collection.php -index ee50fca169..62effcb311 100644 +index a857c2aa43..21c0f07a19 100644 --- a/src/Symfony/Component/Validator/Constraints/Collection.php +++ b/src/Symfony/Component/Validator/Constraints/Collection.php -@@ -61,5 +61,5 @@ class Collection extends Composite +@@ -56,5 +56,5 @@ class Collection extends Composite * @return void */ - protected function initializeNestedConstraints() @@ -11916,10 +11870,10 @@ index 0e3d848430..b4a6755388 100644 { if (!$constraint instanceof Date) { diff --git a/src/Symfony/Component/Validator/Constraints/EmailValidator.php b/src/Symfony/Component/Validator/Constraints/EmailValidator.php -index 8c0ff77308..ca64a5fe88 100644 +index 72765dfbf7..6d14b36e92 100644 --- a/src/Symfony/Component/Validator/Constraints/EmailValidator.php +++ b/src/Symfony/Component/Validator/Constraints/EmailValidator.php -@@ -55,5 +55,5 @@ class EmailValidator extends ConstraintValidator +@@ -49,5 +49,5 @@ class EmailValidator extends ConstraintValidator * @return void */ - public function validate(mixed $value, Constraint $constraint) @@ -13613,10 +13567,10 @@ index 98c2149330..2e85547efb 100644 { if (!$this->connection->write($data) && $this->wrappedDumper) { diff --git a/src/Symfony/Component/VarDumper/VarDumper.php b/src/Symfony/Component/VarDumper/VarDumper.php -index a89f2369bb..78905c797d 100644 +index eda2727d50..5fde05973b 100644 --- a/src/Symfony/Component/VarDumper/VarDumper.php +++ b/src/Symfony/Component/VarDumper/VarDumper.php -@@ -43,5 +43,5 @@ class VarDumper +@@ -41,5 +41,5 @@ class VarDumper * @return mixed */ - public static function dump(mixed $var, string $label = null) @@ -13813,7 +13767,7 @@ index 9acd540dcc..495573aec4 100644 + public function getMetadata(string $key, string|Transition $subject = null): mixed; } diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php -index 287d8b750f..9462747d84 100644 +index ad72693c5a..50bf899d1c 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -28,5 +28,5 @@ class Registry diff --git a/UPGRADE-7.0.md b/UPGRADE-7.0.md index d8c88af9916bb..2ddc9324de2b3 100644 --- a/UPGRADE-7.0.md +++ b/UPGRADE-7.0.md @@ -11,6 +11,11 @@ Cache * Add parameter `$isSameDatabase` to `DoctrineDbalAdapter::configureSchema()` +Config +------ + + * Require explicit argument when calling `NodeBuilder::setParent()` + Console ------- @@ -41,7 +46,7 @@ Console } ``` - * Passing null to `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()` and `Question::setAutocompleterCallback/setValidator()` must be done explicitly + * Require explicit argument when calling `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()` and `Question::setAutocompleterCallback/setValidator()` * Remove `StringInput::REGEX_STRING` * Add method `__toString()` to `InputInterface` @@ -52,7 +57,7 @@ DependencyInjection * Remove `ProxyHelper`, use `Symfony\Component\VarExporter\ProxyHelper` instead * Remove `ReferenceSetArgumentTrait` * Remove support of `@required` annotation, use the `Symfony\Contracts\Service\Attribute\Required` attribute instead - * Passing `null` to `ContainerAwareTrait::setContainer()` must be done explicitly + * Require explicit argument when calling `ContainerAwareTrait::setContainer()` * Remove `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`, use options `inline_factories` and `inline_class_loader` instead * Parameter names of `ParameterBag` cannot be numerics * Remove `ContainerAwareInterface` and `ContainerAwareTrait`, use dependency injection instead @@ -82,10 +87,34 @@ Filesystem * Add argument `$lock` to `Filesystem::appendToFile()` +Form +---- + + * Throw when using `DateTime` or `DateTimeImmutable` model data with a different timezone than configured with the + `model_timezone` option in `DateType`, `DateTimeType`, and `TimeType` + * Make the "widget" option of date/time form types default to "single_text" + * Require explicit argument when calling `Button/Form::setParent()`, `ButtonBuilder/FormConfigBuilder::setDataMapper()`, `TransformationFailedException::setInvalidMessage()` + FrameworkBundle --------------- * Remove command `translation:update`, use `translation:extract` instead + * Make the `http_method_override` config option default to `false` + * Remove the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and + `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against + `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead + * Remove the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead + * Remove `AbstractController::renderForm()`, use `render()` instead + + *Before* + ```php + $this->renderForm(..., ['form' => $form]); + ``` + + *After* + ```php + $this->render(..., ['form' => $form]); + ``` HttpFoundation -------------- @@ -99,6 +128,7 @@ HttpFoundation * Replace `ExpressionRequestMatcher` with `RequestMatcher\ExpressionRequestMatcher` * Remove `Request::getContentType()`, use `Request::getContentTypeFormat()` instead * Throw an `InvalidArgumentException` when calling `Request::create()` with a malformed URI + * Require explicit argument when calling `JsonResponse::setCallback()`, `Response::setExpires/setLastModified/setEtag()`, `MockArraySessionStorage/NativeSessionStorage::setMetadataBag()`, `NativeSessionStorage::setSaveHandler()` HttpClient ---------- @@ -114,6 +144,7 @@ HttpKernel * Remove `AbstractSurrogate::$phpEscapeMap` * Remove `HttpKernelInterface::MASTER_REQUEST` * Remove `terminate_on_cache_hit` option from `HttpCache` + * Require explicit argument when calling `ConfigDataCollector::setKernel()`, `RouterListener::setCurrentRequest()` Lock ---- @@ -121,21 +152,34 @@ Lock * Add parameter `$isSameDatabase` to `DoctrineDbalStore::configureSchema()` * Remove the `gcProbablity` (notice the typo) option, use `gcProbability` instead +Mailer +------ + + * Remove the OhMySmtp bridge in favor of the MailPace bridge + Messenger --------- * Add parameter `$isSameDatabase` to `DoctrineTransport::configureSchema()` + * Remove `MessageHandlerInterface` and `MessageSubscriberInterface`, use `#[AsMessageHandler]` instead + * Remove `StopWorkerOnSigtermSignalListener` in favor of + `StopWorkerOnSignalsListener` and make it configurable with SIGINT and + * Remove `Symfony\Component\Messenger\Transport\InMemoryTransport` and + `Symfony\Component\Messenger\Transport\InMemoryTransportFactory` in favor of + `Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport` and + `Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory` Mime ---- * Remove `Email::attachPart()` method, use `Email::addPart()` instead - * Parameter `$body` is now required (at least null) in `Message::setBody()` + * Require explicit argument when calling `Message::setBody()` PropertyAccess -------------- * Add method `isNullSafe()` to `PropertyPathInterface` + * Require explicit argument when calling `PropertyAccessorBuilder::setCacheItemPool()` ProxyManagerBridge ------------------ @@ -152,6 +196,7 @@ Security * Add argument `$badgeFqcn` to `Passport::addBadge()` * Add argument `$lifetime` to `LoginLinkHandlerInterface::createLoginLink()` + * Require explicit argument when calling `TokenStorage::setToken()` SecurityBundle -------------- @@ -189,6 +234,7 @@ Serializer } } ``` + * Remove `CacheableSupportsMethodInterface`, use `NormalizerInterface` and `DenormalizerInterface` instead *Before* @@ -233,9 +279,24 @@ Serializer // ... } ``` - * First argument of `AttributeMetadata::setSerializedName()` is now required + + * Require explicit argument when calling `AttributeMetadata::setSerializedName()` and `ClassMetadata::setClassDiscriminatorMapping()` * Add argument `$context` to `NormalizerInterface::supportsNormalization()` and `DenormalizerInterface::supportsDenormalization()` +Translation +----------- + + * Remove `PhpStringTokenParser` + * Remove `PhpExtractor` in favor of `PhpAstExtractor` + +TwigBundle +---------- + + * Remove the `Twig_Environment` autowiring alias, use `Twig\Environment` instead + * Remove option `twig.autoescape`; create a class that implements your escaping strategy + (check `FileExtensionEscapingStrategy::guess()` for inspiration) and reference it using + the `twig.autoescape_service` option instead + Validator --------- @@ -250,3 +311,14 @@ VarDumper --------- * Add argument `$label` to `VarDumper::dump()` + * Require explicit argument when calling `VarDumper::setHandler()` + +Workflow +-------- + + * Require explicit argument when calling `Definition::setInitialPlaces()` + +Yaml +---- + + * Remove the `!php/const:` tag, use `!php/const` instead (without the colon) diff --git a/composer.json b/composer.json index 8144b42e051ad..0a270471df520 100644 --- a/composer.json +++ b/composer.json @@ -141,7 +141,6 @@ "pda/pheanstalk": "^4.0", "php-http/discovery": "^1.15", "php-http/httplug": "^1.0|^2.0", - "php-http/message-factory": "^1.0", "phpdocumentor/reflection-docblock": "^5.2", "phpstan/phpdoc-parser": "^1.0", "predis/predis": "^1.1|^2.0", diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index 1382eaf66645a..82cc8a5b7bc88 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -22,7 +22,7 @@ use Symfony\Component\DependencyInjection\Reference; /** - * Registers event listeners and subscribers to the available doctrine connections. + * Registers event listeners to the available doctrine connections. * * @author Jeremy Mikola * @author Alexander @@ -44,7 +44,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface /** * @param string $managerTemplate sprintf() template for generating the event * manager's service ID for a connection name - * @param string $tagPrefix Tag prefix for listeners and subscribers + * @param string $tagPrefix Tag prefix for listeners */ public function __construct(string $connectionsParameter, string $managerTemplate, string $tagPrefix) { @@ -72,18 +72,13 @@ public function process(ContainerBuilder $container): void private function addTaggedServices(ContainerBuilder $container): array { - $listenerTag = $this->tagPrefix.'.event_listener'; - $subscriberTag = $this->tagPrefix.'.event_subscriber'; $listenerRefs = []; - $taggedServices = $this->findAndSortTags($subscriberTag, $listenerTag, $container); - $managerDefs = []; - foreach ($taggedServices as $taggedSubscriber) { - [$tagName, $id, $tag] = $taggedSubscriber; + foreach ($this->findAndSortTags($container) as [$id, $tag]) { $connections = isset($tag['connection']) ? [$container->getParameterBag()->resolveValue($tag['connection'])] : array_keys($this->connections); - if ($listenerTag === $tagName && !isset($tag['event'])) { + if (!isset($tag['event'])) { throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); } foreach ($connections as $con) { @@ -105,19 +100,10 @@ private function addTaggedServices(ContainerBuilder $container): array if (ContainerAwareEventManager::class === $managerClass) { $refs = $managerDef->getArguments()[1] ?? []; $listenerRefs[$con][$id] = new Reference($id); - if ($subscriberTag === $tagName) { - trigger_deprecation('symfony/doctrine-bridge', '6.3', 'Registering "%s" as a Doctrine subscriber is deprecated. Register it as a listener instead, using e.g. the #[AsDoctrineListener] attribute.', $id); - $refs[] = $id; - } else { - $refs[] = [[$tag['event']], $id]; - } + $refs[] = [[$tag['event']], $id]; $managerDef->setArgument(1, $refs); } else { - if ($subscriberTag === $tagName) { - $managerDef->addMethodCall('addEventSubscriber', [new Reference($id)]); - } else { - $managerDef->addMethodCall('addEventListener', [[$tag['event']], new Reference($id)]); - } + $managerDef->addMethodCall('addEventListener', [[$tag['event']], new Reference($id)]); } } } @@ -144,21 +130,14 @@ private function getEventManagerDef(ContainerBuilder $container, string $name): * @see https://bugs.php.net/53710 * @see https://bugs.php.net/60926 */ - private function findAndSortTags(string $subscriberTag, string $listenerTag, ContainerBuilder $container): array + private function findAndSortTags(ContainerBuilder $container): array { $sortedTags = []; - $taggedIds = [ - $subscriberTag => $container->findTaggedServiceIds($subscriberTag, true), - $listenerTag => $container->findTaggedServiceIds($listenerTag, true), - ]; - $taggedIds[$subscriberTag] = array_diff_key($taggedIds[$subscriberTag], $taggedIds[$listenerTag]); - - foreach ($taggedIds as $tagName => $serviceIds) { - foreach ($serviceIds as $serviceId => $tags) { - foreach ($tags as $attributes) { - $priority = $attributes['priority'] ?? 0; - $sortedTags[$priority][] = [$tagName, $serviceId, $attributes]; - } + + foreach ($container->findTaggedServiceIds($this->tagPrefix.'.event_listener', true) as $serviceId => $tags) { + foreach ($tags as $attributes) { + $priority = $attributes['priority'] ?? 0; + $sortedTags[$priority][] = [$serviceId, $attributes]; } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php index 254953c9d6a2a..0966d5ae1bec7 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\ContainerAwareEventManager; use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -23,22 +22,6 @@ class RegisterEventListenersAndSubscribersPassTest extends TestCase { - use ExpectDeprecationTrait; - - public function testExceptionOnAbstractTaggedSubscriber() - { - $this->expectException(\InvalidArgumentException::class); - $container = $this->createBuilder(); - - $abstractDefinition = new Definition('stdClass'); - $abstractDefinition->setAbstract(true); - $abstractDefinition->addTag('doctrine.event_subscriber'); - - $container->setDefinition('a', $abstractDefinition); - - $this->process($container); - } - public function testExceptionOnAbstractTaggedListener() { $this->expectException(\InvalidArgumentException::class); @@ -198,300 +181,6 @@ public function testProcessEventListenersWithMultipleConnections() ); } - /** - * @group legacy - */ - public function testProcessEventSubscribersWithMultipleConnections() - { - $container = $this->createBuilder(true); - - $container->setParameter('connection_param', 'second'); - - $container - ->register('a', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'event' => 'onFlush', - ]) - ; - - $container - ->register('b', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'event' => 'onFlush', - 'connection' => 'default', - ]) - ; - - $container - ->register('c', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'event' => 'onFlush', - 'connection' => 'second', - ]) - ; - - $container - ->register('d', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'event' => 'onFlush', - 'connection' => '%connection_param%', - ]) - ; - - $this->expectDeprecation('Since symfony/doctrine-bridge 6.3: Registering "d" as a Doctrine subscriber is deprecated. Register it as a listener instead, using e.g. the #[AsDoctrineListener] attribute.'); - $this->process($container); - - $eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager'); - - // first connection - $this->assertEquals( - [ - 'a', - 'b', - ], - $eventManagerDef->getArgument(1) - ); - - $serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0)); - $this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass()); - $this->assertEquals( - [ - 'a' => new ServiceClosureArgument(new Reference('a')), - 'b' => new ServiceClosureArgument(new Reference('b')), - ], - $serviceLocatorDef->getArgument(0) - ); - - $eventManagerDef = $container->getDefinition('doctrine.dbal.second_connection.event_manager'); - - // second connection - $this->assertEquals( - [ - 'a', - 'c', - 'd', - ], - $eventManagerDef->getArgument(1) - ); - - $serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0)); - $this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass()); - $this->assertEquals( - [ - 'a' => new ServiceClosureArgument(new Reference('a')), - 'c' => new ServiceClosureArgument(new Reference('c')), - 'd' => new ServiceClosureArgument(new Reference('d')), - ], - $serviceLocatorDef->getArgument(0) - ); - } - - /** - * @group legacy - */ - public function testProcessEventSubscribersWithPriorities() - { - $container = $this->createBuilder(); - - $container - ->register('a', 'stdClass') - ->addTag('doctrine.event_subscriber') - ; - $container - ->register('b', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 5, - ]) - ; - $container - ->register('c', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - $container - ->register('d', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - $container - ->register('e', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - - $this->expectDeprecation('Since symfony/doctrine-bridge 6.3: Registering "d" as a Doctrine subscriber is deprecated. Register it as a listener instead, using e.g. the #[AsDoctrineListener] attribute.'); - $this->process($container); - - $eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager'); - - $this->assertEquals( - [ - 'c', - 'd', - 'e', - 'b', - 'a', - ], - $eventManagerDef->getArgument(1) - ); - - $serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0)); - $this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass()); - $this->assertEquals( - [ - 'a' => new ServiceClosureArgument(new Reference('a')), - 'b' => new ServiceClosureArgument(new Reference('b')), - 'c' => new ServiceClosureArgument(new Reference('c')), - 'd' => new ServiceClosureArgument(new Reference('d')), - 'e' => new ServiceClosureArgument(new Reference('e')), - ], - $serviceLocatorDef->getArgument(0) - ); - } - - /** - * @group legacy - */ - public function testProcessEventSubscribersAndListenersWithPriorities() - { - $container = $this->createBuilder(); - - $container - ->register('a', 'stdClass') - ->addTag('doctrine.event_subscriber') - ; - $container - ->register('b', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 5, - ]) - ; - $container - ->register('c', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - $container - ->register('d', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - $container - ->register('e', 'stdClass') - ->addTag('doctrine.event_subscriber', [ - 'priority' => 10, - ]) - ; - $container - ->register('f', 'stdClass') - ->setPublic(false) - ->addTag('doctrine.event_listener', [ - 'event' => 'bar', - ]) - ->addTag('doctrine.event_listener', [ - 'event' => 'foo', - 'priority' => -5, - ]) - ->addTag('doctrine.event_listener', [ - 'event' => 'foo_bar', - 'priority' => 3, - ]) - ; - $container - ->register('g', 'stdClass') - ->addTag('doctrine.event_listener', [ - 'event' => 'foo', - ]) - ; - $container - ->register('h', 'stdClass') - ->addTag('doctrine.event_listener', [ - 'event' => 'foo_bar', - 'priority' => 4, - ]) - ; - - $this->expectDeprecation('Since symfony/doctrine-bridge 6.3: Registering "d" as a Doctrine subscriber is deprecated. Register it as a listener instead, using e.g. the #[AsDoctrineListener] attribute.'); - $this->process($container); - - $eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager'); - - $this->assertEquals( - [ - 'c', - 'd', - 'e', - 'b', - [['foo_bar'], 'h'], - [['foo_bar'], 'f'], - 'a', - [['bar'], 'f'], - [['foo'], 'g'], - [['foo'], 'f'], - ], - $eventManagerDef->getArgument(1) - ); - - $serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0)); - $this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass()); - $this->assertEquals( - [ - 'a' => new ServiceClosureArgument(new Reference('a')), - 'b' => new ServiceClosureArgument(new Reference('b')), - 'c' => new ServiceClosureArgument(new Reference('c')), - 'd' => new ServiceClosureArgument(new Reference('d')), - 'e' => new ServiceClosureArgument(new Reference('e')), - 'f' => new ServiceClosureArgument(new Reference('f')), - 'g' => new ServiceClosureArgument(new Reference('g')), - 'h' => new ServiceClosureArgument(new Reference('h')), - ], - $serviceLocatorDef->getArgument(0) - ); - } - - public function testSubscribersAreSkippedIfListenerDefinedForSameDefinition() - { - $container = $this->createBuilder(); - - $container - ->register('a', 'stdClass') - ->setPublic(false) - ->addTag('doctrine.event_listener', [ - 'event' => 'bar', - 'priority' => 3, - ]) - ; - $container - ->register('b', 'stdClass') - ->setPublic(false) - ->addTag('doctrine.event_listener', [ - 'event' => 'bar', - ]) - ->addTag('doctrine.event_listener', [ - 'event' => 'foo', - 'priority' => -5, - ]) - ->addTag('doctrine.event_subscriber') - ; - $this->process($container); - - $eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager'); - - $this->assertEquals( - [ - [['bar'], 'a'], - [['bar'], 'b'], - [['foo'], 'b'], - ], - $eventManagerDef->getArgument(1) - ); - } - public function testProcessNoTaggedServices() { $container = $this->createBuilder(true); diff --git a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php index bbe50eba9c748..266f1bf0caba4 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php @@ -48,7 +48,7 @@ protected function getDefaultFormatter() /** * @author Grégoire Pineau * - * @internal since Symfony 6.1 + * @internal */ trait ServerLogHandlerTrait { diff --git a/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php index c455be29a33ec..5d92298fea6fc 100644 --- a/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php @@ -21,20 +21,15 @@ * @author Dany Maillard * @author Igor Timoshenko * - * @internal since Symfony 6.1 + * @internal */ abstract class AbstractTokenProcessor { use CompatibilityProcessor; - /** - * @var TokenStorageInterface - */ - protected $tokenStorage; - - public function __construct(TokenStorageInterface $tokenStorage) - { - $this->tokenStorage = $tokenStorage; + public function __construct( + protected TokenStorageInterface $tokenStorage, + ) { } abstract protected function getKey(): string; diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index effe9a43031c3..79c157980652c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -5,6 +5,12 @@ CHANGELOG --- * Remove command `translation:update`, use `translation:extract` instead + * Make the `http_method_override` config option default to `false` + * Remove `AbstractController::renderForm()`, use `render()` instead + * Remove the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and + `Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against + `Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead + * Remove the `Http\Client\HttpClient` service, use `Psr\Http\Client\ClientInterface` instead 6.3 --- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index f84a560c6d44b..f69a0e11e2863 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -21,7 +21,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Dumper\GraphvizDumper; use Symfony\Component\Workflow\Dumper\MermaidDumper; use Symfony\Component\Workflow\Dumper\PlantUmlDumper; @@ -37,33 +36,16 @@ #[AsCommand(name: 'workflow:dump', description: 'Dump a workflow')] class WorkflowDumpCommand extends Command { - /** - * string is the service id. - * - * @var array - */ - private array $definitions = []; - - private ServiceLocator $workflows; - private const DUMP_FORMAT_OPTIONS = [ 'puml', 'mermaid', 'dot', ]; - public function __construct($workflows) - { + public function __construct( + private ServiceLocator $workflows, + ) { parent::__construct(); - - if ($workflows instanceof ServiceLocator) { - $this->workflows = $workflows; - } elseif (\is_array($workflows)) { - $this->definitions = $workflows; - trigger_deprecation('symfony/framework-bundle', '6.2', 'Passing an array of definitions in "%s()" is deprecated. Inject a ServiceLocator filled with all workflows instead.', __METHOD__); - } else { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an array or a ServiceLocator, "%s" given.', __METHOD__, \gettype($workflows))); - } } protected function configure(): void @@ -92,20 +74,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $workflowName = $input->getArgument('name'); - if (isset($this->workflows)) { - if (!$this->workflows->has($workflowName)) { - throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); - } - $workflow = $this->workflows->get($workflowName); - $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; - $definition = $workflow->getDefinition(); - } elseif (isset($this->definitions['workflow.'.$workflowName])) { - $definition = $this->definitions['workflow.'.$workflowName]; - $type = 'workflow'; - } elseif (isset($this->definitions['state_machine.'.$workflowName])) { - $definition = $this->definitions['state_machine.'.$workflowName]; - $type = 'state_machine'; + if (!$this->workflows->has($workflowName)) { + throw new InvalidArgumentException(sprintf('The workflow named "%s" cannot be found.', $workflowName)); } + $workflow = $this->workflows->get($workflowName); + $type = $workflow instanceof StateMachine ? 'state_machine' : 'workflow'; + $definition = $workflow->getDefinition(); if (null === $definition) { throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName)); @@ -147,11 +121,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestArgumentValuesFor('name')) { - if (isset($this->workflows)) { - $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices())); - } else { - $suggestions->suggestValues(array_keys($this->definitions)); - } + $suggestions->suggestValues(array_keys($this->workflows->getProvidedServices())); } if ($input->mustSuggestOptionValuesFor('dump-format')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index 13e155235358b..4af31ad7d1dd0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -186,7 +186,7 @@ protected function addFlash(string $type, mixed $message): void } if (!$session instanceof FlashBagAwareSessionInterface) { - trigger_deprecation('symfony/framework-bundle', '6.2', 'Calling "addFlash()" method when the session does not implement %s is deprecated.', FlashBagAwareSessionInterface::class); + throw new \LogicException(sprintf('You cannot use the addFlash method because class "%s" doesn\'t implement "%s".', get_debug_type($session), FlashBagAwareSessionInterface::class)); } $session->getFlashBag()->add($type, $message); @@ -268,20 +268,6 @@ protected function render(string $view, array $parameters = [], Response $respon return $response; } - /** - * Renders a view and sets the appropriate status code when a form is listed in parameters. - * - * If an invalid form is found in the list of parameters, a 422 status code is returned. - * - * @deprecated since Symfony 6.2, use render() instead - */ - protected function renderForm(string $view, array $parameters = [], Response $response = null): Response - { - trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s::renderForm()" method is deprecated, use "render()" instead.', get_debug_type($this)); - - return $this->render($view, $parameters, $response); - } - /** * Streams a view. */ diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 708b43b840c84..8ca6a54c06803 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -81,23 +81,12 @@ public function getConfigTreeBuilder(): TreeBuilder return $v; }) ->end() - ->validate() - ->always(function ($v) { - if (!isset($v['http_method_override'])) { - trigger_deprecation('symfony/framework-bundle', '6.1', 'Not setting the "framework.http_method_override" config option is deprecated. It will default to "false" in 7.0.'); - - $v['http_method_override'] = true; - } - - return $v; - }) - ->end() ->fixXmlConfig('enabled_locale') ->children() ->scalarNode('secret')->end() ->booleanNode('http_method_override') ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") - ->treatNullLike(false) + ->defaultFalse() ->end() ->scalarNode('trust_x_sendfile_type_header') ->info('Set true to enable support for xsendfile in binary file responses.') @@ -244,9 +233,6 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->scalarNode('field_name')->defaultValue('_token')->end() ->end() ->end() - ->booleanNode('legacy_error_messages') - ->setDeprecated('symfony/framework-bundle', '6.2') - ->end() ->end() ->end() ->end() @@ -1303,27 +1289,6 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode): void ->arrayNode('exceptions') ->info('Exception handling configuration') ->useAttributeAsKey('class') - ->beforeNormalization() - // Handle legacy XML configuration - ->ifArray() - ->then(function (array $v): array { - if (!\array_key_exists('exception', $v)) { - return $v; - } - - trigger_deprecation('symfony/framework-bundle', '6.3', '"framework:exceptions" tag is deprecated. Unwrap it and replace your "framework:exception" tags\' "name" attribute by "class".'); - - $v = $v['exception']; - unset($v['exception']); - - foreach ($v as &$exception) { - $exception['class'] = $exception['name']; - unset($exception['name']); - } - - return $v; - }) - ->end() ->prototype('array') ->children() ->scalarNode('log_level') @@ -1620,15 +1585,6 @@ function ($a) { ->defaultNull() ->info('Transport name to send failed messages to (after all retries have failed).') ->end() - ->booleanNode('reset_on_message') - ->defaultTrue() - ->info('Reset container services after each message.') - ->setDeprecated('symfony/framework-bundle', '6.1', 'Option "%node%" at "%path%" is deprecated. It does nothing and will be removed in version 7.0.') - ->validate() - ->ifTrue(static fn ($v) => true !== $v) - ->thenInvalid('The "framework.messenger.reset_on_message" configuration option can be set to "true" only. To prevent services resetting after each message you can set the "--no-reset" option in "messenger:consume" command.') - ->end() - ->end() ->arrayNode('stop_worker_on_signals') ->defaultValue([]) ->info('A list of signals that should stop the worker; defaults to SIGTERM and SIGINT.') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f5ddf2fac6aa3..34e8c93b932ba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -111,7 +111,6 @@ use Symfony\Component\Messenger\Bridge as MessengerBridge; use Symfony\Component\Messenger\Command\StatsCommand; use Symfony\Component\Messenger\Handler\BatchHandlerInterface; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; @@ -213,7 +212,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled('symfony/symfony') && 'symfony/symfony' !== (InstalledVersions::getRootPackage()['name'] ?? '')) { - trigger_deprecation('symfony/symfony', '6.1', 'Requiring the "symfony/symfony" package is deprecated; replace it with standalone components instead.'); + throw new \LogicException('Requiring the "symfony/symfony" package is unsupported; replace it with standalone components instead.'); } $loader->load('web.php'); @@ -647,8 +646,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('validator.constraint_validator'); $container->registerForAutoconfiguration(ObjectInitializerInterface::class) ->addTag('validator.initializer'); - $container->registerForAutoconfiguration(MessageHandlerInterface::class) - ->addTag('messenger.message_handler'); $container->registerForAutoconfiguration(BatchHandlerInterface::class) ->addTag('messenger.message_handler'); $container->registerForAutoconfiguration(MessengerTransportFactoryInterface::class) @@ -2591,7 +2588,6 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailjet\Transport\MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', - MailerBridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', MailerBridge\Sendinblue\Transport\SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', @@ -2893,45 +2889,6 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde } } - /** - * @deprecated since Symfony 6.2 - * - * @return void - */ - public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig) - { - trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s()" method is deprecated.', __METHOD__); - - // default configuration (when used by other DI extensions) - $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter']; - - $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); - - if (null !== $limiterConfig['lock_factory']) { - if (!interface_exists(LockInterface::class)) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be installed. Try running "composer require symfony/lock".', $name)); - } - if (!$container->hasDefinition('lock.factory.abstract')) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be configured.', $name)); - } - - $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory'])); - } - unset($limiterConfig['lock_factory']); - - if (null === $storageId = $limiterConfig['storage_service'] ?? null) { - $container->register($storageId = 'limiter.storage.'.$name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool'])); - } - - $limiter->replaceArgument(1, new Reference($storageId)); - unset($limiterConfig['storage_service'], $limiterConfig['cache_pool']); - - $limiterConfig['id'] = $name; - $limiter->replaceArgument(0, $limiterConfig); - - $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); - } - private function registerUidConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void { $loader->load('uid.php'); diff --git a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php index 694714faa0feb..794f4f454427d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php +++ b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php @@ -110,10 +110,6 @@ public function loginUser(object $user, string $firewallContext = 'main'): stati } $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); - // required for compatibility with Symfony 5.4 - if (method_exists($token, 'isAuthenticated')) { - $token->setAuthenticated(true, false); - } $container = $this->getContainer(); $container->get('security.untracked_token_storage')->setToken($token); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php index f043c87ec7d73..0f561d9d3a571 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php @@ -22,7 +22,7 @@ return static function (ContainerConfigurator $container) { $container->services() ->set('annotations.reader', AnnotationReader::class) - ->call('addGlobalIgnoredName', ['required']) // @deprecated since Symfony 6.3 + ->call('addGlobalIgnoredName', ['required']) ->set('annotations.cached_reader', PsrCachedReader::class) ->args([ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.php index 23b794f45b2dd..ed932fdf8e7f6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.php @@ -58,8 +58,6 @@ ]) ->alias(HttpAsyncClient::class, 'httplug.http_client') - ->alias(\Http\Client\HttpClient::class, 'httplug.http_client') - ->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "'.ClientInterface::class.'" instead.') ->set('http_client.abstract_retry_strategy', GenericRetryStrategy::class) ->abstract() diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php index d352eb5bee856..bc5900a76c65c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -19,7 +19,6 @@ use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -92,10 +91,6 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.ohmysmtp', OhMySmtpTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory', ['priority' => -100]) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 3fe593ac673ff..0096ff1e099f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -209,9 +209,6 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) - ->alias('messenger.listener.stop_worker_on_sigterm_signal_listener', 'messenger.listener.stop_worker_signals_listener') - ->deprecate('6.3', 'symfony/messenger', 'The "%alias_id%" service is deprecated, use "messenger.listener.stop_worker_signals_listener" instead.') - ->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class) ->tag('kernel.event_subscriber') diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php index 6ce674148a878..3bd19b8ddc061 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php @@ -129,8 +129,5 @@ ->set('notifier.notification_logger_listener', NotificationLoggerListener::class) ->tag('kernel.event_subscriber') - ->alias('notifier.logger_notification_listener', 'notifier.notification_logger_listener') - ->deprecate('symfony/framework-bundle', '6.3', 'The "%alias_id%" service is deprecated, use "notifier.notification_logger_listener" instead.') - ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index a2abb5bc0c42a..69475e307a1ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -31,8 +31,7 @@ - - + @@ -67,7 +66,6 @@ - @@ -409,31 +407,10 @@ - - - - - - - + - - - - - - - - - - - - - - - - + @@ -585,7 +562,6 @@ - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index 6459dfa4442bd..94107237f0bae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -42,7 +42,6 @@ use Symfony\Component\Serializer\Normalizer\FormErrorNormalizer; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Serializer\Normalizer\MimeMessageNormalizer; -use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ProblemNormalizer; @@ -127,9 +126,6 @@ ]) ->tag('serializer.normalizer', ['priority' => -1000]) - ->alias(ObjectNormalizer::class, 'serializer.normalizer.object') - ->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "'.NormalizerInterface::class.'" or implement "'.NormalizerAwareInterface::class.'" instead.') - ->set('serializer.normalizer.property', PropertyNormalizer::class) ->args([ service('serializer.mapping.class_metadata_factory'), @@ -139,9 +135,6 @@ null, ]) - ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') - ->deprecate('symfony/serializer', '6.2', 'The "%alias_id%" service alias is deprecated, type-hint against "'.NormalizerInterface::class.'" or implement "'.NormalizerAwareInterface::class.'" instead.') - ->set('serializer.denormalizer.array', ArrayDenormalizer::class) ->tag('serializer.normalizer', ['priority' => -990]) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php index dcfa2bc15716d..a450e6894cc8a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php @@ -27,7 +27,6 @@ use Symfony\Component\Translation\Extractor\ChainExtractor; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\Extractor\PhpAstExtractor; -use Symfony\Component\Translation\Extractor\PhpExtractor; use Symfony\Component\Translation\Extractor\Visitor\ConstraintVisitor; use Symfony\Component\Translation\Extractor\Visitor\TranslatableMessageVisitor; use Symfony\Component\Translation\Extractor\Visitor\TransMethodVisitor; @@ -152,10 +151,6 @@ ->set('translation.dumper.res', IcuResFileDumper::class) ->tag('translation.dumper', ['alias' => 'res']) - ->set('translation.extractor.php', PhpExtractor::class) - ->deprecate('symfony/framework-bundle', '6.2', 'The "%service_id%" service is deprecated, use "translation.extractor.php_ast" instead.') - ->tag('translation.extractor', ['alias' => 'php']) - ->set('translation.extractor.php_ast', PhpAstExtractor::class) ->args([tagged_iterator('translation.extractor.visitor')]) ->tag('translation.extractor', ['alias' => 'php']) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php index 85d786537f031..2c47fa96058ba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.php @@ -40,10 +40,6 @@ ->set('workflow.marking_store.method', MethodMarkingStore::class) ->abstract() ->set('.workflow.registry', Registry::class) - ->alias(Registry::class, '.workflow.registry') - ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" alias is deprecated, inject the workflow directly.') - ->alias('workflow.registry', '.workflow.registry') - ->deprecate('symfony/workflow', '6.2', 'The "%alias_id%" alias is deprecated, inject the workflow directly.') ->set('workflow.security.expression_language', ExpressionLanguage::class) ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index efa9c7becab59..14e5abd0115d0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -471,58 +471,6 @@ public function testRenderWithFormSubmittedAndInvalid() $this->assertSame('bar', $response->getContent()); } - /** - * @group legacy - */ - public function testRenderForm() - { - $formView = new FormView(); - - $form = $this->getMockBuilder(FormInterface::class)->getMock(); - $form->expects($this->once())->method('createView')->willReturn($formView); - - $twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); - $twig->expects($this->once())->method('render')->with('foo', ['bar' => $formView])->willReturn('bar'); - - $container = new Container(); - $container->set('twig', $twig); - - $controller = $this->createController(); - $controller->setContainer($container); - - $response = $controller->renderForm('foo', ['bar' => $form]); - - $this->assertTrue($response->isSuccessful()); - $this->assertSame('bar', $response->getContent()); - } - - /** - * @group legacy - */ - public function testRenderFormSubmittedAndInvalid() - { - $formView = new FormView(); - - $form = $this->getMockBuilder(FormInterface::class)->getMock(); - $form->expects($this->once())->method('createView')->willReturn($formView); - $form->expects($this->once())->method('isSubmitted')->willReturn(true); - $form->expects($this->once())->method('isValid')->willReturn(false); - - $twig = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); - $twig->expects($this->once())->method('render')->with('foo', ['bar' => $formView])->willReturn('bar'); - - $container = new Container(); - $container->set('twig', $twig); - - $controller = $this->createController(); - $controller->setContainer($container); - - $response = $controller->renderForm('foo', ['bar' => $form]); - - $this->assertSame(422, $response->getStatusCode()); - $this->assertSame('bar', $response->getContent()); - } - public function testStreamTwig() { $twig = $this->createMock(Environment::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index e3ecd982d3cc8..2e291157abcbd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -676,7 +676,6 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], 'default_bus' => null, 'buses' => ['messenger.bus.default' => ['default_middleware' => ['enabled' => true, 'allow_no_handlers' => false, 'allow_no_senders' => true], 'middleware' => []]], - 'reset_on_message' => true, 'stop_worker_on_signals' => [], ], 'disallow_search_engine_index' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php deleted file mode 100644 index 3cb006c46750b..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_disabled_reset_on_message.php +++ /dev/null @@ -1,20 +0,0 @@ -loadFromExtension('framework', [ - 'http_method_override' => false, - 'messenger' => [ - 'reset_on_message' => false, - 'routing' => [ - FooMessage::class => ['sender.bar', 'sender.biz'], - BarMessage::class => 'sender.foo', - ], - 'transports' => [ - 'sender.biz' => 'null://', - 'sender.bar' => 'null://', - 'sender.foo' => 'null://', - ], - ], -]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php deleted file mode 100644 index ee689ae0932db..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_with_explict_reset_on_message_legacy.php +++ /dev/null @@ -1,20 +0,0 @@ -loadFromExtension('framework', [ - 'http_method_override' => false, - 'messenger' => [ - 'reset_on_message' => true, - 'routing' => [ - FooMessage::class => ['sender.bar', 'sender.biz'], - BarMessage::class => 'sender.foo', - ], - 'transports' => [ - 'sender.biz' => 'null://', - 'sender.bar' => 'null://', - 'sender.foo' => 'null://', - ], - ], -]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml deleted file mode 100644 index 2e6048fa7c7aa..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml deleted file mode 100644 index c0bc33bcde151..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_disabled_reset_on_message.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml deleted file mode 100644 index 4c208aad2f0b2..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_with_explict_reset_on_message_legacy.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 97831b04e7773..968195153f38e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -14,7 +14,6 @@ use Doctrine\Common\Annotations\Annotation; use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; @@ -93,8 +92,6 @@ abstract class FrameworkExtensionTestCase extends TestCase { - use ExpectDeprecationTrait; - private static $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -507,7 +504,7 @@ public function testWorkflowServicesCanBeEnabled() { $container = $this->createContainerFromFile('workflows_enabled'); - $this->assertTrue($container->has(Workflow\Registry::class)); + $this->assertTrue($container->hasDefinition('.workflow.registry')); $this->assertTrue($container->hasDefinition('console.command.workflow_dump')); } @@ -791,26 +788,6 @@ public function testMessengerServicesRemovedWhenDisabled() $this->assertFalse($container->hasDefinition('cache.messenger.restart_workers_signal')); } - /** - * @group legacy - */ - public function testMessengerWithExplictResetOnMessageLegacy() - { - $this->expectDeprecation('Since symfony/framework-bundle 6.1: Option "reset_on_message" at "framework.messenger" is deprecated. It does nothing and will be removed in version 7.0.'); - - $container = $this->createContainerFromFile('messenger_with_explict_reset_on_message_legacy'); - - $this->assertTrue($container->hasDefinition('console.command.messenger_consume_messages')); - $this->assertTrue($container->hasAlias('messenger.default_bus')); - $this->assertTrue($container->getAlias('messenger.default_bus')->isPublic()); - $this->assertTrue($container->hasDefinition('messenger.transport.amqp.factory')); - $this->assertTrue($container->hasDefinition('messenger.transport.redis.factory')); - $this->assertTrue($container->hasDefinition('messenger.transport_factory')); - $this->assertSame(TransportFactory::class, $container->getDefinition('messenger.transport_factory')->getClass()); - $this->assertTrue($container->hasDefinition('messenger.listener.reset_services')); - $this->assertSame('messenger.listener.reset_services', (string) $container->getDefinition('console.command.messenger_consume_messages')->getArgument(5)); - } - public function testMessenger() { $container = $this->createContainerFromFile('messenger', [], true, false); @@ -1117,17 +1094,6 @@ public function testMessengerInvalidWildcardRouting() $this->createContainerFromFile('messenger_routing_invalid_transport'); } - /** - * @group legacy - */ - public function testMessengerWithDisabledResetOnMessage() - { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('The "framework.messenger.reset_on_message" configuration option can be set to "true" only. To prevent services resetting after each message you can set the "--no-reset" option in "messenger:consume" command.'); - - $this->createContainerFromFile('messenger_with_disabled_reset_on_message'); - } - public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php index 36d3f5e379d3e..40b3588d77a1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php @@ -33,40 +33,6 @@ public function testMessengerMiddlewareFactoryErroneousFormat() $this->markTestSkipped('XML configuration will not allow erroneous format.'); } - public function testLegacyExceptionsConfig() - { - $container = $this->createContainerFromFile('exceptions_legacy'); - - $configuration = $container->getDefinition('exception_listener')->getArgument(3); - - $this->assertSame([ - \Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class, - \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class, - \Symfony\Component\HttpKernel\Exception\ConflictHttpException::class, - \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class, - ], array_keys($configuration)); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => 422, - ], $configuration[\Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => 'info', - 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ConflictHttpException::class]); - - $this->assertEqualsCanonicalizing([ - 'log_level' => null, - 'status_code' => 500, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class]); - } - public function testRateLimiter() { $container = $this->createContainerFromFile('rate_limiter'); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 722a4c5f10243..069dcc7b4dec9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -22,7 +22,6 @@ "symfony/cache": "^6.4|^7.0", "symfony/config": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", - "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/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index cc93d323df7e9..10ceb6826f4f3 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; @@ -40,8 +39,6 @@ class SecurityExtensionTest extends TestCase { - use ExpectDeprecationTrait; - public function testInvalidCheckPath() { $this->expectException(InvalidConfigurationException::class); diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index ba5a3f08850d8..1b2f57f979f52 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +7.0 +--- + + * Remove the `Twig_Environment` autowiring alias, use `Twig\Environment` instead + * Remove option `twig.autoescape`; create a class that implements your escaping strategy + (check `FileExtensionEscapingStrategy::guess()` for inspiration) and reference it using + the `twig.autoescape_service` option instead + 6.3 --- diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index 4712b18a6ac1b..e5e3310eeddb5 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -127,10 +127,6 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode): void $rootNode ->fixXmlConfig('path') ->children() - ->variableNode('autoescape') - ->defaultValue('name') - ->setDeprecated('symfony/twig-bundle', '6.1', 'Option "%node%" at "%path%" is deprecated, use autoescape_service[_method] instead.') - ->end() ->scalarNode('autoescape_service')->defaultNull()->end() ->scalarNode('autoescape_service_method')->defaultNull()->end() ->scalarNode('base_template_class')->example('Twig\Template')->cannotBeEmpty()->end() diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index f606e7ae4b591..73a069e5df7a9 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -150,6 +150,8 @@ public function load(array $configs, ContainerBuilder $container): void if (isset($config['autoescape_service']) && isset($config['autoescape_service_method'])) { $config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method']]; + } else { + $config['autoescape'] = 'name'; } $container->getDefinition('twig')->replaceArgument(1, array_intersect_key($config, [ diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd index 50eff2bc29923..05f949e943ab2 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd @@ -18,7 +18,6 @@ - diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php index 6525d875a5737..002d284f87727 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php @@ -66,9 +66,6 @@ ->tag('container.preload', ['class' => ExtensionSet::class]) ->tag('container.preload', ['class' => Template::class]) ->tag('container.preload', ['class' => TemplateWrapper::class]) - - ->alias('Twig_Environment', 'twig') - ->deprecate('symfony/twig-bundle', '6.3', 'The "%alias_id%" service alias is deprecated, use "'.Environment::class.'" or "twig" instead.') ->alias(Environment::class, 'twig') ->set('twig.app_variable', AppVariable::class) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index 094d5abba0637..51e2d1fee567b 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Require explicit argument when calling `NodeBuilder::setParent()` + 6.3 --- diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php index 7cda0bc7d8b1e..49b73c8045868 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php @@ -39,11 +39,8 @@ public function __construct() * * @return $this */ - public function setParent(ParentNodeDefinitionInterface $parent = null): static + public function setParent(?ParentNodeDefinitionInterface $parent): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->parent = $parent; return $this; diff --git a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php index dbd47e66de25c..dbc927b592041 100644 --- a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php +++ b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Config\Resource; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; /** @@ -191,13 +190,6 @@ private function generateSignature(\ReflectionClass $class): iterable yield print_r($class->name::getSubscribedEvents(), true); } - if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) { - yield MessageSubscriberInterface::class; - foreach ($class->name::getHandledMessages() as $key => $value) { - yield $key.print_r($value, true); - } - } - if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) { yield ServiceSubscriberInterface::class; yield print_r($class->name::getSubscribedServices(), true); diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index ef7a9b420fbdd..fa12c4cf78ca7 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Resource\ReflectionClassResource; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; class ReflectionClassResourceTest extends TestCase @@ -175,27 +174,6 @@ public function testEventSubscriber() $this->assertTrue($res->isFresh(0)); } - /** - * @group legacy - */ - public function testMessageSubscriber() - { - $res = new ReflectionClassResource(new \ReflectionClass(TestMessageSubscriber::class)); - $this->assertTrue($res->isFresh(0)); - - TestMessageSubscriberConfigHolder::$handledMessages = ['SomeMessageClass' => []]; - $this->assertFalse($res->isFresh(0)); - - $res = new ReflectionClassResource(new \ReflectionClass(TestMessageSubscriber::class)); - $this->assertTrue($res->isFresh(0)); - - TestMessageSubscriberConfigHolder::$handledMessages = ['OtherMessageClass' => []]; - $this->assertFalse($res->isFresh(0)); - - $res = new ReflectionClassResource(new \ReflectionClass(TestMessageSubscriber::class)); - $this->assertTrue($res->isFresh(0)); - } - public function testServiceSubscriber() { $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class)); @@ -232,22 +210,6 @@ public static function getSubscribedEvents(): array } } -if (interface_exists(MessageSubscriberInterface::class)) { - class TestMessageSubscriber implements MessageSubscriberInterface - { - public static function getHandledMessages(): iterable - { - foreach (TestMessageSubscriberConfigHolder::$handledMessages as $key => $subscribedMessage) { - yield $key => $subscribedMessage; - } - } - } - class TestMessageSubscriberConfigHolder - { - public static $handledMessages = []; - } -} - class TestServiceSubscriber implements ServiceSubscriberInterface { public static $subscribedServices = []; diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 1406d75f6970b..fe4425a9a2848 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -6,7 +6,7 @@ CHANGELOG * Add method `__toString()` to `InputInterface` * Remove `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead - * Passing null to `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()` and `Question::setAutocompleterCallback/setValidator()` must be done explicitly + * Require explicit argument when calling `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()` and `Question::setAutocompleterCallback/setValidator()` * Remove `StringInput::REGEX_STRING` 6.4 diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 48ba927063c77..6c1c60d776cce 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Console\Application; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -29,8 +28,6 @@ class CommandTest extends TestCase { - use ExpectDeprecationTrait; - protected static $fixturesPath; public static function setUpBeforeClass(): void diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index ef0925176bbf9..5ca14fd4c4a9b 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", "symfony/string": "^6.4|^7.0" diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index ad4e39a4524a3..e11f32348e2c8 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -8,7 +8,7 @@ CHANGELOG * Remove `ProxyHelper`, use `Symfony\Component\VarExporter\ProxyHelper` instead * Remove `ReferenceSetArgumentTrait` * Remove support of `@required` annotation, use the `Symfony\Contracts\Service\Attribute\Required` attribute instead - * Passing `null` to `ContainerAwareTrait::setContainer()` must be done explicitly + * Require explicit argument when calling `ContainerAwareTrait::setContainer()` * Remove `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`, use options `inline_factories` and `inline_class_loader` instead * Parameter names of `ParameterBag` cannot be numerics * Remove `ContainerAwareInterface` and `ContainerAwareTrait`, use dependency injection instead diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index 089da1e79e0fb..75726d3700d89 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -12,14 +12,12 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Contracts\Service\Attribute\SubscribedService; use Symfony\Contracts\Service\ServiceProviderInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; @@ -71,8 +69,6 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class)); } $class = $r->name; - // to remove when symfony/dependency-injection will stop being compatible with symfony/framework-bundle<6.0 - $replaceDeprecatedSession = $this->container->has('.session.deprecated') && $r->isSubclassOf(AbstractController::class); $subscriberMap = []; foreach ($class::getSubscribedServices() as $key => $type) { @@ -99,11 +95,6 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed if (!$autowire) { throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class)); } - if ($replaceDeprecatedSession && SessionInterface::class === $type) { - // This prevents triggering the deprecation when building the container - // to remove when symfony/dependency-injection will stop being compatible with symfony/framework-bundle<6.0 - $type = '.session.deprecated'; - } $serviceMap[$key] = new Reference($type); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php index 544322ba3348e..c67ce1994a91e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; @@ -38,8 +37,6 @@ class ResolveBindingsPassTest extends TestCase { - use ExpectDeprecationTrait; - public function testProcess() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/ErrorHandler/Resources/bin/patch-type-declarations b/src/Symfony/Component/ErrorHandler/Resources/bin/patch-type-declarations index f24c99689706b..5be1db42f6dca 100755 --- a/src/Symfony/Component/ErrorHandler/Resources/bin/patch-type-declarations +++ b/src/Symfony/Component/ErrorHandler/Resources/bin/patch-type-declarations @@ -19,7 +19,7 @@ if (\in_array('-h', $argv) || \in_array('--help', $argv)) { ' Patches type declarations based on "@return" PHPDoc and triggers deprecations for', ' incompatible method declarations.', '', - ' This assists you to make your package compatible with Symfony 6, but it can be used', + ' This assists you to make your package compatible with Symfony 7, but it can be used', ' for any class/package.', '', ' Available configuration via environment variables:', diff --git a/src/Symfony/Component/Form/Button.php b/src/Symfony/Component/Form/Button.php index 00373b3770452..67772ccfe1c6b 100644 --- a/src/Symfony/Component/Form/Button.php +++ b/src/Symfony/Component/Form/Button.php @@ -81,11 +81,8 @@ public function offsetUnset(mixed $offset): void throw new BadMethodCallException('Buttons cannot have children.'); } - public function setParent(FormInterface $parent = null): static + public function setParent(?FormInterface $parent): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if ($this->submitted) { throw new AlreadySubmittedException('You cannot set the parent of a submitted button.'); } diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php index 20a30968d402e..2c8c12ce23d45 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -220,12 +220,8 @@ public function setAttributes(array $attributes): static * * @throws BadMethodCallException */ - public function setDataMapper(DataMapperInterface $dataMapper = null): static + public function setDataMapper(?DataMapperInterface $dataMapper): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } - throw new BadMethodCallException('Buttons do not support data mappers.'); } diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 22597f3b47215..73c85c2271d51 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +7.0 +--- + + * Throw when using `DateTime` or `DateTimeImmutable` model data with a different timezone than configured with the + `model_timezone` option in `DateType`, `DateTimeType`, and `TimeType` + * Make the "widget" option of date/time form types default to "single_text" + * Require explicit argument when calling `Button/Form::setParent()`, `ButtonBuilder/FormConfigBuilder::setDataMapper()`, `TransformationFailedException::setInvalidMessage()` + 6.4 --- diff --git a/src/Symfony/Component/Form/Exception/TransformationFailedException.php b/src/Symfony/Component/Form/Exception/TransformationFailedException.php index 409b51517a674..ceb01f1a9a1b1 100644 --- a/src/Symfony/Component/Form/Exception/TransformationFailedException.php +++ b/src/Symfony/Component/Form/Exception/TransformationFailedException.php @@ -34,11 +34,8 @@ public function __construct(string $message = '', int $code = 0, \Throwable $pre * @param string|null $invalidMessage The message or message key * @param array $invalidMessageParameters Data to be passed into the translator */ - public function setInvalidMessage(string $invalidMessage = null, array $invalidMessageParameters = []): void + public function setInvalidMessage(?string $invalidMessage, array $invalidMessageParameters = []): void { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->invalidMessage = $invalidMessage; $this->invalidMessageParameters = $invalidMessageParameters; } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 9ec4c9cca4739..73ae5708c9236 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -206,8 +206,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ($date->getTimezone()->getName() !== $options['model_timezone']) { - trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); - // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', get_debug_type($date), $date->getTimezone()->getName(), $options['model_timezone'])); } }); } @@ -335,8 +334,7 @@ public function configureOptions(OptionsResolver $resolver) throw new LogicException(sprintf('Cannot use the "time_widget" option of the "%s" when the "widget" option is set to "single_text".', self::class)); } } elseif (null === $widget && null === $options['date_widget'] && null === $options['time_widget']) { - trigger_deprecation('symfony/form', '6.3', 'Not configuring the "widget" option of form type "datetime" is deprecated. It will default to "single_text" in Symfony 7.0.'); - // return 'single_text'; + return 'single_text'; } return $widget; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index 480afc315f2ad..d204a914bd5aa 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -190,8 +190,7 @@ class_exists(\IntlTimeZone::class, false) ? \IntlTimeZone::createDefault() : nul } if ($date->getTimezone()->getName() !== $options['model_timezone']) { - trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); - // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', get_debug_type($date), $date->getTimezone()->getName(), $options['model_timezone'])); } }); } @@ -286,11 +285,7 @@ public function configureOptions(OptionsResolver $resolver) 'years' => range((int) date('Y') - 5, (int) date('Y') + 5), 'months' => range(1, 12), 'days' => range(1, 31), - 'widget' => static function (Options $options) { - trigger_deprecation('symfony/form', '6.3', 'Not configuring the "widget" option of form type "date" is deprecated. It will default to "single_text" in Symfony 7.0.'); - - return 'choice'; - }, + 'widget' => 'single_text', 'input' => 'datetime', 'format' => $format, 'model_timezone' => null, diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index 623259f17a001..7788290d7a4ae 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -218,8 +218,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ($date->getTimezone()->getName() !== $options['model_timezone']) { - trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); - // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', get_debug_type($date), $date->getTimezone()->getName(), $options['model_timezone'])); } }); } @@ -327,11 +326,7 @@ public function configureOptions(OptionsResolver $resolver) 'hours' => range(0, 23), 'minutes' => range(0, 59), 'seconds' => range(0, 59), - 'widget' => static function (Options $options) { - trigger_deprecation('symfony/form', '6.3', 'Not configuring the "widget" option of form type "time" is deprecated. It will default to "single_text" in Symfony 7.0.'); - - return 'choice'; - }, + 'widget' => 'single_text', 'input' => 'datetime', 'input_format' => 'H:i:s', 'with_minutes' => true, diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index a4b76506a2f91..5c86d27b56f64 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -218,12 +218,8 @@ public function isDisabled(): bool return true; } - public function setParent(FormInterface $parent = null): static + public function setParent(?FormInterface $parent): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } - if ($this->submitted) { throw new AlreadySubmittedException('You cannot set the parent of a submitted form.'); } diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index 9fed3d1a0a5f4..29e643680e5b8 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -347,11 +347,8 @@ public function setAttributes(array $attributes): static /** * @return $this */ - public function setDataMapper(DataMapperInterface $dataMapper = null): static + public function setDataMapper(?DataMapperInterface $dataMapper): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index 71020a06b9b44..eb6538e6a6d7d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -11,14 +11,12 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; class DateTimeTypeTest extends BaseTypeTestCase { - use ExpectDeprecationTrait; - public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'; private $defaultLocale; @@ -751,28 +749,20 @@ public function testSubmitStringWithCustomInputFormat() $this->assertSame('14/01/2018 21:29:00 +00:00', $form->getData()); } - /** - * @group legacy - */ public function testDateTimeInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ 'model_timezone' => 'Europe/Berlin', ]); } - /** - * @group legacy - */ public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ 'input' => 'datetime_immutable', diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index bb171ffe88735..976836553e9ee 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\ChoiceList\View\ChoiceView; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -20,8 +20,6 @@ class DateTypeTest extends BaseTypeTestCase { - use ExpectDeprecationTrait; - public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateType'; private $defaultTimezone; @@ -1115,28 +1113,20 @@ public function testSubmitStringWithCustomInputFormat() $this->assertSame('14/01/2018', $form->getData()); } - /** - * @group legacy - */ public function testDateTimeInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ 'model_timezone' => 'Europe/Berlin', ]); } - /** - * @group legacy - */ public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ 'input' => 'datetime_immutable', diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index 3e8e42f4a8f7a..155657038f29e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\LogicException; @@ -21,8 +20,6 @@ class TimeTypeTest extends BaseTypeTestCase { - use ExpectDeprecationTrait; - public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TimeType'; public function testSubmitDateTime() @@ -1164,28 +1161,20 @@ public static function provideEmptyData() ]; } - /** - * @group legacy - */ public function testDateTimeInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ 'model_timezone' => 'Europe/Berlin', ]); } - /** - * @group legacy - */ public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() { - $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); - // $this->expectException(LogicException::class); - // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ 'input' => 'datetime_immutable', diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 7ee167817f352..914ddc6c52b32 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher": "^6.4|^7.0", "symfony/options-resolver": "^6.4|^7.0", "symfony/polyfill-ctype": "~1.8", diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 2d3669d2f0b17..ce2bdb638f0f1 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Remove classes `RequestMatcher` and `ExpressionRequestMatcher` * Remove `Request::getContentType()`, use `Request::getContentTypeFormat()` instead * Throw an `InvalidArgumentException` when calling `Request::create()` with a malformed URI + * Require explicit argument when calling `JsonResponse::setCallback()`, `Response::setExpires/setLastModified/setEtag()`, `MockArraySessionStorage/NativeSessionStorage::setMetadataBag()`, `NativeSessionStorage::setSaveHandler()` 6.4 --- diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 8dd250a369e55..62278b657ad9b 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -75,11 +75,8 @@ public static function fromJsonString(string $data, int $status = 200, array $he * * @throws \InvalidArgumentException When the callback name is not valid */ - public function setCallback(string $callback = null): static + public function setCallback(?string $callback): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if (null !== $callback) { // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ // partially taken from https://github.com/willdurand/JsonpCallbackValidator diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 8e09c46d46580..cff6fe40cc81f 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -761,11 +761,8 @@ public function getExpires(): ?\DateTimeImmutable * * @final */ - public function setExpires(\DateTimeInterface $date = null): static + public function setExpires(?\DateTimeInterface $date): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if (null === $date) { $this->headers->remove('Expires'); @@ -942,11 +939,8 @@ public function getLastModified(): ?\DateTimeImmutable * * @final */ - public function setLastModified(\DateTimeInterface $date = null): static + public function setLastModified(?\DateTimeInterface $date): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if (null === $date) { $this->headers->remove('Last-Modified'); @@ -980,11 +974,8 @@ public function getEtag(): ?string * * @final */ - public function setEtag(string $etag = null, bool $weak = false): static + public function setEtag(?string $etag, bool $weak = false): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if (null === $etag) { $this->headers->remove('Etag'); } else { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index d30b56d691ec0..65f06c69e4a3d 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -192,11 +192,8 @@ public function isStarted(): bool /** * @return void */ - public function setMetadataBag(MetadataBag $bag = null) + public function setMetadataBag(?MetadataBag $bag) { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->metadataBag = $bag ?? new MetadataBag(); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 7c6b6f9296c6f..e2e6f9f1f9d30 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -317,11 +317,8 @@ public function getBag(string $name): SessionBagInterface /** * @return void */ - public function setMetadataBag(MetadataBag $metaBag = null) + public function setMetadataBag(?MetadataBag $metaBag) { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->metadataBag = $metaBag ?? new MetadataBag(); } @@ -396,12 +393,8 @@ public function setOptions(array $options) * * @throws \InvalidArgumentException */ - public function setSaveHandler(AbstractProxy|\SessionHandlerInterface $saveHandler = null) + public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler) { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } - // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index ae25848cd590d..151c4133b92fd 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 3a15ecfd0d195..0f4e3482d137f 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * Remove `AbstractSurrogate::$phpEscapeMap` * Remove `HttpKernelInterface::MASTER_REQUEST` * Remove `terminate_on_cache_hit` option from `HttpCache` + * Require explicit argument when calling `ConfigDataCollector::setKernel()`, `RouterListener::setCurrentRequest()` 6.4 --- diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index b3e096d11e5d5..9cb77b4cadea2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -27,8 +26,6 @@ */ class HttpCacheTest extends HttpCacheTestCase { - use ExpectDeprecationTrait; - public function testTerminateDelegatesTerminationOnlyForTerminableInterface() { $storeMock = $this->getMockBuilder(StoreInterface::class) diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 92cb6fcbbf985..3417565755f5c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\HttpKernel\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json index f9d53d036c667..ee8426dd3b69b 100644 --- a/src/Symfony/Component/Lock/composer.json +++ b/src/Symfony/Component/Lock/composer.json @@ -17,8 +17,7 @@ ], "require": { "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3" + "psr/log": "^1|^2|^3" }, "require-dev": { "doctrine/dbal": "^3.6", diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes deleted file mode 100644 index 84c7add058fb5..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore deleted file mode 100644 index c49a5d8df5c65..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md deleted file mode 100644 index e2bc1aafc7c37..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -CHANGELOG -========= - -6.2 ---- - - * Deprecate the bridge in favor of the MailPace bridge - -5.4 ---- - - * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE deleted file mode 100644 index 99c6bdf356ee7..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md deleted file mode 100644 index c0f421db0605a..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md +++ /dev/null @@ -1,25 +0,0 @@ -OhMySMTP Bridge -=============== - -Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. - -Configuration example: - -```env -# SMTP -MAILER_DSN=ohmysmtp+smtp://API_TOKEN@default - -# API -MAILER_DSN=ohmysmtp+api://API_TOKEN@default -``` - -where: - - `API_TOKEN` is your OhMySMTP API Token - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php deleted file mode 100644 index d7f7285cf4bc7..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php +++ /dev/null @@ -1,164 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\ResponseInterface; - -/** - * @group legacy - */ -final class OhMySmtpApiTransportTest extends TestCase -{ - /** - * @dataProvider getTransportData - */ - public function testToString(OhMySmtpApiTransport $transport, string $expected) - { - $this->assertSame($expected, (string) $transport); - } - - public static function getTransportData(): array - { - return [ - [ - new OhMySmtpApiTransport('KEY'), - 'ohmysmtp+api://app.ohmysmtp.com/api/v1', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), - 'ohmysmtp+api://example.com', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), - 'ohmysmtp+api://example.com:99', - ], - ]; - } - - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayHasKey('Headers', $payload); - $this->assertCount(1, $payload['Headers']); - - $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); - } - - public function testSend() - { - $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { - $this->assertSame('POST', $method); - $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); - $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); - - $body = json_decode($options['body'], true); - $this->assertSame('"Fabien" ', $body['from']); - $this->assertSame('"Saif Eddin" ', $body['to']); - $this->assertSame('Hello!', $body['subject']); - $this->assertSame('Hello There!', $body['textbody']); - - return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ - 'http_code' => 200, - ]); - }); - - $transport = new OhMySmtpApiTransport('KEY', $client); - - $mail = new Email(); - $mail->subject('Hello!') - ->to(new Address('saif.gmati@symfony.com', 'Saif Eddin')) - ->from(new Address('fabpot@symfony.com', 'Fabien')) - ->text('Hello There!'); - - $message = $transport->send($mail); - - $this->assertSame('foobar', $message->getMessageId()); - } - - public function testSendThrowsForErrorResponse() - { - $client = new MockHttpClient(static fn (string $method, string $url, array $options): ResponseInterface => new MockResponse(json_encode(['error' => 'i\'m a teapot']), [ - 'http_code' => 418, - 'response_headers' => [ - 'content-type' => 'application/json', - ], - ])); - $transport = new OhMySmtpApiTransport('KEY', $client); - $transport->setPort(8984); - - $mail = new Email(); - $mail->subject('Hello!') - ->to(new Address('saif.gmati@symfony.com', 'Saif Eddin')) - ->from(new Address('fabpot@symfony.com', 'Fabien')) - ->text('Hello There!'); - - $this->expectException(HttpTransportException::class); - $this->expectExceptionMessage('Unable to send an email: {"error":"i\'m a teapot"}'); - $transport->send($mail); - } - - public function testSendThrowsForMultipleErrorResponses() - { - $client = new MockHttpClient(static fn (string $method, string $url, array $options): ResponseInterface => new MockResponse(json_encode(['errors' => ['to' => 'undefined field']]), [ - 'http_code' => 418, - 'response_headers' => [ - 'content-type' => 'application/json', - ], - ])); - $transport = new OhMySmtpApiTransport('KEY', $client); - $transport->setPort(8984); - - $mail = new Email(); - $mail->subject('Hello!') - ->to(new Address('saif.gmati@symfony.com', 'Saif Eddin')) - ->from(new Address('fabpot@symfony.com', 'Fabien')) - ->text('Hello There!'); - - $this->expectException(HttpTransportException::class); - $this->expectExceptionMessage('Unable to send an email: {"errors":{"to":"undefined field"}}'); - $transport->send($mail); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayNotHasKey('Headers', $payload); - $this->assertArrayHasKey('tags', $payload); - - $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php deleted file mode 100644 index edbd50662f991..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Email; - -/** - * @group legacy - */ -final class OhMySmtpSmtpTransportTest extends TestCase -{ - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->invoke($transport, $email); - - $this->assertCount(1, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->invoke($transport, $email); - - $this->assertCount(2, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php deleted file mode 100644 index 503f0410791d0..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use Psr\Log\NullLogger; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; -use Symfony\Component\Mailer\Test\TransportFactoryTestCase; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportFactoryInterface; - -/** - * @group legacy - */ -final class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase -{ - public function getFactory(): TransportFactoryInterface - { - return new OhMySmtpTransportFactory(null, new MockHttpClient(), new NullLogger()); - } - - public static function supportsProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+api', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'example.com'), - true, - ]; - } - - public static function createProvider(): iterable - { - $logger = new NullLogger(); - - yield [ - new Dsn('ohmysmtp+api', 'default', self::USER), - new OhMySmtpApiTransport(self::USER, new MockHttpClient(), null, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), - (new OhMySmtpApiTransport(self::USER, new MockHttpClient(), null, $logger))->setHost('example.com')->setPort(8080), - ]; - - yield [ - new Dsn('ohmysmtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, null, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, null, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, null, $logger), - ]; - } - - public static function unsupportedSchemeProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+foo', 'default', self::USER), - 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', - ]; - } - - public static function incompleteDsnProvider(): iterable - { - yield [new Dsn('ohmysmtp+api', 'default')]; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php deleted file mode 100644 index 9d749c75e0a63..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php +++ /dev/null @@ -1,147 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceApiTransport; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\AbstractApiTransport; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; -use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\HttpClient\ResponseInterface; - -trigger_deprecation('symfony/oh-my-smtp-mailer', '6.2', 'The "%s" class is deprecated, use "%s" instead.', OhMySmtpApiTransport::class, MailPaceApiTransport::class); - -/** - * @author Paul Oms - * - * @deprecated since Symfony 6.2, use MailPaceApiTransport instead - */ -final class OhMySmtpApiTransport extends AbstractApiTransport -{ - private const HOST = 'app.ohmysmtp.com/api/v1'; - - private string $key; - - public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - $this->key = $key; - - parent::__construct($client, $dispatcher, $logger); - } - - public function __toString(): string - { - return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); - } - - protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface - { - $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ - 'headers' => [ - 'Accept' => 'application/json', - 'OhMySMTP-Server-Token' => $this->key, - 'Content-Type' => 'application/json', - 'User-Agent' => 'OhMySMTP Symfony Mailer', - ], - 'json' => $this->getPayload($email, $envelope), - ]); - - try { - $statusCode = $response->getStatusCode(); - $result = $response->toArray(false); - } catch (DecodingExceptionInterface) { - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); - } catch (TransportExceptionInterface $e) { - throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); - } - - if (200 !== $statusCode) { - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false), $response); - } - - $sentMessage->setMessageId($result['id']); - - return $response; - } - - private function getPayload(Email $email, Envelope $envelope): array - { - $payload = [ - 'from' => $envelope->getSender()->toString(), - 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), - 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), - 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), - 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), - 'subject' => $email->getSubject(), - 'textbody' => $email->getTextBody(), - 'htmlbody' => $email->getHtmlBody(), - 'attachments' => $this->getAttachments($email), - 'tags' => [], - ]; - - $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; - - foreach ($email->getHeaders()->all() as $name => $header) { - if (\in_array($name, $headersToBypass, true)) { - continue; - } - - if ($header instanceof TagHeader) { - $payload['tags'][] = $header->getValue(); - continue; - } - - $payload['Headers'][] = [ - 'Name' => $header->getName(), - 'Value' => $header->getBodyAsString(), - ]; - } - - return $payload; - } - - private function getAttachments(Email $email): array - { - $attachments = []; - foreach ($email->getAttachments() as $attachment) { - $headers = $attachment->getPreparedHeaders(); - $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); - $disposition = $headers->getHeaderBody('Content-Disposition'); - - $att = [ - 'name' => $filename, - 'content' => $attachment->bodyToString(), - 'content_type' => $headers->get('Content-Type')->getBody(), - ]; - - if ('inline' === $disposition) { - $att['cid'] = 'cid:'.$filename; - } - - $attachments[] = $att; - } - - return $attachments; - } - - private function getEndpoint(): ?string - { - return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php deleted file mode 100644 index 09b5fdd4fac09..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceSmtpTransport; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; -use Symfony\Component\Mime\Message; -use Symfony\Component\Mime\RawMessage; - -trigger_deprecation('symfony/oh-my-smtp-mailer', '6.2', 'The "%s" class is deprecated, use "%s" instead.', OhMySmtpSmtpTransport::class, MailPaceSmtpTransport::class); - -/** - * @author Paul Oms - * - * @deprecated since Symfony 6.2, use MailPaceSmtpTransport instead - */ -final class OhMySmtpSmtpTransport extends EsmtpTransport -{ - public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); - - $this->setUsername($id); - $this->setPassword($id); - } - - public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage - { - if ($message instanceof Message) { - $this->addOhMySmtpHeaders($message); - } - - return parent::send($message, $envelope); - } - - private function addOhMySmtpHeaders(Message $message): void - { - $headers = $message->getHeaders(); - - foreach ($headers->all() as $name => $header) { - if ($header instanceof TagHeader) { - if (null != $headers->get('X-OMS-Tags')) { - $existing = $headers->get('X-OMS-Tags')->getBody(); - $headers->remove('X-OMS-Tags'); - $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); - } else { - $headers->addTextHeader('X-OMS-Tags', $header->getValue()); - } - $headers->remove($name); - } - } - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php deleted file mode 100644 index 62c2b24e7cdc9..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; -use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; -use Symfony\Component\Mailer\Transport\AbstractTransportFactory; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportInterface; - -/** - * @author Paul Oms - * - * @deprecated since Symfony 6.2, use MailPaceTransportFactory instead - */ -final class OhMySmtpTransportFactory extends AbstractTransportFactory -{ - public function create(Dsn $dsn): TransportInterface - { - trigger_deprecation('symfony/oh-my-smtp-mailer', '6.2', 'The "%s" class is deprecated, use "%s" instead.', self::class, MailPaceTransportFactory::class); - - $scheme = $dsn->getScheme(); - - if ('ohmysmtp+api' === $scheme) { - $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); - $port = $dsn->getPort(); - - return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); - } - - if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { - return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); - } - - throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); - } - - protected function getSupportedSchemes(): array - { - return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json deleted file mode 100644 index a11f305c24ebe..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/oh-my-smtp-mailer", - "type": "symfony-mailer-bridge", - "description": "Symfony OhMySMTP Mailer Bridge", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Paul Oms", - "homepage": "https://ohmysmtp.com" - } - ], - "require": { - "php": ">=8.2", - "psr/event-dispatcher": "^1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/mailer": "^6.4|^7.0" - }, - "require-dev": { - "symfony/http-client": "^6.4|^7.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist deleted file mode 100644 index 706e4cf3c1339..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Resources - ./Tests - ./vendor - - - - diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md index 291125f3aec32..3ac8882d352bb 100644 --- a/src/Symfony/Component/Mailer/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove the OhMySmtp bridge in favor of the MailPace bridge + 6.3 --- diff --git a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php index b0612b23808fe..8f87fe18f1af6 100644 --- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php @@ -44,10 +44,6 @@ class UnsupportedSchemeException extends LogicException 'class' => Bridge\Mailchimp\Transport\MandrillTransportFactory::class, 'package' => 'symfony/mailchimp-mailer', ], - 'ohmysmtp' => [ - 'class' => Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class, - 'package' => 'symfony/oh-my-smtp-mailer', - ], 'postmark' => [ 'class' => Bridge\Postmark\Transport\PostmarkTransportFactory::class, 'package' => 'symfony/postmark-mailer', diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index 5dcf0f1bbfd7c..430ca774f4b02 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -20,7 +20,6 @@ use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -42,7 +41,6 @@ public static function setUpBeforeClass(): void MailgunTransportFactory::class => false, MailjetTransportFactory::class => false, MandrillTransportFactory::class => false, - OhMySmtpTransportFactory::class => false, PostmarkTransportFactory::class => false, SendgridTransportFactory::class => false, SendinblueTransportFactory::class => false, @@ -71,7 +69,6 @@ public static function messageWhereSchemeIsPartOfSchemeToPackageMapProvider(): \ yield ['mailgun', 'symfony/mailgun-mailer']; yield ['mailjet', 'symfony/mailjet-mailer']; yield ['mandrill', 'symfony/mailchimp-mailer']; - yield ['ohmysmtp', 'symfony/oh-my-smtp-mailer']; yield ['postmark', 'symfony/postmark-mailer']; yield ['sendgrid', 'symfony/sendgrid-mailer']; yield ['sendinblue', 'symfony/sendinblue-mailer']; diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index 2c6fdd5505e70..ea404095ed50a 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -20,7 +20,6 @@ use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -51,7 +50,6 @@ final class Transport MailgunTransportFactory::class, MailjetTransportFactory::class, MandrillTransportFactory::class, - OhMySmtpTransportFactory::class, PostmarkTransportFactory::class, SendgridTransportFactory::class, SendinblueTransportFactory::class, diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsTransportTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsTransportTest.php index 541b543f699d0..0b874e06941bc 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsTransportTest.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsTransportTest.php @@ -53,7 +53,6 @@ class AmazonSqsTransportTest extends TestCase protected function setUp(): void { $this->connection = $this->createMock(Connection::class); - // Mocking the concrete receiver class because mocking multiple interfaces is deprecated $this->receiver = $this->createMock(AmazonSqsReceiver::class); $this->sender = $this->createMock(SenderInterface::class); diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index a92c40183ea8b..4f410f97cb1a9 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -5,6 +5,13 @@ CHANGELOG --- * Add parameter `$isSameDatabase` to `DoctrineTransport::configureSchema()` + * Remove `MessageHandlerInterface` and `MessageSubscriberInterface`, use `#[AsMessageHandler]` instead + * Remove `StopWorkerOnSigtermSignalListener` in favor of + `StopWorkerOnSignalsListener` and make it configurable with SIGINT and + * Remove `Symfony\Component\Messenger\Transport\InMemoryTransport` and + `Symfony\Component\Messenger\Transport\InMemoryTransportFactory` in favor of + `Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport` and + `Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory` 6.3 --- diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php index 03f48edfcd93a..f6f26d6946de2 100644 --- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php +++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php @@ -20,11 +20,8 @@ use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\Handler\HandlerDescriptor; use Symfony\Component\Messenger\Handler\HandlersLocator; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; use Symfony\Component\Messenger\TraceableMessageBus; use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface; @@ -109,9 +106,7 @@ private function registerHandlers(ContainerBuilder $container, array $busIds): v if (isset($options['bus'])) { if (!\in_array($options['bus'], $busIds)) { - // @deprecated since Symfony 6.2, in 7.0 change to: - // $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); - $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : ($r->implementsInterface(MessageSubscriberInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method)); + $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); throw new RuntimeException(sprintf('Invalid configuration '.$messageLocation.' for message "%s": bus "%s" does not exist.', $message, $options['bus'])); } @@ -120,9 +115,7 @@ private function registerHandlers(ContainerBuilder $container, array $busIds): v } if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { - // @deprecated since Symfony 6.2, in 7.0 change to: - // $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); - $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : ($r->implementsInterface(MessageSubscriberInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method)); + $messageLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); throw new RuntimeException(sprintf('Invalid handler service "%s": class or interface "%s" '.$messageLocation.' not found.', $serviceId, $message)); } @@ -147,7 +140,7 @@ private function registerHandlers(ContainerBuilder $container, array $busIds): v } if (null === $message) { - throw new RuntimeException(sprintf('Invalid handler service "%s": method "%s::getHandledMessages()" must return one or more messages.', $serviceId, $r->getName())); + throw new RuntimeException(sprintf('Invalid handler service "%s": the list of messages to handle is empty.', $serviceId, $r->getName())); } } } @@ -203,16 +196,6 @@ private function registerHandlers(ContainerBuilder $container, array $busIds): v private function guessHandledClasses(\ReflectionClass $handlerClass, string $serviceId, string $methodName): iterable { - if ($handlerClass->implementsInterface(MessageSubscriberInterface::class)) { - trigger_deprecation('symfony/messenger', '6.2', 'Implementing "%s" is deprecated, use the "%s" attribute instead.', MessageSubscriberInterface::class, AsMessageHandler::class); - - return $handlerClass->getName()::getHandledMessages(); - } - - if ($handlerClass->implementsInterface(MessageHandlerInterface::class)) { - trigger_deprecation('symfony/messenger', '6.2', 'Implementing "%s" is deprecated, use the "%s" attribute instead.', MessageHandlerInterface::class, AsMessageHandler::class); - } - try { $method = $handlerClass->getMethod($methodName); } catch (\ReflectionException) { diff --git a/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php b/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php deleted file mode 100644 index eeddf7d5fc675..0000000000000 --- a/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\EventListener; - -trigger_deprecation('symfony/messenger', '6.3', '"%s" is deprecated, use "%s" instead.', StopWorkerOnSigtermSignalListener::class, StopWorkerOnSignalsListener::class); - -use Psr\Log\LoggerInterface; - -/** - * @author Tobias Schultze - * - * @deprecated since Symfony 6.3, use the StopWorkerOnSignalsListener instead - */ -class StopWorkerOnSigtermSignalListener extends StopWorkerOnSignalsListener -{ - public function __construct(LoggerInterface $logger = null) - { - parent::__construct([SIGTERM], $logger); - } -} diff --git a/src/Symfony/Component/Messenger/Handler/MessageHandlerInterface.php b/src/Symfony/Component/Messenger/Handler/MessageHandlerInterface.php deleted file mode 100644 index 80d510cecde0c..0000000000000 --- a/src/Symfony/Component/Messenger/Handler/MessageHandlerInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\Handler; - -use Symfony\Component\Messenger\Attribute\AsMessageHandler; - -/** - * Marker interface for message handlers. - * - * @author Samuel Roze - * - * @deprecated since Symfony 6.2, use the {@see AsMessageHandler} attribute instead - */ -interface MessageHandlerInterface -{ -} diff --git a/src/Symfony/Component/Messenger/Handler/MessageSubscriberInterface.php b/src/Symfony/Component/Messenger/Handler/MessageSubscriberInterface.php deleted file mode 100644 index d24fc6b1dc4b1..0000000000000 --- a/src/Symfony/Component/Messenger/Handler/MessageSubscriberInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\Handler; - -use Symfony\Component\Messenger\Attribute\AsMessageHandler; - -/** - * Handlers can implement this interface to handle multiple messages. - * - * @author Samuel Roze - * - * @deprecated since Symfony 6.2, use the {@see AsMessageHandler} attribute instead - */ -interface MessageSubscriberInterface extends MessageHandlerInterface -{ - /** - * Returns a list of messages to be handled. - * - * It returns a list of messages like in the following example: - * - * yield MyMessage::class; - * - * It can also change the priority per classes. - * - * yield FirstMessage::class => ['priority' => 0]; - * yield SecondMessage::class => ['priority' => -10]; - * - * It can also specify a method, a priority, a bus and/or a transport per message: - * - * yield FirstMessage::class => ['method' => 'firstMessageMethod']; - * yield SecondMessage::class => [ - * 'method' => 'secondMessageMethod', - * 'priority' => 20, - * 'bus' => 'my_bus_name', - * 'from_transport' => 'your_transport_name', - * ]; - * - * The benefit of using `yield` instead of returning an array is that you can `yield` multiple times the - * same key and therefore subscribe to the same message multiple times with different options. - * - * The `__invoke` method of the handler will be called as usual with the message to handle. - */ - public static function getHandledMessages(): iterable; -} diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php index 226c8d71fb27a..4cc283bca94f3 100644 --- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php +++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php @@ -34,8 +34,6 @@ use Symfony\Component\Messenger\DependencyInjection\MessengerPass; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Handler\HandlersLocator; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; use Symfony\Component\Messenger\Middleware\MiddlewareInterface; @@ -152,19 +150,6 @@ public function testHandledMessageTypeResolvedWithMethodAndNoHandlesViaTagAttrib public function testTaggedMessageHandler() { $container = $this->getContainerBuilder($busId = 'message_bus'); - $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \ReflectionClass|\ReflectionMethod $reflector): void { - $tagAttributes = get_object_vars($attribute); - $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; - unset($tagAttributes['fromTransport']); - if ($reflector instanceof \ReflectionMethod) { - if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); - } - $tagAttributes['method'] = $reflector->getName(); - } - - $definition->addTag('messenger.message_handler', $tagAttributes); - }); $container ->register(TaggedDummyHandler::class, TaggedDummyHandler::class) ->setAutoconfigured(true) @@ -192,19 +177,6 @@ public function testTaggedMessageHandler() public function testTaggedMessageHandlerWithUnionTypes() { $container = $this->getContainerBuilder($busId = 'message_bus'); - $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \ReflectionClass|\ReflectionMethod $reflector): void { - $tagAttributes = get_object_vars($attribute); - $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; - unset($tagAttributes['fromTransport']); - if ($reflector instanceof \ReflectionMethod) { - if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); - } - $tagAttributes['method'] = $reflector->getName(); - } - - $definition->addTag('messenger.message_handler', $tagAttributes); - }); $container ->register(TaggedDummyHandlerWithUnionTypes::class, TaggedDummyHandlerWithUnionTypes::class) ->setAutoconfigured(true) @@ -309,22 +281,20 @@ public function testProcessTagWithUnknownBus() (new MessengerPass())->process($container); } - /** - * @group legacy - */ - public function testGetClassesFromTheHandlerSubscriberInterface() + public function testGetClassesFromTheAttribute() { $container = $this->getContainerBuilder($busId = 'message_bus'); $container ->register(HandlerWithMultipleMessages::class, HandlerWithMultipleMessages::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; $container ->register(PrioritizedHandler::class, PrioritizedHandler::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; - $this->expectDeprecation('Since symfony/messenger 6.2: Implementing "Symfony\Component\Messenger\Handler\MessageSubscriberInterface" is deprecated, use the "Symfony\Component\Messenger\Attribute\AsMessageHandler" attribute instead.'); + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0); @@ -336,21 +306,20 @@ public function testGetClassesFromTheHandlerSubscriberInterface() $this->assertHandlerDescriptor($container, $handlersMapping, SecondMessage::class, [PrioritizedHandler::class, HandlerWithMultipleMessages::class], [['priority' => 10]]); } - /** - * @group legacy - */ - public function testGetClassesAndMethodsAndPrioritiesFromTheSubscriber() + public function testGetClassesAndMethodsAndPrioritiesFromTheAttribute() { $container = $this->getContainerBuilder($busId = 'message_bus'); $container ->register(HandlerMappingMethods::class, HandlerMappingMethods::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; $container ->register(PrioritizedHandler::class, PrioritizedHandler::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0); @@ -418,9 +387,6 @@ public function testThrowsExceptionIfTheHandlerClassDoesNotExist() (new MessengerPass())->process($container); } - /** - * @group legacy - */ public function testThrowsExceptionIfTheHandlerMethodDoesNotExist() { $this->expectException(RuntimeException::class); @@ -429,9 +395,11 @@ public function testThrowsExceptionIfTheHandlerMethodDoesNotExist() $container->register('message_bus', MessageBusInterface::class)->addTag('messenger.bus'); $container ->register(HandlerMappingWithNonExistentMethod::class, HandlerMappingWithNonExistentMethod::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); } @@ -492,39 +460,6 @@ public function testItSetsTheReceiverNamesOnTheSetupTransportsCommand() $this->assertSame(['amqp', 'dummy'], $container->getDefinition('console.command.messenger_setup_transports')->getArgument(1)); } - /** - * @group legacy - */ - public function testItShouldNotThrowIfGeneratorIsReturnedInsteadOfArray() - { - $container = $this->getContainerBuilder($busId = 'message_bus'); - $container - ->register(HandlerWithGenerators::class, HandlerWithGenerators::class) - ->addTag('messenger.message_handler') - ; - - (new MessengerPass())->process($container); - - $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0); - - $this->assertHandlerDescriptor( - $container, - $handlersMapping, - DummyMessage::class, - [[HandlerWithGenerators::class, 'dummyMethod']] - ); - - $this->assertHandlerDescriptor( - $container, - $handlersMapping, - SecondMessage::class, - [[HandlerWithGenerators::class, 'secondMessage']] - ); - } - - /** - * @group legacy - */ public function testItRegistersHandlersOnDifferentBuses() { $container = $this->getContainerBuilder($eventsBusId = 'event_bus'); @@ -532,8 +467,11 @@ public function testItRegistersHandlersOnDifferentBuses() $container ->register(HandlerOnSpecificBuses::class, HandlerOnSpecificBuses::class) - ->addTag('messenger.message_handler'); + ->setAutoconfigured(true) + ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); $eventsHandlerMapping = $container->getDefinition($eventsBusId.'.messenger.handlers_locator')->getArgument(0); @@ -557,19 +495,18 @@ public function testItRegistersHandlersOnDifferentBuses() ); } - /** - * @group legacy - */ public function testItThrowsAnExceptionOnUnknownBus() { $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Invalid configuration returned by method "Symfony\Component\Messenger\Tests\DependencyInjection\HandlerOnUndefinedBus::getHandledMessages()" for message "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage": bus "some_undefined_bus" does not exist.'); + $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\HandlerOnUndefinedBus": bus "some_undefined_bus" specified on the tag "messenger.message_handler" does not exist (known ones are: "message_bus").'); $container = $this->getContainerBuilder(); $container ->register(HandlerOnUndefinedBus::class, HandlerOnUndefinedBus::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); } @@ -586,35 +523,18 @@ public function testUndefinedMessageClassForHandler() (new MessengerPass())->process($container); } - /** - * @group legacy - */ - public function testUndefinedMessageClassForHandlerImplementingMessageHandlerInterface() + public function testUndefinedMessageClassForHandlerViaAttribute() { $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface::__invoke()" not found.'); + $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaAttribute": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaAttribute::__invoke()" not found.'); $container = $this->getContainerBuilder(); $container - ->register(UndefinedMessageHandlerViaHandlerInterface::class, UndefinedMessageHandlerViaHandlerInterface::class) - ->addTag('messenger.message_handler') - ; - - (new MessengerPass())->process($container); - } - - /** - * @group legacy - */ - public function testUndefinedMessageClassForHandlerImplementingMessageSubscriberInterface() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" returned by method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface::getHandledMessages()" not found.'); - $container = $this->getContainerBuilder(); - $container - ->register(UndefinedMessageHandlerViaSubscriberInterface::class, UndefinedMessageHandlerViaSubscriberInterface::class) - ->addTag('messenger.message_handler') + ->register(UndefinedMessageHandlerViaAttribute::class, UndefinedMessageHandlerViaAttribute::class) + ->setAutoconfigured(true) ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); (new MessengerPass())->process($container); } @@ -701,19 +621,20 @@ public function testUnionBuiltinArgumentTypeHandler() (new MessengerPass())->process($container); } - /** - * @group legacy - */ public function testNeedsToHandleAtLeastOneMessage() { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\HandleNoMessageHandler": method "Symfony\Component\Messenger\Tests\DependencyInjection\HandleNoMessageHandler::getHandledMessages()" must return one or more messages.'); $container = $this->getContainerBuilder(); $container ->register(HandleNoMessageHandler::class, HandleNoMessageHandler::class) - ->addTag('messenger.message_handler') + ->setAutoconfigured(true) ; + (new AttributeAutoconfigurationPass())->process($container); + (new ResolveInstanceofConditionalsPass())->process($container); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\HandleNoMessageHandler": method "Symfony\Component\Messenger\Tests\DependencyInjection\HandleNoMessageHandler::__invoke()" requires at least one argument, first one being the message it handles.'); + (new MessengerPass())->process($container); } @@ -739,7 +660,7 @@ public function testRegistersMiddlewareFromServices() $container->setParameter($middlewareParameter = $fooBusId.'.middleware', [ ['id' => UselessMiddleware::class], - ['id' => 'middleware_with_factory', 'arguments' => $factoryChildMiddlewareArgs1 = ['index_0' => 'foo', 'bar']], + ['id' => 'middleware_with_factory', 'arguments' => ['index_0' => 'foo', 'bar']], ['id' => 'middleware_with_factory', 'arguments' => $factoryChildMiddlewareArgs2 = ['index_0' => 'baz']], ['id' => 'middleware_with_factory_using_default'], ]); @@ -788,7 +709,7 @@ public function testCannotRegistersAnUndefinedMiddleware() $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Invalid middleware: service "not_defined_middleware" not found.'); $container = $this->getContainerBuilder($fooBusId = 'messenger.bus.foo'); - $container->setParameter($middlewareParameter = $fooBusId.'.middleware', [ + $container->setParameter($fooBusId.'.middleware', [ ['id' => 'not_defined_middleware', 'arguments' => []], ]); @@ -801,7 +722,7 @@ public function testMiddlewareFactoryDefinitionMustBeAbstract() $this->expectExceptionMessage('Invalid middleware factory "not_an_abstract_definition": a middleware factory must be an abstract definition.'); $container = $this->getContainerBuilder($fooBusId = 'messenger.bus.foo'); $container->register('not_an_abstract_definition', UselessMiddleware::class); - $container->setParameter($middlewareParameter = $fooBusId.'.middleware', [ + $container->setParameter($fooBusId.'.middleware', [ ['id' => 'not_an_abstract_definition', 'arguments' => ['foo']], ]); @@ -862,6 +783,20 @@ private function getContainerBuilder(string $busId = 'message_bus'): ContainerBu ->addArgument(new Reference('service_container')) ; + $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \ReflectionClass|\ReflectionMethod $reflector): void { + $tagAttributes = get_object_vars($attribute); + $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; + unset($tagAttributes['fromTransport']); + if ($reflector instanceof \ReflectionMethod) { + if (isset($tagAttributes['method'])) { + throw new LogicException(sprintf('AsMessageHandler attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); + } + $tagAttributes['method'] = $reflector->getName(); + } + + $definition->addTag('messenger.message_handler', $tagAttributes); + }); + return $container; } @@ -958,25 +893,14 @@ public function __invoke(UndefinedMessage $message) } } -class UndefinedMessageHandlerViaHandlerInterface implements MessageHandlerInterface +#[AsMessageHandler] +class UndefinedMessageHandlerViaAttribute { public function __invoke(UndefinedMessage $message) { } } -class UndefinedMessageHandlerViaSubscriberInterface implements MessageSubscriberInterface -{ - public static function getHandledMessages(): iterable - { - return [UndefinedMessage::class]; - } - - public function __invoke() - { - } -} - class NotInvokableHandler { } @@ -1002,114 +926,66 @@ public function __invoke(string $message) } } -class HandlerWithMultipleMessages implements MessageSubscriberInterface +#[AsMessageHandler(handles: DummyMessage::class)] +#[AsMessageHandler(handles: SecondMessage::class)] +class HandlerWithMultipleMessages { - public static function getHandledMessages(): iterable - { - return [ - DummyMessage::class, - SecondMessage::class, - ]; - } - - public function __invoke() + public function __invoke($message) { } } -class PrioritizedHandler implements MessageSubscriberInterface +#[AsMessageHandler(handles: SecondMessage::class, priority: 10)] +class PrioritizedHandler { - public static function getHandledMessages(): iterable - { - yield SecondMessage::class => ['priority' => 10]; - } - - public function __invoke() + public function __invoke(SecondMessage $message) { } } -class HandlerMappingMethods implements MessageSubscriberInterface +#[AsMessageHandler(handles: DummyMessage::class, method: 'dummyMethod')] +#[AsMessageHandler(handles: SecondMessage::class, method: 'secondMessage', priority: 20)] +class HandlerMappingMethods { - public static function getHandledMessages(): iterable - { - yield DummyMessage::class => 'dummyMethod'; - yield SecondMessage::class => ['method' => 'secondMessage', 'priority' => 20]; - } - - public function dummyMethod() + public function dummyMethod(DummyMessage $message) { } - public function secondMessage() + public function secondMessage(SecondMessage $message) { } } -class HandlerMappingWithNonExistentMethod implements MessageSubscriberInterface +#[AsMessageHandler(handles: DummyMessage::class, method: 'dummyMethod')] +class HandlerMappingWithNonExistentMethod { - public static function getHandledMessages(): iterable - { - return [ - DummyMessage::class => 'dummyMethod', - ]; - } } -class HandleNoMessageHandler implements MessageSubscriberInterface +#[AsMessageHandler] +class HandleNoMessageHandler { - public static function getHandledMessages(): iterable - { - return []; - } - public function __invoke() { } } -class HandlerWithGenerators implements MessageSubscriberInterface +#[AsMessageHandler(handles: DummyMessage::class, method: 'dummyMethodForEvents', bus: 'event_bus')] +#[AsMessageHandler(handles: DummyMessage::class, method: 'dummyMethodForCommands', bus: 'command_bus')] +class HandlerOnSpecificBuses { - public static function getHandledMessages(): iterable - { - yield DummyMessage::class => 'dummyMethod'; - yield SecondMessage::class => 'secondMessage'; - } - - public function dummyMethod() + public function dummyMethodForEvents(DummyMessage $message) { } - public function secondMessage() + public function dummyMethodForCommands(DummyMessage $message) { } } -class HandlerOnSpecificBuses implements MessageSubscriberInterface +#[AsMessageHandler(handles: DummyMessage::class, bus: 'some_undefined_bus', method: 'dummyMethodForSomeBus')] +class HandlerOnUndefinedBus { - public static function getHandledMessages(): iterable - { - yield DummyMessage::class => ['method' => 'dummyMethodForEvents', 'bus' => 'event_bus']; - yield DummyMessage::class => ['method' => 'dummyMethodForCommands', 'bus' => 'command_bus']; - } - - public function dummyMethodForEvents() - { - } - - public function dummyMethodForCommands() - { - } -} - -class HandlerOnUndefinedBus implements MessageSubscriberInterface -{ - public static function getHandledMessages(): iterable - { - yield DummyMessage::class => ['method' => 'dummyMethodForSomeBus', 'bus' => 'some_undefined_bus']; - } - - public function dummyMethodForSomeBus() + public function dummyMethodForSomeBus(DummyMessage $message) { } } diff --git a/src/Symfony/Component/Messenger/Transport/InMemoryTransport.php b/src/Symfony/Component/Messenger/Transport/InMemoryTransport.php deleted file mode 100644 index a8941b00b67ad..0000000000000 --- a/src/Symfony/Component/Messenger/Transport/InMemoryTransport.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\Transport; - -use Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport as BaseInMemoryTransport; - -trigger_deprecation('symfony/messenger', '6.3', 'The "%s" class is deprecated, use "%s" instead. ', InMemoryTransport::class, BaseInMemoryTransport::class); - -/** - * @deprecated since Symfony 6.3, use {@link BaseInMemoryTransport} instead - */ -class InMemoryTransport extends BaseInMemoryTransport -{ -} diff --git a/src/Symfony/Component/Messenger/Transport/InMemoryTransportFactory.php b/src/Symfony/Component/Messenger/Transport/InMemoryTransportFactory.php deleted file mode 100644 index bdd4817d6a600..0000000000000 --- a/src/Symfony/Component/Messenger/Transport/InMemoryTransportFactory.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\Transport; - -use Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory as BaseInMemoryTransportFactory; - -trigger_deprecation('symfony/messenger', '6.3', 'The "%s" class is deprecated, use "%s" instead. ', InMemoryTransportFactory::class, BaseInMemoryTransportFactory::class); - -/** - * @deprecated since Symfony 6.3, use {@link BaseInMemoryTransportFactory} instead - */ -class InMemoryTransportFactory extends BaseInMemoryTransportFactory -{ -} diff --git a/src/Symfony/Component/Mime/CHANGELOG.md b/src/Symfony/Component/Mime/CHANGELOG.md index 810018ba32327..8d593e6ff3e33 100644 --- a/src/Symfony/Component/Mime/CHANGELOG.md +++ b/src/Symfony/Component/Mime/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Remove `Email::attachPart()`, use `Email::addPart()` instead * Argument `$body` is now required (at least null) in `Message::setBody()` + * Require explicit argument when calling `Message::setBody()` 6.3 --- diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/CHANGELOG.md b/src/Symfony/Component/Notifier/Bridge/GoogleChat/CHANGELOG.md index c01ece62d544a..4e40ad9fce639 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/CHANGELOG.md +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove `GoogleChatOptions::card()` in favor of `cardV2()` + 6.3 --- diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatOptions.php b/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatOptions.php index 231a5df4361d5..74b606f7588a3 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatOptions.php +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatOptions.php @@ -61,20 +61,6 @@ public function toArray(): array return $this->options; } - /** - * @deprecated since Symfony 6.3, use "cardV2()" instead - * - * @return $this - */ - public function card(array $card): static - { - trigger_deprecation('symfony/google-chat-notifier', '6.3', '"%s()" is deprecated, use "cardV2()" instead.', __METHOD__); - - $this->options['cards'][] = $card; - - return $this; - } - /** * @return $this */ diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatOptionsTest.php b/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatOptionsTest.php index 00984a60044c9..9c0ae8a0c0633 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatOptionsTest.php +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatOptionsTest.php @@ -16,27 +16,6 @@ final class GoogleChatOptionsTest extends TestCase { - /** - * @group legacy - */ - public function testToArray() - { - $options = new GoogleChatOptions(); - - $options - ->text('Pizza Bot') - ->card(['header' => ['Pizza Bot Customer Support']]); - - $expected = [ - 'text' => 'Pizza Bot', - 'cards' => [ - ['header' => ['Pizza Bot Customer Support']], - ], - ]; - - $this->assertSame($expected, $options->toArray()); - } - public function testToArrayWithCardV2() { $options = new GoogleChatOptions(); diff --git a/src/Symfony/Component/Notifier/Bridge/Novu/Tests/NovuOptionsTest.php b/src/Symfony/Component/Notifier/Bridge/Novu/Tests/NovuOptionsTest.php index 6d1125bf18bb0..3bcf25100730f 100644 --- a/src/Symfony/Component/Notifier/Bridge/Novu/Tests/NovuOptionsTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Novu/Tests/NovuOptionsTest.php @@ -16,9 +16,6 @@ class NovuOptionsTest extends TestCase { - /** - * @group legacy - */ public function testToArray() { $options = new NovuOptions( diff --git a/src/Symfony/Component/PropertyAccess/CHANGELOG.md b/src/Symfony/Component/PropertyAccess/CHANGELOG.md index 3d515960ad641..0dacd605277bf 100644 --- a/src/Symfony/Component/PropertyAccess/CHANGELOG.md +++ b/src/Symfony/Component/PropertyAccess/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add method `isNullSafe()` to `PropertyPathInterface` + * Require explicit argument when calling `PropertyAccessorBuilder::setCacheItemPool()` 6.3 --- diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 0bf5c0afa903a..ac45dbe3b0010 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -290,14 +290,7 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert for ($i = 0; $i < $lastIndex; ++$i) { $property = $propertyPath->getElement($i); $isIndex = $propertyPath->isIndex($i); - - $isNullSafe = false; - if (method_exists($propertyPath, 'isNullSafe')) { - // To be removed in symfony 7 once we are sure isNullSafe is always implemented. - $isNullSafe = $propertyPath->isNullSafe($i); - } else { - trigger_deprecation('symfony/property-access', '6.2', 'The "%s()" method in class "%s" needs to be implemented in version 7.0, not defining it is deprecated.', 'isNullSafe', PropertyPathInterface::class); - } + $isNullSafe = $propertyPath->isNullSafe($i); if ($isIndex) { // Create missing nested arrays on demand diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php index 51362afeb93a8..3a62b44dcdc76 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php @@ -239,11 +239,8 @@ public function isExceptionOnInvalidPropertyPath(): bool * * @return $this */ - public function setCacheItemPool(CacheItemPoolInterface $cacheItemPool = null): static + public function setCacheItemPool(?CacheItemPoolInterface $cacheItemPool): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/property-access', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->cacheItemPool = $cacheItemPool; return $this; diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 95258ff7dd20f..376ee7e1afd0d 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", "symfony/property-info": "^6.4|^7.0" }, "require-dev": { diff --git a/src/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php b/src/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php index e5b83af6be2f1..37f0145c97a58 100644 --- a/src/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php +++ b/src/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php @@ -26,18 +26,11 @@ class MissingMandatoryParametersException extends \InvalidArgumentException impl * @param string[] $missingParameters * @param int $code */ - public function __construct(string $routeName = '', $missingParameters = null, $code = 0, \Throwable $previous = null) + public function __construct(string $routeName = '', array $missingParameters = [], int $code = 0, \Throwable $previous = null) { - if (\is_array($missingParameters)) { - $this->routeName = $routeName; - $this->missingParameters = $missingParameters; - $message = sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', $missingParameters), $routeName); - } else { - trigger_deprecation('symfony/routing', '6.1', 'Construction of "%s" with an exception message is deprecated, provide the route name and an array of missing parameters instead.', __CLASS__); - $message = $routeName; - $previous = $code instanceof \Throwable ? $code : null; - $code = (int) $missingParameters; - } + $this->routeName = $routeName; + $this->missingParameters = $missingParameters; + $message = sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', $missingParameters), $routeName); parent::__construct($message, $code, $previous); } diff --git a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php index a6335b7ba856c..2c599730f0b09 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php @@ -321,29 +321,6 @@ public function testGenerateWithInvalidLocale() $generator->generate($name); } - /** - * @group legacy - */ - public function testLegacyThrowingMissingMandatoryParameters() - { - $this->expectDeprecation('Since symfony/routing 6.1: Construction of "Symfony\Component\Routing\Exception\MissingMandatoryParametersException" with an exception message is deprecated, provide the route name and an array of missing parameters instead.'); - - $exception = new MissingMandatoryParametersException('expected legacy message'); - $this->assertSame('expected legacy message', $exception->getMessage()); - } - - /** - * @group legacy - */ - public function testLegacyThrowingMissingMandatoryParametersWithAllParameters() - { - $this->expectDeprecation('Since symfony/routing 6.1: Construction of "Symfony\Component\Routing\Exception\MissingMandatoryParametersException" with an exception message is deprecated, provide the route name and an array of missing parameters instead.'); - - $exception = new MissingMandatoryParametersException('expected legacy message', 256, new \Exception()); - $this->assertSame('expected legacy message', $exception->getMessage()); - $this->assertInstanceOf(\Exception::class, $exception->getPrevious()); - } - public function testGenerateForRouteWithoutMandatoryParameter() { $this->expectException(MissingMandatoryParametersException::class); diff --git a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php index 57f61c7e865f2..63186881afb33 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php @@ -186,7 +186,7 @@ public static function provideCompileData() /** * @dataProvider provideCompileImplicitUtf8Data */ - public function testCompileImplicitUtf8Data($name, $arguments, $prefix, $regex, $variables, $tokens, $deprecationType) + public function testCompileImplicitUtf8Data($name, $arguments, $prefix, $regex, $variables, $tokens) { $this->expectException(\LogicException::class); $r = new \ReflectionClass(Route::class); diff --git a/src/Symfony/Component/Security/Core/CHANGELOG.md b/src/Symfony/Component/Security/Core/CHANGELOG.md index b489556c919bb..663b5999cafce 100644 --- a/src/Symfony/Component/Security/Core/CHANGELOG.md +++ b/src/Symfony/Component/Security/Core/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.0 +--- + + * Remove the `Security` class, use `Symfony\Bundle\SecurityBundle\Security` instead + * Require explicit argument when calling `TokenStorage::setToken()` + 6.3 --- diff --git a/src/Symfony/Component/Security/Core/Security.php b/src/Symfony/Component/Security/Core/Security.php deleted file mode 100644 index bb2576a7ab9dc..0000000000000 --- a/src/Symfony/Component/Security/Core/Security.php +++ /dev/null @@ -1,69 +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; - -use Psr\Container\ContainerInterface; -use Symfony\Bundle\SecurityBundle\Security as NewSecurityHelper; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\User\UserInterface; - -/** - * Helper class for commonly-needed security tasks. - * - * @deprecated since Symfony 6.2, use \Symfony\Bundle\SecurityBundle\Security instead - */ -class Security implements AuthorizationCheckerInterface -{ - public const ACCESS_DENIED_ERROR = '_security.403_error'; - public const AUTHENTICATION_ERROR = '_security.last_error'; - public const LAST_USERNAME = '_security.last_username'; - - /** - * @deprecated since Symfony 6.2, use \Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge::MAX_USERNAME_LENGTH instead - */ - public const MAX_USERNAME_LENGTH = 4096; - - private ContainerInterface $container; - - public function __construct(ContainerInterface $container, bool $triggerDeprecation = true) - { - $this->container = $container; - - if ($triggerDeprecation) { - trigger_deprecation('symfony/security-core', '6.2', 'The "%s" class is deprecated, use "%s" instead.', __CLASS__, NewSecurityHelper::class); - } - } - - 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 getToken(): ?TokenInterface - { - return $this->container->get('security.token_storage')->getToken(); - } -} diff --git a/src/Symfony/Component/Security/Http/Authenticator/RemoteUserAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/RemoteUserAuthenticator.php index 2cbb90a8767d8..946206c70fadb 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/RemoteUserAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/RemoteUserAuthenticator.php @@ -24,11 +24,9 @@ * @author Fabien Potencier * @author Maxime Douailin * - * @final - * - * @internal in Symfony 5.1 + * @internal */ -class RemoteUserAuthenticator extends AbstractPreAuthenticatedAuthenticator +final class RemoteUserAuthenticator extends AbstractPreAuthenticatedAuthenticator { private string $userKey; diff --git a/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php b/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php index 91271d14a3d98..d4c7acd826028 100644 --- a/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php +++ b/src/Symfony/Component/Security/Http/EntryPoint/AuthenticationEntryPointInterface.php @@ -39,8 +39,6 @@ interface AuthenticationEntryPointInterface * - For an API token authentication system, you return a 401 response * * return new Response('Auth header required', 401); - * - * @return Response */ - public function start(Request $request, AuthenticationException $authException = null); + public function start(Request $request, AuthenticationException $authException = null): Response; } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ExceptionListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ExceptionListenerTest.php index 6e4d862d2c069..5b79943d24b3e 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ExceptionListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ExceptionListenerTest.php @@ -75,29 +75,6 @@ public static function getAuthenticationExceptionProvider() ]; } - /** - * This test should be removed in Symfony 7.0 when adding native return types to AuthenticationEntryPointInterface::start(). - * - * @group legacy - */ - public function testExceptionWhenEntryPointReturnsBadValue() - { - if ((new \ReflectionMethod(AuthenticationEntryPointInterface::class, 'start'))->hasReturnType()) { - $this->markTestSkipped('Native return type found'); - } - - $event = $this->createEvent(new AuthenticationException()); - - $entryPoint = $this->createMock(AuthenticationEntryPointInterface::class); - $entryPoint->expects($this->once())->method('start')->willReturn('NOT A RESPONSE'); - - $listener = $this->createExceptionListener(null, null, null, $entryPoint); - $listener->onKernelException($event); - // the exception has been replaced by our LogicException - $this->assertInstanceOf(\LogicException::class, $event->getThrowable()); - $this->assertStringEndsWith('start()" method must return a Response object ("string" returned).', $event->getThrowable()->getMessage()); - } - /** * @dataProvider getAccessDeniedExceptionProvider */ diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 2eccea3cb1e2c..fad14fca498f9 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -10,7 +10,7 @@ CHANGELOG * Remove `ContextAwareDenormalizerInterface`, use `DenormalizerInterface` instead * Remove `ContextAwareNormalizerInterface`, use `NormalizerInterface` instead * Remove `CacheableSupportsMethodInterface`, use `NormalizerInterface` and `DenormalizerInterface` instead - * First argument of `AttributeMetadata::setSerializedName()` is now required + * Require explicit argument when calling `AttributeMetadata::setSerializedName()` and `ClassMetadata::setClassDiscriminatorMapping()` * Add argument `$context` to `NormalizerInterface::supportsNormalization()` and `DenormalizerInterface::supportsDenormalization()` 6.3 diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 3d11567a7bfaa..7873f651a267b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -33,10 +33,8 @@ * * @author Nils Adermann * @author Kévin Dunglas - * - * @final since Symfony 6.3 */ -class GetSetMethodNormalizer extends AbstractObjectNormalizer +final class GetSetMethodNormalizer extends AbstractObjectNormalizer { private static $setterAccessibleCache = []; diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index cfe93bc10b51a..d4c5a97e89bd9 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -33,10 +33,8 @@ * * @author Matthieu Napoli * @author Kévin Dunglas - * - * @final since Symfony 6.3 */ -class PropertyNormalizer extends AbstractObjectNormalizer +final class PropertyNormalizer extends AbstractObjectNormalizer { public const NORMALIZE_PUBLIC = 1; public const NORMALIZE_PROTECTED = 2; diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 07ba0d031029e..eef7aa2d9bc60 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.0 +--- + + * Remove `PhpStringTokenParser` + * Remove `PhpExtractor` in favor of `PhpAstExtractor` + 6.2.7 ----- diff --git a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php deleted file mode 100644 index 7ff27f7c8096b..0000000000000 --- a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php +++ /dev/null @@ -1,333 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Translation\Extractor; - -trigger_deprecation('symfony/translation', '6.2', '"%s" is deprecated, use "%s" instead.', PhpExtractor::class, PhpAstExtractor::class); - -use Symfony\Component\Finder\Finder; -use Symfony\Component\Translation\MessageCatalogue; - -/** - * PhpExtractor extracts translation messages from a PHP template. - * - * @author Michel Salib - * - * @deprecated since Symfony 6.2, use the PhpAstExtractor instead - */ -class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface -{ - public const MESSAGE_TOKEN = 300; - public const METHOD_ARGUMENTS_TOKEN = 1000; - public const DOMAIN_TOKEN = 1001; - - /** - * Prefix for new found message. - */ - private string $prefix = ''; - - /** - * The sequence that captures translation messages. - */ - protected $sequences = [ - [ - '->', - 'trans', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ], - [ - '->', - 'trans', - '(', - self::MESSAGE_TOKEN, - ], - [ - 'new', - 'TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ], - [ - 'new', - 'TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ], - [ - 'new', - '\\', - 'Symfony', - '\\', - 'Component', - '\\', - 'Translation', - '\\', - 'TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ], - [ - 'new', - '\Symfony\Component\Translation\TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ], - [ - 'new', - '\\', - 'Symfony', - '\\', - 'Component', - '\\', - 'Translation', - '\\', - 'TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ], - [ - 'new', - '\Symfony\Component\Translation\TranslatableMessage', - '(', - self::MESSAGE_TOKEN, - ], - [ - 't', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ], - [ - 't', - '(', - self::MESSAGE_TOKEN, - ], - ]; - - /** - * @return void - */ - public function extract(string|iterable $resource, MessageCatalogue $catalog) - { - $files = $this->extractFiles($resource); - foreach ($files as $file) { - $this->parseTokens(token_get_all(file_get_contents($file)), $catalog, $file); - - gc_mem_caches(); - } - } - - /** - * @return void - */ - public function setPrefix(string $prefix) - { - $this->prefix = $prefix; - } - - /** - * Normalizes a token. - */ - protected function normalizeToken(mixed $token): ?string - { - if (isset($token[1]) && 'b"' !== $token) { - return $token[1]; - } - - return $token; - } - - /** - * Seeks to a non-whitespace token. - */ - private function seekToNextRelevantToken(\Iterator $tokenIterator): void - { - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - if (\T_WHITESPACE !== $t[0]) { - break; - } - } - } - - private function skipMethodArgument(\Iterator $tokenIterator): void - { - $openBraces = 0; - - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - - if ('[' === $t[0] || '(' === $t[0]) { - ++$openBraces; - } - - if (']' === $t[0] || ')' === $t[0]) { - --$openBraces; - } - - if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { - break; - } - } - } - - /** - * Extracts the message from the iterator while the tokens - * match allowed message tokens. - */ - private function getValue(\Iterator $tokenIterator): string - { - $message = ''; - $docToken = ''; - $docPart = ''; - - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - if ('.' === $t) { - // Concatenate with next token - continue; - } - if (!isset($t[1])) { - break; - } - - switch ($t[0]) { - case \T_START_HEREDOC: - $docToken = $t[1]; - break; - case \T_ENCAPSED_AND_WHITESPACE: - case \T_CONSTANT_ENCAPSED_STRING: - if ('' === $docToken) { - $message .= PhpStringTokenParser::parse($t[1]); - } else { - $docPart = $t[1]; - } - break; - case \T_END_HEREDOC: - if ($indentation = strspn($t[1], ' ')) { - $docPartWithLineBreaks = $docPart; - $docPart = ''; - - foreach (preg_split('~(\r\n|\n|\r)~', $docPartWithLineBreaks, -1, \PREG_SPLIT_DELIM_CAPTURE) as $str) { - if (\in_array($str, ["\r\n", "\n", "\r"], true)) { - $docPart .= $str; - } else { - $docPart .= substr($str, $indentation); - } - } - } - - $message .= PhpStringTokenParser::parseDocString($docToken, $docPart); - $docToken = ''; - $docPart = ''; - break; - case \T_WHITESPACE: - break; - default: - break 2; - } - } - - return $message; - } - - /** - * Extracts trans message from PHP tokens. - * - * @return void - */ - protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename) - { - $tokenIterator = new \ArrayIterator($tokens); - - for ($key = 0; $key < $tokenIterator->count(); ++$key) { - foreach ($this->sequences as $sequence) { - $message = ''; - $domain = 'messages'; - $tokenIterator->seek($key); - - foreach ($sequence as $sequenceKey => $item) { - $this->seekToNextRelevantToken($tokenIterator); - - if ($this->normalizeToken($tokenIterator->current()) === $item) { - $tokenIterator->next(); - continue; - } elseif (self::MESSAGE_TOKEN === $item) { - $message = $this->getValue($tokenIterator); - - if (\count($sequence) === ($sequenceKey + 1)) { - break; - } - } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { - $this->skipMethodArgument($tokenIterator); - } elseif (self::DOMAIN_TOKEN === $item) { - $domainToken = $this->getValue($tokenIterator); - if ('' !== $domainToken) { - $domain = $domainToken; - } - - break; - } else { - break; - } - } - - if ($message) { - $catalog->set($message, $this->prefix.$message, $domain); - $metadata = $catalog->getMetadata($message, $domain) ?? []; - $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename); - $metadata['sources'][] = $normalizedFilename.':'.$tokens[$key][2]; - $catalog->setMetadata($message, $metadata, $domain); - break; - } - } - } - } - - /** - * @throws \InvalidArgumentException - */ - protected function canBeExtracted(string $file): bool - { - return $this->isFile($file) && 'php' === pathinfo($file, \PATHINFO_EXTENSION); - } - - protected function extractFromDirectory(string|array $directory): iterable - { - if (!class_exists(Finder::class)) { - throw new \LogicException(sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class)); - } - - $finder = new Finder(); - - return $finder->files()->name('*.php')->in($directory); - } -} diff --git a/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php b/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php deleted file mode 100644 index 3b854ce73cb38..0000000000000 --- a/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Translation\Extractor; - -trigger_deprecation('symfony/translation', '6.2', '"%s" is deprecated.', PhpStringTokenParser::class); - -/* - * The following is derived from code at http://github.com/nikic/PHP-Parser - * - * Copyright (c) 2011 by Nikita Popov - * - * Some rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * The names of the contributors may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @deprecated since Symfony 6.2 - */ -class PhpStringTokenParser -{ - protected static $replacements = [ - '\\' => '\\', - '$' => '$', - 'n' => "\n", - 'r' => "\r", - 't' => "\t", - 'f' => "\f", - 'v' => "\v", - 'e' => "\x1B", - ]; - - /** - * Parses a string token. - * - * @param string $str String token content - */ - public static function parse(string $str): string - { - $bLength = 0; - if ('b' === $str[0]) { - $bLength = 1; - } - - if ('\'' === $str[$bLength]) { - return str_replace( - ['\\\\', '\\\''], - ['\\', '\''], - substr($str, $bLength + 1, -1) - ); - } else { - return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); - } - } - - /** - * Parses escape sequences in strings (all string types apart from single quoted). - * - * @param string $str String without quotes - * @param string|null $quote Quote type - */ - public static function parseEscapeSequences(string $str, string $quote = null): string - { - if (null !== $quote) { - $str = str_replace('\\'.$quote, $quote, $str); - } - - return preg_replace_callback( - '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', - [__CLASS__, 'parseCallback'], - $str - ); - } - - private static function parseCallback(array $matches): string - { - $str = $matches[1]; - - if (isset(self::$replacements[$str])) { - return self::$replacements[$str]; - } elseif ('x' === $str[0] || 'X' === $str[0]) { - return \chr(hexdec($str)); - } else { - return \chr(octdec($str)); - } - } - - /** - * Parses a constant doc string. - * - * @param string $startToken Doc string start token content (<< - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Translation\Tests\Extractor; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\Extractor\PhpExtractor; -use Symfony\Component\Translation\MessageCatalogue; - -/** - * @group legacy - */ -class PhpExtractorTest extends TestCase -{ - /** - * @dataProvider resourcesProvider - * - * @param array|string $resource - */ - public function testExtraction($resource) - { - // Arrange - $extractor = new PhpExtractor(); - $extractor->setPrefix('prefix'); - $catalogue = new MessageCatalogue('en'); - - // Act - $extractor->extract($resource, $catalogue); - - $expectedHeredoc = << [ - 'translatable single-quoted key' => 'prefixtranslatable single-quoted key', - 'translatable double-quoted key' => 'prefixtranslatable double-quoted key', - 'translatable heredoc key' => 'prefixtranslatable heredoc key', - 'translatable nowdoc key' => 'prefixtranslatable nowdoc key', - "translatable double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixtranslatable double-quoted key with whitespace and escaped \$\n\" sequences", - 'translatable single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixtranslatable single-quoted key with whitespace and nonescaped \$\n\' sequences', - 'translatable single-quoted key with "quote mark at the end"' => 'prefixtranslatable single-quoted key with "quote mark at the end"', - 'translatable '.$expectedHeredoc => 'prefixtranslatable '.$expectedHeredoc, - 'translatable '.$expectedNowdoc => 'prefixtranslatable '.$expectedNowdoc, - 'translatable concatenated message with heredoc and nowdoc' => 'prefixtranslatable concatenated message with heredoc and nowdoc', - 'translatable default domain' => 'prefixtranslatable default domain', - 'translatable-fqn single-quoted key' => 'prefixtranslatable-fqn single-quoted key', - 'translatable-fqn double-quoted key' => 'prefixtranslatable-fqn double-quoted key', - 'translatable-fqn heredoc key' => 'prefixtranslatable-fqn heredoc key', - 'translatable-fqn nowdoc key' => 'prefixtranslatable-fqn nowdoc key', - "translatable-fqn double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixtranslatable-fqn double-quoted key with whitespace and escaped \$\n\" sequences", - 'translatable-fqn single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixtranslatable-fqn single-quoted key with whitespace and nonescaped \$\n\' sequences', - 'translatable-fqn single-quoted key with "quote mark at the end"' => 'prefixtranslatable-fqn single-quoted key with "quote mark at the end"', - 'translatable-fqn '.$expectedHeredoc => 'prefixtranslatable-fqn '.$expectedHeredoc, - 'translatable-fqn '.$expectedNowdoc => 'prefixtranslatable-fqn '.$expectedNowdoc, - 'translatable-fqn concatenated message with heredoc and nowdoc' => 'prefixtranslatable-fqn concatenated message with heredoc and nowdoc', - 'translatable-fqn default domain' => 'prefixtranslatable-fqn default domain', - 'translatable-short single-quoted key' => 'prefixtranslatable-short single-quoted key', - 'translatable-short double-quoted key' => 'prefixtranslatable-short double-quoted key', - 'translatable-short heredoc key' => 'prefixtranslatable-short heredoc key', - 'translatable-short nowdoc key' => 'prefixtranslatable-short nowdoc key', - "translatable-short double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixtranslatable-short double-quoted key with whitespace and escaped \$\n\" sequences", - 'translatable-short single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixtranslatable-short single-quoted key with whitespace and nonescaped \$\n\' sequences', - 'translatable-short single-quoted key with "quote mark at the end"' => 'prefixtranslatable-short single-quoted key with "quote mark at the end"', - 'translatable-short '.$expectedHeredoc => 'prefixtranslatable-short '.$expectedHeredoc, - 'translatable-short '.$expectedNowdoc => 'prefixtranslatable-short '.$expectedNowdoc, - 'translatable-short concatenated message with heredoc and nowdoc' => 'prefixtranslatable-short concatenated message with heredoc and nowdoc', - 'translatable-short default domain' => 'prefixtranslatable-short default domain', - 'single-quoted key' => 'prefixsingle-quoted key', - 'double-quoted key' => 'prefixdouble-quoted key', - 'heredoc key' => 'prefixheredoc key', - 'nowdoc key' => 'prefixnowdoc key', - "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences", - 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences', - 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"', - $expectedHeredoc => 'prefix'.$expectedHeredoc, - $expectedNowdoc => 'prefix'.$expectedNowdoc, - 'concatenated message with heredoc and nowdoc' => 'prefixconcatenated message with heredoc and nowdoc', - 'default domain' => 'prefixdefault domain', - ], - 'not_messages' => [ - 'translatable other-domain-test-no-params-short-array' => 'prefixtranslatable other-domain-test-no-params-short-array', - 'translatable other-domain-test-no-params-long-array' => 'prefixtranslatable other-domain-test-no-params-long-array', - 'translatable other-domain-test-params-short-array' => 'prefixtranslatable other-domain-test-params-short-array', - 'translatable other-domain-test-params-long-array' => 'prefixtranslatable other-domain-test-params-long-array', - 'translatable typecast' => 'prefixtranslatable typecast', - 'translatable-fqn other-domain-test-no-params-short-array' => 'prefixtranslatable-fqn other-domain-test-no-params-short-array', - 'translatable-fqn other-domain-test-no-params-long-array' => 'prefixtranslatable-fqn other-domain-test-no-params-long-array', - 'translatable-fqn other-domain-test-params-short-array' => 'prefixtranslatable-fqn other-domain-test-params-short-array', - 'translatable-fqn other-domain-test-params-long-array' => 'prefixtranslatable-fqn other-domain-test-params-long-array', - 'translatable-fqn typecast' => 'prefixtranslatable-fqn typecast', - 'translatable-short other-domain-test-no-params-short-array' => 'prefixtranslatable-short other-domain-test-no-params-short-array', - 'translatable-short other-domain-test-no-params-long-array' => 'prefixtranslatable-short other-domain-test-no-params-long-array', - 'translatable-short other-domain-test-params-short-array' => 'prefixtranslatable-short other-domain-test-params-short-array', - 'translatable-short other-domain-test-params-long-array' => 'prefixtranslatable-short other-domain-test-params-long-array', - 'translatable-short typecast' => 'prefixtranslatable-short typecast', - 'other-domain-test-no-params-short-array' => 'prefixother-domain-test-no-params-short-array', - 'other-domain-test-no-params-long-array' => 'prefixother-domain-test-no-params-long-array', - 'other-domain-test-params-short-array' => 'prefixother-domain-test-params-short-array', - 'other-domain-test-params-long-array' => 'prefixother-domain-test-params-long-array', - 'typecast' => 'prefixtypecast', - ], - ]; - $actualCatalogue = $catalogue->all(); - - $this->assertEquals($expectedCatalogue, $actualCatalogue); - - $filename = str_replace(\DIRECTORY_SEPARATOR, '/', __DIR__).'/../fixtures/extractor/translatable.html.php'; - $this->assertEquals(['sources' => [$filename.':2']], $catalogue->getMetadata('translatable single-quoted key')); - $this->assertEquals(['sources' => [$filename.':37']], $catalogue->getMetadata('translatable other-domain-test-no-params-short-array', 'not_messages')); - - $filename = str_replace(\DIRECTORY_SEPARATOR, '/', __DIR__).'/../fixtures/extractor/translatable-fqn.html.php'; - $this->assertEquals(['sources' => [$filename.':2']], $catalogue->getMetadata('translatable-fqn single-quoted key')); - $this->assertEquals(['sources' => [$filename.':37']], $catalogue->getMetadata('translatable-fqn other-domain-test-no-params-short-array', 'not_messages')); - - $filename = str_replace(\DIRECTORY_SEPARATOR, '/', __DIR__).'/../fixtures/extractor/translatable-short.html.php'; - $this->assertEquals(['sources' => [$filename.':2']], $catalogue->getMetadata('translatable-short single-quoted key')); - $this->assertEquals(['sources' => [$filename.':37']], $catalogue->getMetadata('translatable-short other-domain-test-no-params-short-array', 'not_messages')); - - $filename = str_replace(\DIRECTORY_SEPARATOR, '/', __DIR__).'/../fixtures/extractor/translation.html.php'; - $this->assertEquals(['sources' => [$filename.':2']], $catalogue->getMetadata('single-quoted key')); - $this->assertEquals(['sources' => [$filename.':37']], $catalogue->getMetadata('other-domain-test-no-params-short-array', 'not_messages')); - } - - public function testExtractionFromIndentedHeredocNowdoc() - { - $catalogue = new MessageCatalogue('en'); - - $extractor = new PhpExtractor(); - $extractor->setPrefix('prefix'); - $extractor->extract(__DIR__.'/../fixtures/extractor-7.3/translation.html.php', $catalogue); - - $expectedCatalogue = [ - 'messages' => [ - "heredoc\nindented\n further" => "prefixheredoc\nindented\n further", - "nowdoc\nindented\n further" => "prefixnowdoc\nindented\n further", - ], - ]; - - $this->assertEquals($expectedCatalogue, $catalogue->all()); - } - - public static function resourcesProvider() - { - $directory = __DIR__.'/../fixtures/extractor/'; - $phpFiles = []; - $splFiles = []; - foreach (new \DirectoryIterator($directory) as $fileInfo) { - if ($fileInfo->isDot()) { - continue; - } - if (\in_array($fileInfo->getBasename(), ['translatable.html.php', 'translatable-fqn.html.php', 'translatable-short.html.php', 'translation.html.php'], true)) { - $phpFiles[] = $fileInfo->getPathname(); - } - $splFiles[] = $fileInfo->getFileInfo(); - } - - return [ - [$directory], - [$phpFiles], - [glob($directory.'*')], - [$splFiles], - [new \ArrayObject(glob($directory.'*'))], - [new \ArrayObject($splFiles)], - ]; - } -} diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md index 4c3bba6636fa4..9843da0d82151 100644 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add argument `$label` to `VarDumper::dump()` + * Require explicit argument when calling `VarDumper::setHandler()` 6.3 --- diff --git a/src/Symfony/Component/VarDumper/VarDumper.php b/src/Symfony/Component/VarDumper/VarDumper.php index a89f2369bb015..eda2727d50709 100644 --- a/src/Symfony/Component/VarDumper/VarDumper.php +++ b/src/Symfony/Component/VarDumper/VarDumper.php @@ -38,8 +38,6 @@ class VarDumper private static $handler; /** - * @param string|null $label - * * @return mixed */ public static function dump(mixed $var, string $label = null) @@ -51,11 +49,8 @@ public static function dump(mixed $var, string $label = null) return (self::$handler)($var, $label); } - public static function setHandler(callable $callable = null): ?callable + public static function setHandler(?callable $callable): ?callable { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/var-dumper', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $prevHandler = self::$handler; // Prevent replacing the handler with expected format as soon as the env var was set: diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index ff7162853d0fa..bec98b076e98d 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Require explicit argument when calling `Definition::setInitialPlaces()` + 6.4 --- diff --git a/src/Symfony/Component/Workflow/Definition.php b/src/Symfony/Component/Workflow/Definition.php index cdb180976895e..91172dcebce82 100644 --- a/src/Symfony/Component/Workflow/Definition.php +++ b/src/Symfony/Component/Workflow/Definition.php @@ -76,11 +76,8 @@ public function getMetadataStore(): MetadataStoreInterface return $this->metadataStore; } - private function setInitialPlaces(string|array $places = null): void + private function setInitialPlaces(string|array|null $places): void { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/workflow', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } if (!$places) { return; } diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php index 287d8b750f9b4..ad72693c5a64f 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -18,7 +18,7 @@ * @author Fabien Potencier * @author Grégoire Pineau * - * @internal since Symfony 6.2. Inject the workflow where you need it. + * @internal */ class Registry { diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 0c2021f48b2ef..4342bb3cd490c 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.0 +--- + + * Remove the `!php/const:` tag, use `!php/const` instead (without the colon) + 6.3 --- diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index ddfbcfd83a06f..fb0bfeaa69766 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -198,14 +198,9 @@ private function doParse(string $value, int $flags): mixed array_pop($this->refsBeingParsed); } } elseif ( - // @todo in 7.0 remove legacy "(?:!?!php/const:)?" - self::preg_match('#^(?P(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(( |\t)++(?P.+))?$#u', rtrim($this->currentLine), $values) + self::preg_match('#^(?P(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{!].*?)) *\:(( |\t)++(?P.+))?$#u', rtrim($this->currentLine), $values) && (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"])) ) { - if (str_starts_with($values['key'], '!php/const:')) { - trigger_deprecation('symfony/yaml', '6.2', 'YAML syntax for key "%s" is deprecated and replaced by "!php/const %s".', $values['key'], substr($values['key'], 11)); - } - if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename); } @@ -413,7 +408,7 @@ private function doParse(string $value, int $flags): mixed throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine, $this->filename); } - if ($deprecatedUsage = (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1])) { + if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) { throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } @@ -443,7 +438,7 @@ private function doParse(string $value, int $flags): mixed continue; } // If the indentation is not consistent at offset 0, it is to be considered as a ParseError - if (0 === $this->offset && !$deprecatedUsage && isset($line[0]) && ' ' === $line[0]) { + if (0 === $this->offset && isset($line[0]) && ' ' === $line[0]) { throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index e5da4c224e422..4a3543d121574 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -824,7 +824,7 @@ public function testTheEmptyStringIsAValidMappingKey() /** * @dataProvider getNotPhpCompatibleMappingKeyData */ - public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected) + public function testImplicitStringCastingOfMappingKeysThrows($yaml, $expected) { $this->expectException(ParseException::class); $this->expectExceptionMessage('Implicit casting of incompatible mapping keys to strings is not supported. Quote your evaluable mapping keys instead'); diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 2918d1b07c337..5d1968252bb2d 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Yaml\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Tag\TaggedValue; @@ -20,8 +19,6 @@ class ParserTest extends TestCase { - use ExpectDeprecationTrait; - private ?Parser $parser; protected function setUp(): void @@ -662,7 +659,7 @@ public function testObjectsSupportDisabledWithExceptions() $this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } - public function testMappingKeyInMultiLineStringTriggersDeprecationNotice() + public function testMappingKeyInMultiLineStringThrowsException() { $this->expectException(ParseException::class); $this->expectExceptionMessage('Mapping values are not allowed in multi-line blocks at line 2 (near "dbal:wrong").'); @@ -2483,7 +2480,7 @@ public function testPhpConstantTagMappingKey() $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); } - public function testDeprecatedPhpConstantSyntax() + public function testWrongPhpConstantSyntax() { $this->expectException(ParseException::class); $this->expectExceptionMessage('Missing value for tag "php/const:App\Kernel::SEMART_VERSION" at line 1 (near "!php/const:App\Kernel::SEMART_VERSION").'); @@ -2491,17 +2488,6 @@ public function testDeprecatedPhpConstantSyntax() $this->parser->parse('!php/const:App\Kernel::SEMART_VERSION', Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_CONSTANT); } - /** - * @group legacy - */ - public function testDeprecatedPhpConstantSyntaxAsScalarKey() - { - $this->expectDeprecation('Since symfony/yaml 6.2: YAML syntax for key "!php/const:Symfony\Component\Yaml\Tests\B::BAR" is deprecated and replaced by "!php/const Symfony\Component\Yaml\Tests\B::BAR".'); - $actual = $this->parser->parse('!php/const:Symfony\Component\Yaml\Tests\B::BAR: value', Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_CONSTANT); - - $this->assertSame(['bar' => 'value'], $actual); - } - public function testPhpConstantTagMappingAsScalarKey() { $yaml = << - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Test; - -class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); - -if (false) { - /** - * @deprecated since PHPUnit 9.6 - */ - class ServiceLocatorTest - { - } -}