diff --git a/.appveyor.yml b/.appveyor.yml index 8a880a9b3c063..67dcba9b569f6 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,10 +3,6 @@ clone_depth: 2 clone_folder: c:\projects\symfony image: Visual Studio 2019 -cache: - - composer.phar - - .phpunit -> phpunit - init: - SET PATH=c:\php;%PATH% - SET COMPOSER_NO_INTERACTION=1 @@ -17,13 +13,13 @@ init: install: - mkdir c:\php && cd c:\php - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.0.2-Win32-vs16-x86.zip - - 7z x php-8.0.2-Win32-vs16-x86.zip -y >nul + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.1.0-Win32-vs16-x86.zip + - 7z x php-8.1.0-Win32-vs16-x86.zip -y >nul - cd ext - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.21-8.0-ts-vs16-x86.zip - - 7z x php_apcu-5.1.21-8.0-ts-vs16-x86.zip -y >nul - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-5.3.5-8.0-ts-vs16-x86.zip - - 7z x php_redis-5.3.5-8.0-ts-vs16-x86.zip -y >nul + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.21-8.1-ts-vs16-x86.zip + - 7z x php_apcu-5.1.21-8.1-ts-vs16-x86.zip -y >nul + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-5.3.7rc1-8.1-ts-vs16-x86.zip + - 7z x php_redis-5.3.7rc1-8.1-ts-vs16-x86.zip -y >nul - cd .. - copy /Y php.ini-development php.ini-min - echo memory_limit=-1 >> php.ini-min @@ -46,11 +42,11 @@ install: - echo extension=php_fileinfo.dll >> php.ini-max - echo extension=php_pdo_sqlite.dll >> php.ini-max - echo extension=php_curl.dll >> php.ini-max + - echo extension=php_sodium.dll >> php.ini-max - copy /Y php.ini-max php.ini - cd c:\projects\symfony - - IF NOT EXIST composer.phar (appveyor DownloadFile https://github.com/composer/composer/releases/download/2.0.0/composer.phar) - - php composer.phar self-update --2 - - copy /Y .github\composer-config.json %APPDATA%\Composer\config.json + - appveyor DownloadFile https://getcomposer.org/download/latest-stable/composer.phar + - mkdir %APPDATA%\Composer && copy /Y .github\composer-config.json %APPDATA%\Composer\config.json - git config --global user.email "" - git config --global user.name "Symfony" - FOR /F "tokens=* USEBACKQ" %%F IN (`bash -c "grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -o '[0-9][0-9]*\.[0-9]'"`) DO (SET SYMFONY_VERSION=%%F) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b958112d1b58a..19e868793ac36 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -24,13 +24,8 @@ /src/Symfony/Component/Form/ @xabbuh @yceruto # HttpKernel /src/Symfony/Component/HttpKernel/Log/Logger.php @dunglas -# LDAP -/src/Symfony/Component/Ldap/ @csarrazi # Lock /src/Symfony/Component/Lock/ @jderusse -# Messenger -/src/Symfony/Bridge/Doctrine/Messenger/ @sroze -/src/Symfony/Component/Messenger/ @sroze # Notifer /src/Symfony/Component/Notifier/ @OskarStark # OptionsResolver diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e6333054fe172..6a3604dff7aad 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,10 @@ | Q | A | ------------- | --- -| Branch? | 6.1 for features / 4.4, 5.4 or 6.0 for bug fixes +| Branch? | 6.3 for features / 5.4, 6.0, 6.1, or 6.2 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no -| Tickets | Fix #... +| Tickets | Fix #... | License | MIT | Doc PR | symfony/symfony-docs#... diff --git a/.github/composer-config.json b/.github/composer-config.json index 65919964fa8a1..2bdec1a826251 100644 --- a/.github/composer-config.json +++ b/.github/composer-config.json @@ -10,6 +10,9 @@ "symfony/translation": "source", "symfony/validator": "source", "*": "dist" + }, + "allow-plugins": { + "symfony/flex": true } } } diff --git a/.github/expected-missing-return-types.diff b/.github/expected-missing-return-types.diff index 4fd8581aba1ac..cf4c237e3070c 100644 --- a/.github/expected-missing-return-types.diff +++ b/.github/expected-missing-return-types.diff @@ -1,35 +1,24 @@ # Run these steps to update this file: sed -i 's/ *"\*\*\/Tests\/"//' composer.json composer u -o -SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.0' php .github/patch-types.php +SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.1' php .github/patch-types.php head=$(sed '/^diff /Q' .github/expected-missing-return-types.diff) -(echo "$head" && echo && git diff -U2 composer.json src/) > .github/expected-missing-return-types.diff +(echo "$head" && echo && git diff -U2 src/) > .github/expected-missing-return-types.diff git checkout composer.json src/ -diff --git a/composer.json b/composer.json -index c7b7eac4c7..2b60fb6a19 100644 ---- a/composer.json -+++ b/composer.json -@@ -180,5 +180,5 @@ - ], - "exclude-from-classmap": [ -- "**/Tests/" -+ - ] - }, diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php -index d68ae4c8b3..8e980a9e70 100644 +index 165797504b..0c0922088a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php -@@ -88,5 +88,5 @@ abstract class KernelTestCase extends TestCase - * @return TestContainer +@@ -87,5 +87,5 @@ abstract class KernelTestCase extends TestCase + * @return Container */ - protected static function getContainer(): ContainerInterface -+ protected static function getContainer(): TestContainer ++ protected static function getContainer(): Container { if (!static::$booted) { diff --git a/src/Symfony/Component/BrowserKit/AbstractBrowser.php b/src/Symfony/Component/BrowserKit/AbstractBrowser.php -index 697e34cb77..9a1e4c5618 100644 +index ac25bdf4be..949a036abd 100644 --- a/src/Symfony/Component/BrowserKit/AbstractBrowser.php +++ b/src/Symfony/Component/BrowserKit/AbstractBrowser.php @@ -408,5 +408,5 @@ abstract class AbstractBrowser @@ -60,6 +49,17 @@ index 697e34cb77..9a1e4c5618 100644 + protected function filterResponse(object $response): Response { return $response; +diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +index 89d6adb70e..c569992efc 100644 +--- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php ++++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +@@ -108,5 +108,5 @@ class NodeBuilder implements NodeParentInterface + * @return NodeDefinition&ParentNodeDefinitionInterface + */ +- public function end() ++ public function end(): NodeDefinition&ParentNodeDefinitionInterface + { + return $this->parent; diff --git a/src/Symfony/Component/Config/Definition/ConfigurationInterface.php b/src/Symfony/Component/Config/Definition/ConfigurationInterface.php index 7b5d443fe6..d64ae0d024 100644 --- a/src/Symfony/Component/Config/Definition/ConfigurationInterface.php @@ -156,7 +156,7 @@ index 6b1c6c5fbe..bb80ed461e 100644 + public function isFresh(ResourceInterface $resource, int $timestamp): bool; } diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php -index 0ed5649b8a..6c814bf82c 100644 +index 64068fcc23..f29aaf1b94 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -218,5 +218,5 @@ class Application implements ResetInterface @@ -166,42 +166,42 @@ index 0ed5649b8a..6c814bf82c 100644 + public function doRun(InputInterface $input, OutputInterface $output): int { if (true === $input->hasParameterOption(['--version', '-V'], true)) { -@@ -445,5 +445,5 @@ class Application implements ResetInterface +@@ -454,5 +454,5 @@ class Application implements ResetInterface * @return string */ - public function getLongVersion() + public function getLongVersion(): string { if ('UNKNOWN' !== $this->getName()) { -@@ -488,5 +488,5 @@ class Application implements ResetInterface +@@ -497,5 +497,5 @@ class Application implements ResetInterface * @return Command|null */ - public function add(Command $command) + public function add(Command $command): ?Command { $this->init(); -@@ -525,5 +525,5 @@ class Application implements ResetInterface +@@ -534,5 +534,5 @@ class Application implements ResetInterface * @throws CommandNotFoundException When given command name does not exist */ - public function get(string $name) + public function get(string $name): Command { $this->init(); -@@ -632,5 +632,5 @@ class Application implements ResetInterface +@@ -641,5 +641,5 @@ class Application implements ResetInterface * @throws CommandNotFoundException When command name is incorrect or ambiguous */ - public function find(string $name) + public function find(string $name): Command { $this->init(); -@@ -742,5 +742,5 @@ class Application implements ResetInterface +@@ -751,5 +751,5 @@ class Application implements ResetInterface * @return Command[] */ - public function all(string $namespace = null) + public function all(string $namespace = null): array { $this->init(); -@@ -941,5 +941,5 @@ class Application implements ResetInterface +@@ -950,5 +950,5 @@ class Application implements ResetInterface * @return int 0 if everything went fine, or an error code */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) @@ -209,23 +209,44 @@ index 0ed5649b8a..6c814bf82c 100644 { foreach ($command->getHelperSet() as $helper) { diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php -index 0bd3426c07..b38caf989e 100644 +index 0a3f4b7889..18c2312399 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php -@@ -171,5 +171,5 @@ class Command +@@ -188,5 +188,5 @@ class Command * @return bool */ - public function isEnabled() + public function isEnabled(): bool { return true; -@@ -197,5 +197,5 @@ class Command +@@ -214,5 +214,5 @@ class Command * @see setCode() */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { throw new LogicException('You must override the execute() method in the concrete command class.'); +diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php +index 3c6b0efccd..121664f15a 100644 +--- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php ++++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php +@@ -137,5 +137,5 @@ class OutputFormatter implements WrappableOutputFormatterInterface + * {@inheritdoc} + */ +- public function formatAndWrap(?string $message, int $width) ++ public function formatAndWrap(?string $message, int $width): string + { + if (null === $message) { +diff --git a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php +index 746cd27e79..52c61429cf 100644 +--- a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php ++++ b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php +@@ -24,4 +24,4 @@ interface WrappableOutputFormatterInterface extends OutputFormatterInterface + * @return string + */ +- public function formatAndWrap(?string $message, int $width); ++ public function formatAndWrap(?string $message, int $width): string; + } diff --git a/src/Symfony/Component/Console/Helper/HelperInterface.php b/src/Symfony/Component/Console/Helper/HelperInterface.php index 1d2b7bfb84..cb1f66152d 100644 --- a/src/Symfony/Component/Console/Helper/HelperInterface.php @@ -262,7 +283,7 @@ index 3af991a76f..742e2508f3 100644 /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php -index c2824f4578..032f5c2318 100644 +index 70b6c91ff5..cfced387f3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -71,5 +71,5 @@ abstract class AbstractRecursivePass implements CompilerPassInterface @@ -273,7 +294,7 @@ index c2824f4578..032f5c2318 100644 { if (\is_array($value)) { diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php -index b9dd838898..3a8cb63eac 100644 +index 04b7022484..5d736ec754 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -108,5 +108,5 @@ class Container implements ContainerInterface, ResetInterface @@ -284,7 +305,7 @@ index b9dd838898..3a8cb63eac 100644 { return $this->parameterBag->get($name); diff --git a/src/Symfony/Component/DependencyInjection/ContainerInterface.php b/src/Symfony/Component/DependencyInjection/ContainerInterface.php -index aa5d6b317e..31ffbca4ef 100644 +index cad44026c0..14cd192e07 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerInterface.php +++ b/src/Symfony/Component/DependencyInjection/ContainerInterface.php @@ -53,5 +53,5 @@ interface ContainerInterface extends PsrContainerInterface @@ -402,10 +423,10 @@ index 79d61e8bc0..7f34d95d84 100644 { return null; diff --git a/src/Symfony/Component/Form/AbstractRendererEngine.php b/src/Symfony/Component/Form/AbstractRendererEngine.php -index 3dbe0a8420..b4179c785c 100644 +index ada182f57b..0d2591f7a7 100644 --- a/src/Symfony/Component/Form/AbstractRendererEngine.php +++ b/src/Symfony/Component/Form/AbstractRendererEngine.php -@@ -135,5 +135,5 @@ abstract class AbstractRendererEngine implements FormRendererEngineInterface +@@ -137,5 +137,5 @@ abstract class AbstractRendererEngine implements FormRendererEngineInterface, Re * @return bool */ - abstract protected function loadResourceForBlockName(string $cacheKey, FormView $view, string $blockName); @@ -547,7 +568,7 @@ index 1cb865fd66..f6f4efe7a7 100644 + public function getName(): string; } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php -index cf0e243c6b..292b907ea8 100644 +index 45ff4a006c..611259b3b6 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -448,5 +448,5 @@ class HttpCache implements HttpKernelInterface, TerminableInterface @@ -611,6 +632,17 @@ index 125b6eae50..ac327e8981 100644 + public function createLockFromKey(Key $key, ?float $ttl = 300.0, bool $autoRelease = true): SharedLockInterface { $lock = new Lock($key, $this->store, $ttl, $autoRelease); +diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsTransport.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsTransport.php +index 297fccbd3f..4c47d95b38 100644 +--- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsTransport.php ++++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsTransport.php +@@ -109,5 +109,5 @@ class AmazonSqsTransport implements TransportInterface, SetupableTransportInterf + * @return MessageCountAwareInterface&ReceiverInterface + */ +- private function getReceiver(): ReceiverInterface ++ private function getReceiver(): MessageCountAwareInterface&ReceiverInterface + { + return $this->receiver ??= new AmazonSqsReceiver($this->connection, $this->serializer); diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php index 205c15b4cd..e93e460ed1 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php @@ -696,10 +728,10 @@ index fbb37d9f94..522e0487a9 100644 + public function isIndex(int $index): bool; } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php -index cfffdb2f71..3e2261898a 100644 +index 38e563e177..ee9c00a1db 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php -@@ -725,5 +725,5 @@ class PropertyAccessorTest extends TestCase +@@ -742,5 +742,5 @@ class PropertyAccessorTest extends TestCase * @return mixed */ - public function getFoo() @@ -744,10 +776,10 @@ index 6da0bcb4c8..16e9765b1d 100644 + public function getTypes(string $class, string $property, array $context = []): ?array; } diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php -index 2dd0e5efbf..95e01d8955 100644 +index 204e9b3341..8e624e1154 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php -@@ -260,5 +260,5 @@ abstract class AnnotationClassLoader implements LoaderInterface +@@ -253,5 +253,5 @@ abstract class AnnotationClassLoader implements LoaderInterface * @return string */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) @@ -755,7 +787,7 @@ index 2dd0e5efbf..95e01d8955 100644 { $name = str_replace('\\', '_', $class->name).'_'.$method->name; diff --git a/src/Symfony/Component/Routing/Router.php b/src/Symfony/Component/Routing/Router.php -index 83c10427a1..e113d4a194 100644 +index 1142fc9714..9e4965ce06 100644 --- a/src/Symfony/Component/Routing/Router.php +++ b/src/Symfony/Component/Routing/Router.php @@ -178,5 +178,5 @@ class Router implements RouterInterface, RequestMatcherInterface @@ -867,31 +899,31 @@ index f38069e471..0966eb3e89 100644 + public function decode(string $data, string $format, array $context = []): mixed; /** -@@ -45,4 +45,4 @@ interface DecoderInterface +@@ -44,4 +44,4 @@ interface DecoderInterface * @return bool */ -- public function supportsDecoding(string $format /*, array $context = [] */); -+ public function supportsDecoding(string $format /*, array $context = [] */): bool; +- public function supportsDecoding(string $format); ++ public function supportsDecoding(string $format): bool; } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php -index 7f86ed8d78..cf084423ec 100644 +index 44ba45f581..3398115497 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php -@@ -223,5 +223,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn +@@ -213,5 +213,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn * @return string[]|AttributeMetadataInterface[]|bool */ - protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = false) + protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = false): array|bool { $allowExtraAttributes = $context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES]; -@@ -273,5 +273,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn +@@ -263,5 +263,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn * @return bool */ - protected function isAllowedAttribute(object|string $classOrObject, string $attribute, string $format = null, array $context = []) + protected function isAllowedAttribute(object|string $classOrObject, string $attribute, string $format = null, array $context = []): bool { $ignoredAttributes = $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES]; -@@ -324,5 +324,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn +@@ -314,5 +314,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn * @throws MissingConstructorArgumentsException */ - protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null) @@ -899,52 +931,52 @@ index 7f86ed8d78..cf084423ec 100644 { if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) { diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php -index a8943113c4..2983dabd0f 100644 +index 511dd1c724..c319e1839b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php -@@ -138,5 +138,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -139,5 +139,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * @param array $context */ -- public function supportsNormalization(mixed $data, string $format = null /*, array $context = [] */) -+ public function supportsNormalization(mixed $data, string $format = null /*, array $context = [] */): bool +- public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */) ++ public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool { return \is_object($data) && !$data instanceof \Traversable; -@@ -146,5 +146,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -147,5 +147,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * {@inheritdoc} */ - public function normalize(mixed $object, string $format = null, array $context = []) + public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { if (!isset($context['cache_key'])) { -@@ -279,5 +279,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -265,5 +265,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * {@inheritdoc} */ - protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null) + protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null): object { if ($this->classDiscriminatorResolver && $mapping = $this->classDiscriminatorResolver->getMappingForClass($class)) { -@@ -341,5 +341,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -327,5 +327,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * @return string[] */ - abstract protected function extractAttributes(object $object, string $format = null, array $context = []); + abstract protected function extractAttributes(object $object, string $format = null, array $context = []): array; /** -@@ -348,5 +348,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -334,5 +334,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * @return mixed */ - abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []); + abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed; /** -@@ -355,5 +355,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -341,5 +341,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * @param array $context */ -- public function supportsDenormalization(mixed $data, string $type, string $format = null /*, array $context = [] */) -+ public function supportsDenormalization(mixed $data, string $type, string $format = null /*, array $context = [] */): bool +- public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */) ++ public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool { return class_exists($type) || (interface_exists($type, false) && $this->classDiscriminatorResolver && null !== $this->classDiscriminatorResolver->getMappingForClass($type)); -@@ -363,5 +363,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer +@@ -349,5 +349,5 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * {@inheritdoc} */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []) @@ -965,8 +997,8 @@ index 1c708738a1..3b6c9d5056 100644 @@ -57,4 +57,4 @@ interface DenormalizerInterface * @return bool */ -- public function supportsDenormalization(mixed $data, string $type, string $format = null /*, array $context = [] */); -+ public function supportsDenormalization(mixed $data, string $type, string $format = null /*, array $context = [] */): bool; +- public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */); ++ public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool; } diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php index 741f19e50b..acf3be931b 100644 @@ -982,8 +1014,8 @@ index 741f19e50b..acf3be931b 100644 @@ -48,4 +48,4 @@ interface NormalizerInterface * @return bool */ -- public function supportsNormalization(mixed $data, string $format = null /*, array $context = [] */); -+ public function supportsNormalization(mixed $data, string $format = null /*, array $context = [] */): bool; +- public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */); ++ public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool; } diff --git a/src/Symfony/Component/Templating/Helper/HelperInterface.php b/src/Symfony/Component/Templating/Helper/HelperInterface.php index 5dade65db5..db0d0a00ea 100644 @@ -1013,37 +1045,48 @@ index 4c088b94f9..86107a636d 100644 + abstract protected function extractFromDirectory(string|array $resource): iterable; } diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php -index 46432f2f4c..47ac39d5e3 100644 +index ee1d68c78f..9baaabb04c 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php -@@ -243,5 +243,5 @@ abstract class Constraint +@@ -254,5 +254,5 @@ abstract class Constraint * @see __construct() */ - public function getDefaultOption() + public function getDefaultOption(): ?string { return null; -@@ -257,5 +257,5 @@ abstract class Constraint +@@ -268,5 +268,5 @@ abstract class Constraint * @see __construct() */ - public function getRequiredOptions() + public function getRequiredOptions(): array { return []; -@@ -271,5 +271,5 @@ abstract class Constraint +@@ -282,5 +282,5 @@ abstract class Constraint * @return string */ - public function validatedBy() + public function validatedBy(): string { return static::class.'Validator'; -@@ -285,5 +285,5 @@ abstract class Constraint +@@ -296,5 +296,5 @@ abstract class Constraint * @return string|string[] One or more constant values */ - public function getTargets() + public function getTargets(): string|array { return self::PROPERTY_CONSTRAINT; +diff --git a/src/Symfony/Component/VarExporter/Internal/Exporter.php b/src/Symfony/Component/VarExporter/Internal/Exporter.php +index f7ef22df5c..9439e9526f 100644 +--- a/src/Symfony/Component/VarExporter/Internal/Exporter.php ++++ b/src/Symfony/Component/VarExporter/Internal/Exporter.php +@@ -36,5 +36,5 @@ class Exporter + * @throws NotInstantiableTypeException When a value cannot be serialized + */ +- public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic) ++ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array + { + $refs = $values; diff --git a/src/Symfony/Component/Workflow/Event/Event.php b/src/Symfony/Component/Workflow/Event/Event.php index cd7fab7896..b340eba38e 100644 --- a/src/Symfony/Component/Workflow/Event/Event.php diff --git a/.github/patch-types.php b/.github/patch-types.php index 86b1c95c72ec5..a5ff5b3293c15 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -23,6 +23,7 @@ case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php'): + case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/compositetype_classes.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/intersectiontype_classes.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/MultipleArgumentsOptionalScalarNotReallyOptional.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/IntersectionConstructor.php'): @@ -44,6 +45,7 @@ case false !== strpos($file, '/src/Symfony/Component/Validator/Tests/Fixtures/NestedAttribute/Entity.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/ReflectionIntersectionTypeFixture.php'): + case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/ReflectionUnionTypeWithIntersectionFixture.php'): continue 2; } diff --git a/.github/psalm/.gitignore b/.github/psalm/.gitignore index d6b7ef32c8478..53021ab087be4 100644 --- a/.github/psalm/.gitignore +++ b/.github/psalm/.gitignore @@ -1,2 +1,4 @@ * !.gitignore +!stubs +!stubs/* diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index c9d097ec9a4aa..931fba325e7f0 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -8,6 +8,13 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: tests: @@ -16,7 +23,7 @@ jobs: strategy: matrix: - php: ['8.0'] + php: ['8.1'] services: postgres: @@ -41,7 +48,7 @@ jobs: ports: - 16379:6379 redis-cluster: - image: grokzen/redis-cluster:5.0.4 + image: grokzen/redis-cluster:latest ports: - 7000:7000 - 7001:7001 @@ -87,7 +94,7 @@ jobs: zookeeper: image: wurstmeister/zookeeper:3.4.6 kafka: - image: wurstmeister/kafka:2.12-2.4.1 + image: wurstmeister/kafka:2.12-2.0.1 ports: - 9092:9092 env: @@ -99,16 +106,18 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install system dependencies run: | echo "::group::apt-get update" + sudo wget -O - https://packages.couchbase.com/clients/c/repos/deb/couchbase.key | sudo apt-key add - + echo "deb https://packages.couchbase.com/clients/c/repos/deb/ubuntu2004 focal focal/main" | sudo tee /etc/apt/sources.list.d/couchbase.list sudo apt-get update echo "::endgroup::" echo "::group::install tools & libraries" - sudo apt-get install librdkafka-dev redis-server + sudo apt-get install librdkafka-dev redis-server libcouchbase-dev sudo -- sh -c 'echo unixsocket /var/run/redis/redis-server.sock >> /etc/redis/redis.conf' sudo -- sh -c 'echo unixsocketperm 777 >> /etc/redis/redis.conf' sudo service redis-server restart @@ -125,8 +134,8 @@ jobs: uses: shivammathur/setup-php@v2 with: coverage: "none" - extensions: "json,couchbase,memcached,mongodb-1.10.0,redis-5.3.4,rdkafka,xsl,ldap" - ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 + extensions: "json,couchbase-3.2.2,memcached,mongodb-1.12.0,redis-5.3.4,rdkafka,xsl,ldap" + ini-values: date.timezone=UTC,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 php-version: "${{ matrix.php }}" tools: pecl @@ -149,7 +158,7 @@ jobs: echo COMPOSER_ROOT_VERSION=$COMPOSER_ROOT_VERSION >> $GITHUB_ENV echo "::group::composer update" - composer require --dev --no-update mongodb/mongodb:"1.9.1@dev|^1.9.1@stable" + composer require --dev --no-update mongodb/mongodb:"^1.11" composer update --no-progress --ansi echo "::endgroup::" @@ -162,7 +171,7 @@ jobs: env: REDIS_HOST: 'localhost:16379' REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005' - REDIS_SENTINEL_HOSTS: 'localhost:26379' + REDIS_SENTINEL_HOSTS: 'localhost:26379 localhost:26379 localhost:26379' REDIS_SENTINEL_SERVICE: redis_sentinel MESSENGER_REDIS_DSN: redis://127.0.0.1:7006/messages MESSENGER_AMQP_DSN: amqp://localhost/%2f/messages @@ -172,11 +181,11 @@ jobs: POSTGRES_HOST: localhost #- name: Run HTTP push tests - # if: matrix.php == '8.0' + # if: matrix.php == '8.1' # run: | # [ -d .phpunit ] && mv .phpunit .phpunit.bak # wget -q https://github.com/symfony/binary-utils/releases/download/v0.1/vulcain_0.1.3_Linux_x86_64.tar.gz -O - | tar xz && mv vulcain /usr/local/bin - # docker run --rm -e COMPOSER_ROOT_VERSION -v $(pwd):/app -v $(which composer):/usr/local/bin/composer -v $(which vulcain):/usr/local/bin/vulcain -w /app php:8.0-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push + # docker run --rm -e COMPOSER_ROOT_VERSION -v $(pwd):/app -v $(which composer):/usr/local/bin/composer -v $(which vulcain):/usr/local/bin/vulcain -w /app php:8.1-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push # sudo rm -rf .phpunit # [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 4443fe5b83f9b..b3ed15c4cabaa 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -12,6 +12,13 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: tests: name: Tests @@ -19,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install system dependencies run: | @@ -42,7 +49,7 @@ jobs: coverage: "none" extensions: "zip,intl-${{env.SYMFONY_ICU_VERSION}}" ini-values: "memory_limit=-1" - php-version: "8.0" + php-version: "8.1" - name: Install dependencies run: | diff --git a/.github/workflows/package-tests.yml b/.github/workflows/package-tests.yml index 23b65286814a9..f04bacd0170d3 100644 --- a/.github/workflows/package-tests.yml +++ b/.github/workflows/package-tests.yml @@ -5,6 +5,9 @@ on: paths: - src/** +permissions: + contents: read + jobs: verify: name: Verify @@ -18,7 +21,7 @@ jobs: - name: Find packages id: find-packages - run: echo "::set-output name=packages::$(php .github/get-modified-packages.php $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | jq -R -s -c 'split("\n")[:-1]') $(git diff --name-only origin/${{ github.base_ref }} HEAD | grep src/ | jq -R -s -c 'split("\n")[:-1]'))" + run: echo "packages=$(php .github/get-modified-packages.php $(find src/Symfony -mindepth 2 -type f -name composer.json -printf '%h\n' | jq -R -s -c 'split("\n")[:-1]') $(git diff --name-only origin/${{ github.base_ref }} HEAD | grep src/ | jq -R -s -c 'split("\n")[:-1]'))" >> $GITHUB_OUTPUT - name: Verify meta files are correct run: | diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 5bbcc63041020..0c7bc859bb6ef 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -12,6 +12,13 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: lint: name: Lint @@ -19,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 3eeb7201c486d..01b143d68ec78 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -7,6 +7,13 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: psalm: name: Psalm @@ -16,18 +23,18 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.0' + php-version: '8.1' extensions: "json,couchbase,memcached,mongodb,redis,xsl,ldap,dom" ini-values: "memory_limit=-1" coverage: none - name: Checkout target branch - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ github.base_ref }} - name: Checkout PR - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install dependencies run: | @@ -35,18 +42,13 @@ jobs: ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" export COMPOSER_ROOT_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+').x-dev composer remove --dev --no-update --no-interaction symfony/phpunit-bridge - composer require --no-update psalm/phar phpunit/phpunit:^9.5 php-http/discovery psr/event-dispatcher mongodb/mongodb - - echo "::group::composer update" - composer update --no-progress --ansi - git checkout composer.json - echo "::endgroup::" - - ./vendor/bin/psalm.phar --version + composer require --no-progress --ansi psalm/phar phpunit/phpunit:^9.5 php-http/discovery psr/event-dispatcher mongodb/mongodb - name: Generate Psalm baseline run: | + git checkout composer.json git checkout -m ${{ github.base_ref }} + ./vendor/bin/psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress git checkout -m FETCH_HEAD diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 7c1e9139b9b9d..a138b2ea2d661 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -8,6 +8,13 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: tests: @@ -20,32 +27,27 @@ jobs: matrix: include: - php: '8.1' - - php: '8.0' + - php: '8.1' mode: high-deps - php: '8.1' mode: low-deps - php: '8.2' - mode: experimental + #mode: experimental fail-fast: false runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - - name: Configure for PHP >= 8.2 - if: "matrix.php >= '8.2'" - run: | - composer config platform.php 8.1.99 - - name: Setup PHP uses: shivammathur/setup-php@v2 with: coverage: "none" - ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 + ini-values: date.timezone=UTC,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 php-version: "${{ matrix.php }}" extensions: "${{ env.extensions }}" tools: flex @@ -61,8 +63,8 @@ jobs: ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" echo COLUMNS=120 >> $GITHUB_ENV - echo PHPUNIT="$(pwd)/phpunit --exclude-group tty,benchmark,intl-data" >> $GITHUB_ENV - echo COMPOSER_UP='composer update --no-progress --ansi' >> $GITHUB_ENV + echo PHPUNIT="$(pwd)/phpunit --exclude-group tty,benchmark,intl-data,integration" >> $GITHUB_ENV + echo COMPOSER_UP='composer update --no-progress --ansi'$([[ "${{ matrix.php }}" = "8.2" ]] && echo ' --ignore-platform-req=php+') >> $GITHUB_ENV SYMFONY_VERSIONS=$(git ls-remote -q --heads | cut -f2 | grep -o '/[1-9][0-9]*\.[0-9].*' | sort -V) SYMFONY_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | cut -d "'" -f2 | cut -d '.' -f 1-2) @@ -140,8 +142,8 @@ jobs: patch -sp1 < .github/expected-missing-return-types.diff git add . composer install -q --optimize-autoloader - SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.0' php .github/patch-types.php - SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.0' php .github/patch-types.php # ensure the script is idempotent + SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.1' php .github/patch-types.php + SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.1' php .github/patch-types.php # ensure the script is idempotent git diff --exit-code - name: Run tests @@ -218,12 +220,12 @@ jobs: script -e -c './phpunit --group tty' /dev/null - name: Run tests with SIGCHLD enabled PHP - if: "matrix.php == '8.0' && ! matrix.mode" + if: "matrix.php == '8.1' && ! matrix.mode" run: | mkdir build cd build - wget -q https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.0.2-pcntl-sigchild.tar.bz2 - tar -xjf php-8.0.2-pcntl-sigchild.tar.bz2 + wget -q https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.1.2-pcntl-sigchild.tar.bz2 + tar -xjf php-8.1.2-pcntl-sigchild.tar.bz2 cd .. ./build/php/bin/php ./phpunit --colors=always src/Symfony/Component/Process diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 2333c06badd58..2bc2c558d7b9b 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,9 +1,27 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + if (!file_exists(__DIR__.'/src')) { exit(0); } +$fileHeaderComment = <<<'EOF' +This file is part of the Symfony package. + +(c) Fabien Potencier + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + return (new PhpCsFixer\Config()) ->setRules([ '@PHP71Migration' => true, @@ -13,6 +31,7 @@ 'protected_to_private' => false, 'native_constant_invocation' => ['strict' => false], 'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => false], + 'header_comment' => ['header' => $fileHeaderComment], 'modernize_strpos' => true, ]) ->setRiskyAllowed(true) diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 04364c67c5369..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,123 +0,0 @@ -language: php - -dist: bionic - -git: - depth: 1 - -addons: - apt_packages: - - parallel - - zookeeperd - - libzookeeper-mt-dev - -matrix: - include: - - php: 8.0 - fast_finish: true - -cache: - directories: - - .phpunit - - ~/php-ext - -before_install: - - | - # General configuration - set -e - stty cols 120 - sudo sed -i 's/127\.0\.1\.1 localhost/127.0.0.1 localhost/' /etc/hosts - cp .github/composer-config.json "$(composer config home)/config.json" - - nanoseconds () { - local cmd="date" - local format="+%s%N" - local os=$(uname) - if hash gdate > /dev/null 2>&1; then - cmd="gdate" - elif [[ "$os" = Darwin ]]; then - format="+%s000000000" - fi - $cmd -u $format - } - export -f nanoseconds - - # tfold is a helper to create folded reports - tfold () { - local title="$PHP $1" - local fold=$(echo $title | sed -r 's/[^-_A-Za-z0-9]+/./g') - shift - local id=$(printf %08x $(( RANDOM * RANDOM ))) - local start=$(nanoseconds) - echo -e "travis_fold:start:$fold" - echo -e "travis_time:start:$id" - echo -e "\\e[1;34m$title\\e[0m" - - bash -xc "$*" 2>&1 - local ok=$? - local end=$(nanoseconds) - echo -e "\\ntravis_time:end:$id:start=$start,finish=$end,duration=$(($end-$start))" - (exit $ok) && - echo -e "\\e[32mOK\\e[0m $title\\n\\ntravis_fold:end:$fold" || - echo -e "\\e[41mKO\\e[0m $title\\n" - (exit $ok) - } - export -f tfold - - # tpecl is a helper to compile and cache php extensions - tpecl () { - local ext_name=$1 - local ext_so=$2 - local INI=$3 - local input=${4:-yes} - local ext_dir=$(php -r "echo ini_get('extension_dir');") - local ext_cache=~/php-ext/$(basename $ext_dir)/$ext_name - - if [[ -e $ext_cache/$ext_so ]]; then - echo extension = $ext_cache/$ext_so >> $INI - else - rm ~/.pearrc /tmp/pear 2>/dev/null || true - mkdir -p $ext_cache - echo $input | pecl -q install -f $ext_name && - cp $ext_dir/$ext_so $ext_cache - fi - } - export -f tpecl - - - | - # php.ini configuration - for PHP in $TRAVIS_PHP_VERSION $php_extra; do - INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini - echo date.timezone = Europe/Paris >> $INI - echo memory_limit = -1 >> $INI - echo default_socket_timeout = 10 >> $INI - echo session.gc_probability = 0 >> $INI - echo opcache.enable_cli = 1 >> $INI - echo apc.enable_cli = 1 >> $INI - done - find ~/.phpenv -name xdebug.ini -delete - - composer self-update - composer self-update --2 - - - | - # Install extra PHP extensions - for PHP in $TRAVIS_PHP_VERSION $php_extra; do - export PHP=$PHP - phpenv global $PHP - INI=~/.phpenv/versions/$PHP/etc/conf.d/travis.ini - if [[ $PHP != 8.* ]]; then - tfold ext.zookeeper tpecl zookeeper-0.7.2 zookeeper.so $INI - fi - done - -install: - - export COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -not -wholename '*/Bridge/PhpUnit/*' -printf '%h\n' | sort) - - export COMPOSER_ROOT_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+').x-dev - - composer update --no-progress --ansi - - ./phpunit install - -script: - - echo "$COMPONENTS" | parallel --gnu -j +3 "tfold {} ./phpunit --exclude-group tty,benchmark,intl-data {}" - - tfold src/Symfony/Component/Console.tty ./phpunit src/Symfony/Component/Console --group tty - - tfold src/Symfony/Bridge/Twig.tty ./phpunit src/Symfony/Bridge/Twig --group tty diff --git a/CHANGELOG-6.0.md b/CHANGELOG-6.0.md index 20675c834b94c..07005e3077334 100644 --- a/CHANGELOG-6.0.md +++ b/CHANGELOG-6.0.md @@ -7,6 +7,507 @@ in 6.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.0.0...v6.0.1 +* 6.0.19 (2023-01-24) + + * bug #49078 [Security/Http] Check tokens before loading users from providers (nicolas-grekas) + * bug #49077 [DependencyInjection] Fix named arguments when using ContainerBuilder before compilation (nicolas-grekas) + * bug #49031 [Cache] fix collecting cache stats when nesting computations (nicolas-grekas) + * bug #49046 Fix for Windows when projects are deployed on junctions/symlinks (nerdgod) + * bug #49025 [Notifier] [OvhCloud] handle invalid receiver (seferov) + * bug #48993 [VarDumper] Fix JS to expand / collapse (nicolas-grekas) + * bug #48983 Fix BC user_identifier support after deprecation username (vtsykun) + * bug #48986 [Validator] Fix Email validator logic (fabpot) + * bug #48969 [PropertyInfo] Fixes constructor extractor for mixed type (michael.kubovic) + * bug #48978 [Serializer] use method_exists() instead of catching reflection exceptions (xabbuh) + * bug #48937 [SecurityBundle] Fix using same handler for multiple authenticators (RobertMe) + * bug #48971 [DependencyInjection] Fix dump order of inlined deps (nicolas-grekas) + * bug #48966 [HttpClient] Let curl handle content-length headers (nicolas-grekas) + * bug #48968 [VarExporter] Fix exporting enums (nicolas-grekas) + * bug #48926 [DependencyInjection] Fix support for named arguments on non-autowired services (nicolas-grekas) + * bug #48943 [FrameworkBundle] Fix deprecation when accessing a "container.private" service from the test container (nicolas-grekas) + * bug #48931 [DependencyInjection] Fix dumping inlined withers (nicolas-grekas) + * bug #48898 [HttpClient] Move Http clients data collecting at a late level (pforesi) + * bug #48896 [DoctrineBridge] Fix detecting mapping with one line annotations (franmomu) + * bug #48916 [FrameworkBundle] restore call to addGlobalIgnoredName (alexislefebvre) + * bug #48917 [Config] Fix XML dump when node example is an array (alexandre-daubois) + * bug #48904 [Validator] Allow egulias/email-validator v4 (chalasr) + * bug #48831 [Uid] Fix validating nil and max uuid (fancyweb) + +* 6.0.18 (2022-12-29) + + * bug #48823 [Cache] Fix possibly null value passed to preg_match() in RedisTrait (chalasr) + * bug #48816 [Cache] Fix for RedisAdapter without auth parameter (rikvdh) + +* 6.0.17 (2022-12-28) + + * bug #48787 [PhpUnitBridge] Use verbose deprecation output for quiet types only when it reaches the threshold (ogizanagi) + * bug #48784 [Console] Correctly overwrite progressbars with different line count per step (ncharalampidis) + * bug #48801 [Form] Make `ButtonType` handle `form_attr` option (MatTheCat) + * bug #48791 [DependencyInjection] Fix deduplicating service instances in circular graphs (nicolas-grekas) + * bug #48771 [CssSelector] Fix escape patterns (fancyweb) + * bug #48711 [Cache] RedisTrait::createConnection does not pass auth value from redis sentinel cluster DSN (evgkord) + * bug #48724 [VarExporter] Fix exporting classes with __unserialize() but not __serialize() (fancyweb) + * bug #48746 [Validator] Fix IBAN format for Tunisia and Mauritania (smelesh) + * bug #48738 [Workflow] Allow spaces in place names so the PUML dump doesn't break (Kamil Musial) + * bug #48718 Compatibility with doctrine/annotations 2 (derrabus) + * bug #48651 [HttpKernel] AbstractSessionListener should not override the cache lifetime for private responses (rodmen) + * bug #48591 [DependencyInjection] Shared private services becomes public after a public service is accessed (alexpott) + * bug #48126 [Mailer] Include all transports' debug messages in RoundRobin transport exception (mixdf) + * bug #48635 [HttpFoundation] Use relative timestamps with MemcachedSessionHandler (tvlooy) + * bug #47979 [Cache] Fix dealing with ext-redis' multi/exec returning a bool (João Nogueira) + * bug #48612 [Messenger] [Amqp] Added missing rpc_timeout option (lyrixx) + * bug #48233 [Serializer] Prevent `GetSetMethodNormalizer` from creating invalid magic method call (klaussilveira) + * bug #48628 [HttpFoundation] Fix dumping array cookies (nicolas-grekas) + * bug #48048 [WebProfilerBundle] Fix dump header not being displayed (HypeMC) + * bug #47836 [HttpClient] TraceableHttpClient: increase decorator's priority (adpeyre) + * bug #48259 [FrameworkBundle] Allow configuring `framework.exceptions` with a config builder (MatTheCat) + * bug #48314 [Mime] Fix MessagePart serialization (Amunak) + * bug #48331 [Yaml] fix dumping top-level tagged values (xabbuh) + * bug #48615 Fix getting the name of closures on PHP 8.1.11+ (nicolas-grekas) + * bug #48618 [ErrorHandler] [DebugClassLoader] Fix some new return types support (fancyweb) + * bug #48421 [HttpFoundation] IPv4-mapped IPv6 addresses incorrectly rejected (bonroyage) + * bug #48501 [RateLimiter] Add `int` to `Reservation::wait()` (DaRealFreak) + * bug #48359 [VarDumper] Ignore \Error in __debugInfo() (fancyweb) + * bug #48482 [DependencyInjection] Revert "bug #48027 Don't autoconfigure tag when it's already set with attributes" (nicolas-grekas) + * bug #48335 [TwigBridge] Amend `MoneyType` twig to include a space (mogilvie) + * bug #48046 [WebProfilerBundle] Remove redundant code from logger template (HypeMC) + * bug #48292 [Security] [LoginLink] Throw InvalidLoginLinkException on missing parameter (MatTheCat) + +* 6.0.16 (2022-11-28) + + * bug #48333 [Yaml] parse unquoted digits in tag values as integers (xabbuh) + * bug #48330 [FrameworkBundle] do not wire the MercureTransportFactory if the MercureBundle is not enabled (xabbuh) + * bug #48262 [Notifier] [SMSBiuras] `true`/`false` mismatch for `test_mode` option (StaffNowa) + * bug #48273 [HttpKernel] Fix message for unresovable arguments of invokable controllers (fancyweb) + * bug #48251 [PropertyInfo] ignore const expressions read by phpdocumentor (xabbuh) + * bug #48224 [DependencyInjection] Process bindings in `ServiceLocatorTagPass` (MatTheCat) + * bug #48179 [Console] Support completion for bash functions (Chi-teck) + * bug #48217 [Console] Improve error message when shell is not detected in completion command (GromNaN) + * bug #48222 [Translation] [Lokalize] Configure `replace_breaks` to prevent issues with multilines translations (Kocal) + * bug #48210 [Console]  Fix signal handlers called after event listeners and skip exit (GromNaN) + * bug #48198 [Messenger] Fix time-limit check exception (alamirault) + * bug #48122 [PhpUnitBridge] Fix language deprecations incorrectly marked as direct (wouterj) + * bug #47998 [Console] Fix console `ProgressBar::override()` after manual `ProgressBar::cleanup()` (maxbeckers) + * bug #48173 [HttpClient] Handle Amp HTTP client v5 incompatibility gracefully (fancyweb) + * bug #48172 [HttpKernel] Don’t try to wire Response argument with controller.service_arguments (MatTheCat) + * bug #48085 [Messenger] Tell about messenger:consume invalid limit options (MatTheCat) + * bug #48120 [Messenger] Do not throw 'no handlers' exception when skipping handlers due to duplicate handling (wouterj) + * bug #48112 [HttpFoundation] Compare cookie with null value as empty string in ResponseCookieValueSame (fancyweb) + * bug #48119 [FrameworkBundle][Lock] Allow to disable lock without defining a resource (MatTheCat) + * bug #48093 [DependencyInjection] don't move locator tag for service subscriber (RobertMe) + * bug #48075 [Mailer] Stream timeout not detected fgets returns false (Sezil) + * bug #48092 Fix the notification email theme for asynchronously dispatched emails (krisbuist) + * bug #48097 Fix search scope when performing fallback mapping driver detection (spideyfusion) + * bug #48103 [HttpClient] Do not set http_version instead of setting it to null (Tetragramat) + * bug #48027 [DependencyInjection] Don't autoconfigure tag when it's already set with attributes (nicolas-grekas) + * bug #48050 [HttpFoundation] Check IPv6 is valid before comparing it (PhilETaylor) + +* 6.0.15 (2022-10-28) + + * bug #47990 [HttpClient] Fix retrying requests when the content is used by the strategy (nicolas-grekas) + * bug #48005 [ErrorHandler] s/
/
(PhilETaylor) + * bug #47907 [Console] Update Application.php (aleksandr-shevchenko) + * bug #47955 [Security][Serializer] Add missing args to trigger_deprecation (alamirault) + * bug #47932 Throw LogicException instead of Error when trying to generate logout-… (addiks) + * bug #47918 [Intl] Update the ICU data to 72.1 - 5.4 (jderusse) + * bug #47857 [HttpKernel] Fix empty request stack when terminating with exception (krzyc) + * bug #47879 [HttpClient] Fix buffering after calling AsyncContext::passthru() (nicolas-grekas, lubo13) + * bug #47878 [HttpKernel] Remove EOL when using error_log() in HttpKernel Logger (cyve) + * bug #47883 [Console] Fix error output on windows cli (Maximilian.Beckers) + * bug #47884 [Cache] Reserve numeric keys when doing memory leak prevention (simoheinonen) + * bug #47863 [DoctrineBridge] Allow doctrine/event-manager 2 (derrabus) + * bug #47831 [Messenger] Fix amqp socket lost (GurvanVgx) + * bug #47855 [Routing] TypeError in Router when using UrlGenerator (Maximilian.Beckers) + * bug #47822 [Mailer] fix: use message object from event (rogamoore) + * bug #47858 [DoctrineBridge] Implement `EventManager::getAllListeners()` (derrabus) + +* 6.0.14 (2022-10-12) + + * bug #47621 [Serializer] Allow getting discriminated type by class name (TamasSzigeti) + * bug #47833 [TwigBridge] Remove empty spaces between choices when using checkbox-inline or checkbox-switch (simondaigre) + * bug #47808 [HttpClient] Fix seeking in not-yet-initialized requests (nicolas-grekas) + * bug #47798 [DoctrineBridge] Fix auto mapping for bundles that contain only embeddables (jorissae) + * bug #47702 [Messenger] Fix default serializer not handling DateTime objects properly (barton-webwings) + * bug #47779 [Console] Fix `Helper::removeDecoration` hyperlink bug (greew) + * bug #47753 [Mime] sync message serializer code for forward-compatibility (xabbuh) + * bug #47763 [PropertyInfo] a readonly property must not be reported as being writable (xabbuh) + * bug #47731 [WebProfiler] Fix overflow issue in Forms panel (zolikonta) + * bug #46956 [FrameworkBundle] Allow to specify `null` for exception mapping configuration values (andrew-demb) + * bug #47746 [HttpFoundation] Fix BinaryFileResponse content type detection logic (X-Coder264) + * bug #47626 [Notifier] [Expo] Throw exception on error-response from expo api (sdrewergutland) + * bug #47317 [Security] Fix login url matching when app is not run with url rewriting or from a sub folder (sgehrig) + +* 6.0.13 (2022-09-30) + + * bug #47637 [FrameworkBundle] Fix passing `serializer.default_context` option to normalizers (wuchen90) + * bug #47695 [FrameworkBundle] Filter out trans paths that are covered by a parent folder path (natewiebe13) + * bug #45554 [Serializer] Fixed framework.serializer.default_context is not working for JsonEncoder (siganushka) + * bug #47547 [Ldap] Do not run ldap_set_option on failed connection (tatankat) + * bug #47635 [DependencyInjection] EnvPlaceholderParameterBag::get() can't return UnitEnum (jack.shpartko) + * bug #47578 [Security] Fix AbstractFormLoginAuthenticator return types (AndrolGenhald) + * bug #47614 [FrameworkBundle] Fix a phpdoc in mailer assertions (HeahDude) + * bug #47516 [HttpFoundation] Prevent BinaryFileResponse::prepare from adding content type if no content is sent (naitsirch) + * bug #47533 [Messenger] decode URL-encoded characters in DSN's usernames/passwords (xabbuh) + * bug #47530 [HttpFoundation] Always return strings from accept headers (ausi) + * bug #47523 [Uid] Ensure ULIDs are monotonic even when the time goes backward (nicolas-grekas) + * bug #47528 [Form] fix UUID tranformer (nicolas-grekas) + * bug #47488 [Security] Fix valid remember-me token exposure to the second consequent request (Ivan Kurnosov) + * bug #47518 [Uid] Fix validating UUID variant bits (nicolas-grekas) + * bug #47441 [HttpClient] [HttpClientBundle] Bugfix for delayed retryableHttpClient (martkop26) + * bug #47499 [Uid][Validator] Stop to first ULID format violation (ogizanagi) + * bug #47491 [HttpKernel] Prevent exception in RequestDataCollector if request stack is empty (aschempp) + * bug #47497 [Bridge] Fix mkdir() race condition in ProxyCacheWarmer (andrey-tech) + * bug #47415 [HttpClient] Psr18Client ignore invalid HTTP headers (nuryagdym) + * bug #47394 [Console] [Completion] Make bash completion run in non interactive mode (Seldaek) + * bug #47455 [Mime] Fix TextPart broken after being serialized (fabpot) + * bug #47423 [String] CamelCase/SnakeCase on uppercase word (mpiot) + * bug #47435 [HttpKernel] lock when writting profiles (nicolas-grekas) + * bug #47417 [WebProfilerBundle] Fix profile search bar link query params (HeahDude) + * bug #47437 [Mime] Fix email rendering when having inlined parts that are not related to the content (fabpot) + * bug #47434 [HttpFoundation] move flushing outside of Response::closeOutputBuffers (nicolas-grekas) + * bug #47351 [FrameworkBundle] Do not throw when describing a factory definition (MatTheCat) + * bug #47403 [Mailer] Fix edge cases in STMP transports (fabpot) + * bug #47372 [Console] Fix OutputFormatterStyleStack::getCurrent return type (alamirault) + * bug #47391 [LokaliseBridge] Fix push command --delete-missing options when there are no missing messages (rwionczek) + * bug #47368 [Security] Count remember me cookie parts before accessing the second (MatTheCat) + * bug #47358 Fix broken request stack state if throwable is thrown. (Warxcell) + * bug #47304 [Serializer] Fix caching context-aware encoders/decoders in ChainEncoder/ChainDecoder (Guite) + * bug #47329 Email image parts: regex for single closing quote (rr-it) + * bug #47335 [Security] [AbstractToken] getUserIdentifier() must return a string (mpiot) + * bug #47283 [HttpFoundation] Prevent accepted rate limits with no remaining token to be preferred over denied ones (MatTheCat) + * bug #47128 [Serializer] Throw InvalidArgumentException if the data needed in the constructor doesn't belong to a backedEnum (allison guilhem) + * bug #47273 [HttpFoundation] Do not send Set-Cookie header twice for deleted session cookie (X-Coder264) + * bug #47255 [Serializer] Fix get accessor regex in AnnotationLoader (jsor) + * bug #47238 [HttpKernel] Fix passing `null` to `\trim()` method in LoggerDataCollector (SVillette) + * bug #47216 [Translation] Crowdin provider throw Exception when status is 50x (alamirault) + * bug #47209 Always attempt to listen for notifications (goetas) + * bug #47211 [Validator] validate nested constraints only if they are in the same group (xabbuh) + * bug #47218 [Console] fix dispatch signal event check for compatibility with the contract interface (xabbuh) + * bug #47200 [Form] ignore missing keys when mapping DateTime objects to uninitialized arrays (xabbuh) + * bug #47189 [Validator] Add additional hint when `egulias/email-validator` needs to be installed (mpdude) + * bug #47195 [FrameworkBundle] fix writes to static $kernel property (xabbuh) + * bug #47185 [String] Fix snake conversion (simPod) + * bug #47175 [DowCrawler] Fix locale-sensitivity of whitespace normalization (nicolas-grekas) + * bug #47171 [TwigBridge] suggest to install the Twig bundle when the required component is already installed (xabbuh) + * bug #47169 [Serializer] Fix throwing right exception in ArrayDenormalizer with invalid type (norkunas) + * bug #47161 [Mailer] Fix logic (fabpot) + * bug #47157 [Messenger] Fix Doctrine transport on MySQL (nicolas-grekas) + * bug #47155 [Filesystem] Remove needless `mb_*` calls (HellFirePvP) + * bug #46190 [Translation] Fix translator overlapse (Xavier RENAUDIN) + * bug #47142 [Mailer] Fix error message in case of an STMP error (fabpot) + * bug #45333 [Console] Fix ConsoleEvents::SIGNAL subscriber dispatch (GwendolenLynch) + * bug #47145 [HttpClient] Fix shared connections not being freed on PHP < 8 (nicolas-grekas) + * bug #47143 [HttpClient] Fix memory leak when using StreamWrapper (nicolas-grekas) + * bug #47130 [HttpFoundation] Fix invalid ID not regenerated with native PHP file sessions (BrokenSourceCode) + * bug #47129 [FrameworkBundle] remove the ChatterInterface alias when the chatter service is removed (xabbuh) + +* 6.0.12 (2022-08-26) + + * bug #47372 [Console] Fix OutputFormatterStyleStack::getCurrent return type (alamirault) + * bug #47391 [LokaliseBridge] Fix push command --delete-missing options when there are no missing messages (rwionczek) + * bug #47368 [Security] Count remember me cookie parts before accessing the second (MatTheCat) + * bug #47358 Fix broken request stack state if throwable is thrown. (Warxcell) + * bug #47304 [Serializer] Fix caching context-aware encoders/decoders in ChainEncoder/ChainDecoder (Guite) + * bug #47329 Email image parts: regex for single closing quote (rr-it) + * bug #47335 [Security] [AbstractToken] getUserIdentifier() must return a string (mpiot) + * bug #47283 [HttpFoundation] Prevent accepted rate limits with no remaining token to be preferred over denied ones (MatTheCat) + * bug #47128 [Serializer] Throw InvalidArgumentException if the data needed in the constructor doesn't belong to a backedEnum (allison guilhem) + * bug #47273 [HttpFoundation] Do not send Set-Cookie header twice for deleted session cookie (X-Coder264) + * bug #47255 [Serializer] Fix get accessor regex in AnnotationLoader (jsor) + * bug #47238 [HttpKernel] Fix passing `null` to `\trim()` method in LoggerDataCollector (SVillette) + * bug #47216 [Translation] Crowdin provider throw Exception when status is 50x (alamirault) + * bug #47209 Always attempt to listen for notifications (goetas) + * bug #47211 [Validator] validate nested constraints only if they are in the same group (xabbuh) + * bug #47218 [Console] fix dispatch signal event check for compatibility with the contract interface (xabbuh) + * bug #47200 [Form] ignore missing keys when mapping DateTime objects to uninitialized arrays (xabbuh) + * bug #47189 [Validator] Add additional hint when `egulias/email-validator` needs to be installed (mpdude) + * bug #47195 [FrameworkBundle] fix writes to static $kernel property (xabbuh) + * bug #47185 [String] Fix snake conversion (simPod) + * bug #47175 [DowCrawler] Fix locale-sensitivity of whitespace normalization (nicolas-grekas) + * bug #47171 [TwigBridge] suggest to install the Twig bundle when the required component is already installed (xabbuh) + * bug #47169 [Serializer] Fix throwing right exception in ArrayDenormalizer with invalid type (norkunas) + * bug #47161 [Mailer] Fix logic (fabpot) + * bug #47157 [Messenger] Fix Doctrine transport on MySQL (nicolas-grekas) + * bug #47155 [Filesystem] Remove needless `mb_*` calls (HellFirePvP) + * bug #46190 [Translation] Fix translator overlapse (Xavier RENAUDIN) + * bug #47142 [Mailer] Fix error message in case of an STMP error (fabpot) + * bug #45333 [Console] Fix ConsoleEvents::SIGNAL subscriber dispatch (GwendolenLynch) + * bug #47145 [HttpClient] Fix shared connections not being freed on PHP < 8 (nicolas-grekas) + * bug #47143 [HttpClient] Fix memory leak when using StreamWrapper (nicolas-grekas) + * bug #47130 [HttpFoundation] Fix invalid ID not regenerated with native PHP file sessions (BrokenSourceCode) + * bug #47129 [FrameworkBundle] remove the ChatterInterface alias when the chatter service is removed (xabbuh) + +* 6.0.11 (2022-07-29) + + * bug #47069 [Security] Allow redirect after login to absolute URLs (Tim Ward) + * bug #47073 [HttpKernel] Fix non-scalar check in surrogate fragment renderer (aschempp) + * bug #47003 [Cache] Ensured that redis adapter can use multiple redis sentinel hosts (warslett) + * bug #43329 [Serializer] Respect default context in DateTimeNormalizer::denormalize (hultberg) + * bug #47070 [Messenger] Fix function name in TriggerSql on postgresql bridge to support table name with schema (zimny9932) + * bug #47086 Workaround disabled "var_dump" (nicolas-grekas) + * bug #40828 [BrowserKit] Merge fields and files recursively if they are multidimensional array (januszmk) + * bug #47010 [String] Fix `width` method in `AbstractUnicodeString` (TBoileau) + * bug #47048 [Serializer] Fix XmlEncoder encoding attribute false (alamirault) + * bug #46957 [HttpFoundation] Fix `\Stringable` support in `InputBag::get()` (chalasr) + * bug #47022 [Console] get full command path for command in search path (remicollet) + * bug #47000 [ErrorHandler] Fix return type patching for list and class-string pseudo types (derrabus) + * bug #43998 [HttpKernel] [HttpCache] Don't throw on 304 Not Modified (aleho) + * bug #46792 [Bridge] Corrects bug in test listener trait (magikid) + * bug #46985 [DoctrineBridge] Avoid calling `AbstractPlatform::hasNativeGuidType()` (derrabus) + * bug #46958 [Serializer] Ignore getter with required parameters (Fix #46592) (astepin) + * bug #46981 [Mime]  quote address names if they contain parentheses (xabbuh) + * bug #46960 [FrameworkBundle] Fail gracefully when forms use disabled CSRF (HeahDude) + * bug #46973 [DependencyInjection] Fail gracefully when attempting to autowire composite types (derrabus) + * bug #45884 [Serializer] Fix inconsistent behaviour of nullable objects in key/value arrays (phramz) + * bug #46963 [Mime] Fix inline parts when added via attachPart() (fabpot) + * bug #46968 [PropertyInfo] Make sure nested composite types do not crash ReflectionExtractor (derrabus) + * bug #46931 Flush backend output buffer after closing. (bradjones1) + * bug #46947 [Serializer] Prevent that bad Ignore method annotations lead to incorrect results (astepin) + * bug #46948 [Validator] : Fix "PHP Warning: Undefined array key 1" in NotCompromisedPasswordValidator (KevinVanSonsbeek) + * bug #46905 [BrowserKit] fix sending request to paths containing multiple slashes (xabbuh) + * bug #46244 [Validator] Fix traverse option on Valid constraint when used as Attribute (tobias-93) + * bug #42033 [HttpFoundation] Fix deleteFileAfterSend on client abortion (nerg4l) + * bug #46941 [Messenger] Fix calls to deprecated DBAL methods (derrabus) + * bug #46863 [Mime] Fix invalid DKIM signature with multiple parts (BrokenSourceCode) + * bug #46808 [HttpFoundation] Fix TypeError on null `$_SESSION` in `NativeSessionStorage::save()` (chalasr) + * bug #46811 [DoctrineBridge] Fix comment for type on Query::setValue (middlewares) (l-vo) + * bug #46790 [HttpFoundation] Prevent PHP Warning: Session ID is too long or contains illegal characters (BrokenSourceCode) + * bug #46800 Spaces in system temp folder path cause deprecation errors in php 8 (demeritcowboy) + * bug #46797 [Messenger] Ceil waiting time when multiplier is a float on retry (WissameMekhilef) + +* 6.0.10 (2022-06-26) + + * bug #46779 [String] Add an invariable word in french (lemonlab) + * bug #46765 [Serializer] Fix denormalization union types with constructor (Gwemox) + * bug #46769 [HttpKernel] Fix a PHP 8.1 deprecation notice in HttpCache (mpdude) + * bug #46760 Fix double authentication via RememberMe resulting in wrong RememberMe cookie being set in client (heiglandreas) + * bug #46735 [Messenger] Do not log the message object itself (ajardin) + * bug #46748 [Security] Fix legacy impersonation system (dunglas) + * bug #46747 Fix global state pollution between tests run with ApplicationTester (Seldaek) + * bug #46730 [Intl] Fix the IntlDateFormatter::formatObject signature (damienalexandre) + * bug #46668 [FrameworkBundle] Lower JsonSerializableNormalizer priority (aprat84) + * bug #46711 [PhpUnitBridge] Exclude from baseline generation deprecations triggered in legacy test (mondrake) + * bug #46678 [HttpFoundation] Update "[Session] Overwrite invalid session id" to only validate when files session storage is used (alexpott) + * bug #45861 [Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false (T-bond) + * bug #46676 [DoctrineBridge] Extend type guessing on enum fields (Gigino Chianese) + * bug #46699 [Cache] Respect $save option in all adapters (jrjohnson) + * bug #46697 [HttpKernel] Disable session tracking while collecting profiler data (nicolas-grekas) + * bug #46704 Allow passing null in twig_is_selected_choice (raziel057) + * bug #46684 [MonologBridge] Fixed support of elasticsearch 7.+ in ElasticsearchLogstashHandler (lyrixx) + * bug #46646 [Messenger] move resetting services at worker stopped into listener (Thomas Talbot) + * bug #46368 [Mailer] Fix for missing sender name in case with usage of the EnvelopeListener (bobahvas) + * bug #46603 [Mailer] Fix Error Handling for OhMySMTP Bridge (paul-oms) + * bug #46545 Fix getting class constraints on debug command (loic425) + * bug #46548 [Mime] Allow url as a path in the DataPart::fromPath (wkania) + * bug #46576 Fix choice filter error when loading mix of grouped and non-grouped choices (BreyndotEchse) + * bug #46594 [FrameworkBundle] Fix XML cache config (HeahDude) + * bug #46610 [Messenger] use the outermost wrapping DBAL connection (xabbuh) + * bug #46595 [Console] Escape in command name & description from getDefaultName() (ogizanagi) + * bug #46608 [Console] Fix deprecation when description is null (HypeMC) + * bug #46574 [Console] Escape in command name & description from PHP (getDefault* methods) (ogizanagi) + * bug #46577 [Serializer] Fix ignore attribute in Xml files (alamirault) + * bug #46565 [WebProfilerBundle] Fix dark theme selected line highlight color & reuse css vars (ogizanagi) + * bug #46525 [Serializer] Get attributeContext after converting name (zenas1210) + * bug #46535 [Mime] Check that the path is a file in the DataPart::fromPath (wkania) + * bug #46543 [Cache] do not pass null to strlen() (xabbuh) + * bug #46515 [PropertyInfo] Fix extracting int range type (norkunas) + * bug #46478 [Contracts] remove static cache from `ServiceSubscriberTrait` (kbond) + +* 6.0.9 (2022-05-27) + + * bug #46386 [Console]  Fix missing negative variation of negatable options in shell completion (GromNaN) + * bug #46448 [DependencyInjection] Fix "proxy" tag: resolve its parameters and pass it to child definitions (nicolas-grekas) + * bug #46442 [FrameworkBundle] Revert "bug #46125 Always add CacheCollectorPass (fancyweb)" (chalasr) + * bug #46443 [DoctrineBridge] Don't reinit managers when they are proxied as ghost objects (nicolas-grekas) + * bug #46427 [FrameworkBundle] fix wiring of annotations.cached_reader (nicolas-grekas) + * bug #46425 [DependencyInjection] Ignore unused bindings defined by attribute (nicolas-grekas) + * bug #46434 [FrameworkBundle] Fix BC break in abstract config commands (yceruto) + * bug #46424 [Form] do not accept array input when a form is not multiple (xabbuh) + * bug #46367 [Mime] Throw exception when body in Email attach method is not ok (alamirault) + * bug #46421 [VarDumper][VarExporter] Deal with DatePeriod->include_end_date on PHP 8.2 (nicolas-grekas) + * bug #46401 [Cache] Throw when "redis_sentinel" is used with a non-Predis "class" option (buffcode) + * bug #46414 Bootstrap 4 fieldset for row errors (konradkozaczenko) + * bug #46412 [FrameworkBundle] Fix dumping extension config without bundle (yceruto) + * bug #46382 [HttpClient] Honor "max_duration" when replacing requests with async decorators (nicolas-grekas) + * bug #46407 [Filesystem] Safeguard (sym)link calls (derrabus) + * bug #46098 [Form] Fix same choice loader with different choice values (HeahDude) + * bug #46380 [HttpClient] Add missing HttpOptions::setMaxDuration() (nicolas-grekas) + * bug #46377 [HttpKernel] Fix missing null type in `ErrorListener::__construct()` (chalasr) + * bug #46249 [HttpFoundation] [Session] Regenerate invalid session id (peter17) + * bug #46328 [Config] Allow scalar configuration in PHP Configuration (jderusse, HypeMC) + * bug #46366 [Mime] Add null check for EmailHeaderSame (magikid) + * bug #46364 [Config] Fix looking for single files in phars with GlobResource (nicolas-grekas) + * bug #46365 [HttpKernel] Revert "bug #46327 Allow ErrorHandler ^5.0 to be used" (nicolas-grekas) + * bug #46114 Fixes "Incorrectly nested style tag found" error when using multi-line header content (Perturbatio) + * bug #46325 [Ldap] Fix LDAP connection options (buffcode) + * bug #46341 Fix aliases handling in command name completion (Seldaek) + * bug #46317 [Security/Http] Ignore invalid URLs found in failure/success paths (nicolas-grekas) + * bug #46309 [Security] Fix division by zero (tvlooy) + * bug #46327 [HttpKernel] Allow ErrorHandler ^5.0 to be used in HttpKernel 4.4 (mpdude) + * bug #46297 [Serializer] Fix JsonSerializableNormalizer ignores circular reference handler in $context (BreyndotEchse) + * bug #46291 [Console] Suppress unhandled error in some specific use-cases. (rw4lll) + * bug #46302 [ErrorHandler] Fix list of tentative return types (nicolas-grekas) + * bug #45981 [Serializer][PropertyInfo] Fix support for "false" built-in type on PHP 8.2 (alexandre-daubois) + * bug #46277 [HttpKernel] Fix SessionListener without session in request (edditor) + * bug #46282 [DoctrineBridge] Treat firstResult === 0 like null (derrabus) + * bug #46239 [Translation] Refresh local translations on PushCommand if the provider has domains (Florian-B) + * bug #46276 [DependencyInjection] Fix lazyness of AutowiringFailedException (nicolas-grekas) + * bug #46278 [Workflow] Fix deprecated syntax for interpolated strings (nicolas-grekas) + * bug #46264 [Console] Better required argument check in InputArgument (jnoordsij) + * bug #46262 [EventDispatcher] Fix removing listeners when using first-class callable syntax (javer) + * bug #46216 [Form] fix populating single widget time view data with different timezones (xabbuh) + * bug #46221 [DomCrawler][VarDumper] Fix html-encoding emojis (nicolas-grekas) + * bug #46167 [VarExporter] Fix exporting DateTime objects on PHP 8.2 (nicolas-grekas) + +* 6.0.8 (2022-04-27) + + * bug #46154 [Mailer] Restore X-Transport after failure (zenas1210) + * bug #46178 [DependencyInjection] Properly declare #[When] as allowed on functions (nicolas-grekas) + * bug #46171 [VarDumper] Fix dumping floats on PHP8 (nicolas-grekas) + * bug #46170 Fix dumping enums on PHP 8.2 (nicolas-grekas) + * bug #46143 [Cache] Prevent fatal errors on php 8 when running concurrently with TagAwareAdapter v6.1 (sbelyshkin) + * bug #46149 Modify processing of uploaded files to be compatible with PHP 8.1 (p-golovin) + * bug #46125 [FrameworkBundle] Always add CacheCollectorPass (fancyweb) + * bug #46121 Fix "Notice: Undefined index: headers" in messenger with Oracle (rjd22) + * bug #46106 [String] Fix ansi escape sequences regex (fancyweb) + * bug #46097 [Routing] fix router base url when default uri has trailing slash (Tobion) + * bug #46054 [SecurityBundle] Use config's secret in remember-me signatures (jderusse) + * bug #46051 Don't replace symfony/security-guard (derrabus) + * bug #45980 [Finder] Add support of no-capture regex modifier in MultiplePcreFilterIterator (available from PHP 8.2) (alexandre-daubois) + * bug #45394 [HttpKernel] Use the existing session id if available. (trsteel88) + * bug #46008 [Workflow] Catch error when trying to get an uninitialized marking (lyrixx) + * bug #45171 [Translation] Allow usage of Provider domains if possible (welcoMattic) + * bug #40998 [Form] Use reference date in reverse transform (KDederichs) + * bug #46012 [HttpKernel] Fix Symfony not working on SMB share (qinshuze) + * bug #45983 [Messenger] DoctrineTransportFactory works with notify and decorated PostgreSQL driver (alamirault) + * bug #45992 [Mailer] Return-Path has higher priority for envelope address than From address (tpetry) + * bug #45998 [HttpClient] Fix sending content-length when streaming the body (nicolas-grekas) + * bug #45565 Fix table header seperator wrapping (alamirault) + * bug #45969 [Intl] Update the ICU data to 71.1 - 5.4 (jderusse) + * bug #45968 [Intl] Update the ICU data to 71.1 - 4.4 (jderusse) + * bug #45964 Fix use_cookies framework session configuration (alexander-schranz) + * bug #45947 [FrameworkBundle] [Command] Fix `debug:router --no-interaction` error … (WilliamBoulle) + * bug #45948 [RateLimiter] Adding default empty string value on Security::LAST_USERNAME (David-Crty) + * bug #45931 [Process] Fix Process::getEnv() when setEnv() hasn't been called before (asika32764) + * bug #45928 [ExpressionLanguage] Fix matching null against a regular expression (ausi) + * bug #45925 [RateLimiter] Add typecase to SlidingWindow::getExpirationTime (georgringer) + * bug #45910 [Messenger] reset connection on worker shutdown (SanderHagen) + * bug #45909 [Form][TwigBundle] reset Twig form theme resources between requests (xabbuh) + +* 6.0.7 (2022-04-02) + + * bug #45906 [HttpClient] on redirections don't send content related request headers (xabbuh) + * bug #45714 [Messenger] Fix cannot select FOR UPDATE from view on Oracle (rjd22) + * bug #45905 [TwigBridge] Fix the build (wouterj) + * bug #45888 [Messenger] Add mysql indexes back and work around deadlocks using soft-delete (nicolas-grekas) + * bug #45890 [PropertyInfo] PhpStanExtractor namespace missmatch issue (Korbeil) + * bug #45897 [TwigBridge] fix bootstrap_3_layout ChoiceType's expanded label_html (ytilotti) + * bug #45891 [HttpClient] Fix exporting objects with readonly properties (nicolas-grekas) + * bug #45875 [ExpressionLanguage] Fix matches when the regexp is not valid (fabpot) + * bug #44996 [RateLimiter] Always store SlidingWindows with an expiration set (Seldaek) + * bug #45870 [Validator] Fix File constraint invalid max size exception message (fancyweb) + * bug #45851 [Console] Fix exit status on uncaught exception with negative code (acoulton) + * bug #45733 [Validator] fix #43345 @Assert\DivisibleBy (CharlyPoppins) + * bug #45791 [Translation] [LocoProvider] Add content-type for POST translations (Tomasz Kusy) + * bug #45840 [Translation] Fix locales format in CrowdinProvider (ossinkine) + * bug #45491 [DoctrineBridge] Allow to use a middleware instead of DbalLogger (l-vo) + * bug #45839 [Translation] Fix intersect in TranslatorBag (ossinkine) + * bug #45838 [Serializer] Fix denormalizing union types (T-bond) + * bug #45804 Fix compatibility of ldap 6.0 with security 5.x (jderusse) + * bug #45808 [Security] Fixed TOCTOU in RememberMe cache token verifier (Ivan Kurnosov) + * bug #45816 [Mailer] Preserve case of headers (nicolas-grekas) + * bug #45787 [FrameworkBundle] Fix exit codes in debug:translation command (gndk) + * bug #45789 [Config] Fix using null values with config builders (HypeMC) + * bug #45814 [HttpClient] Let curl handle Content-Length headers (nicolas-grekas) + * bug #45813 [HttpClient] Move Content-Type after Content-Length (nicolas-grekas) + * bug #45737 [Lock] SemaphoreStore catching exception from sem_get (Triplkrypl) + * bug #45690 [Mailer] Use recipients in sendmail transport (HypeMC) + * bug #45720 [PropertyInfo] strip only leading `\` when unknown docType (EmilMassey) + * bug #45764 [RateLimiter] Fix rate serialization for long intervals (monthly and yearly) (smelesh) + * bug #45684 [Serializer] Fix nested deserialization_path computation when there is no metadata for the attribute (fancyweb) + * bug #44915 [Console] Fix compact table style to avoid outputting a leading space (Seldaek) + * bug #45691 [Mailer] fix: stringify from address for ses+api transport (everyx) + * bug #45696 Make FormErrorIterator generic (VincentLanglet) + * bug #45676 [Process] Don't return executable directories in PhpExecutableFinder (fancyweb) + * bug #45564 [symfony/mailjet-mailer] Fix invalid mailjet error managment (alamirault, fancyweb) + * bug #45697 [Security] Fix return value of `NullToken::getUser()` (chalasr) + * bug #45719 typehint of DkimOptions algorithm wrong (markusramsak) + * bug #45702 [Form] Fix the usage of the Valid constraints in array-based forms (stof) + * bug #45677 [DependencyInjection] fix `ServiceSubscriberTrait` bug where parent has `__call()` (kbond) + * bug #45678 [HttpClient] Fix reading proxy settings from dotenv when curl is used (nicolas-grekas) + * bug #45675 [Runtime] Fix passing $debug parameter to `ErrorHandler` (Kocal) + * bug #45629 [FrameworkBundle] Fix container:lint and #[Autoconfigure(binds: ...)] failing (LANGERGabrielle) + * bug #45671 [FrameworkBundle] Ensure container is reset between tests (nicolas-grekas) + * bug #45572 [HttpKernel] fix using Target attribute with controller arguments (kbond) + +* 6.0.6 (2022-03-05) + + * bug #45619 [redis-messenger] remove undefined array key warnings (PhilETaylor) + * bug #45637 [Cache] do not pass DBAL connections to PDO adapters (xabbuh) + * bug #45631 [HttpFoundation] Fix PHP 8.1 deprecation in `Response::isNotModified` (HypeMC) + * bug #45610 [HttpKernel] Guard against bad profile data (nicolas-grekas) + * bug #45532 Fix deprecations on PHP 8.2 (nicolas-grekas) + * bug #45595 [FrameworkBundle] Fix resetting container between tests (nicolas-grekas) + * bug #45590 [Console] Revert StringInput bc break from #45088 (bobthecow) + * bug #45585 [HttpClient] fix checking for unset property on PHP <= 7.1.4 (nicolas-grekas) + * bug #45583 [WebProfilerBundle] Fixes HTML syntax regression introduced by #44570 (xavismeh) + +* 6.0.5 (2022-02-28) + + * bug #45351 [WebProfilerBundle] Log section minor fixes (missing "notice" filter, log priority, accessibility) (Amunak) + * bug #44967 [Validator] Multi decimal to alpha for CssColor validator (tilimac) + * bug #45546 [Console] Fix null handling in formatAndWrap() (derrabus) + * bug #44570 [WebProfilerBundle] add nonces to profiler (garak) + * bug #44839 MailerInterface: failed exception contract when enabling messenger (Giorgio Premi) + * bug #45526 [Lock] Release Locks from Internal Store on Postgres waitAndSave* (chrisguitarguy) + * bug #45529 [DependencyInjection] Don't reset env placeholders during compilation (nicolas-grekas) + * bug #45527 [HttpClient] Fix overriding default options with null (nicolas-grekas) + * bug #45531 [Serializer] Fix passing null to str_contains() (Erwin Dirks) + * bug #42458 [Validator][Tests] Fix AssertingContextualValidator not throwing on remaining expectations (fancyweb) + * bug #45279 [Messenger] Fix dealing with unexpected payload in Redis transport (nicoalonso) + * bug #45496 [VarDumper] Fix dumping mysqli_driver instances (nicolas-grekas) + * bug #45495 [HttpFoundation] Fix missing ReturnTypeWillChange attributes (luxemate) + * bug #45482 [Cache] Add missing log when saving namespace (developer-av) + * bug #45479 [HttpKernel] Reset services between requests performed by KernelBrowser (nicolas-grekas) + * bug #44650 [Serializer] Make document type nodes ignorable (boenner) + * bug #45469 [SecurityBundle] fix autoconfiguring Monolog's ProcessorInterface (nicolas-grekas) + * bug #45414 [FrameworkBundle] KernelTestCase resets internal state on tearDown (core23) + * bug #45430 [Dotenv] Fix reading config for symfony/runtime when running dump command (nicolas-grekas) + * bug #45460 [Intl] fix wrong offset timezone PHP 8.1 (Lenny4) + * bug #45462 [HttpKernel] Fix extracting controller name from closures (nicolas-grekas) + * bug #45463 [Security/Http] Fix getting password-upgrader when user-loader is a closure (nicolas-grekas) + * bug #45424 [DependencyInjection] Fix type binding (sveneld) + * bug #45426 [Runtime] Fix dotenv_overload with commands (fancyweb) + * bug #44259 [Security] AccountStatusException::$user should be nullable (Cantepie) + * bug #45391 [Serializer] Ensuring end of line character apply with constructor settings in CSV encoder (bizley) + * bug #45323 [Serializer] Fix ignored callbacks in denormalization (benjaminmal) + * bug #45399 [FrameworkBundle] Fix sorting bug in sorting of tagged services by priority (Ahummeling) + * bug #45338 [Mailer] Fix string-cast of exceptions thrown by authenticator in EsmtpTransport (wikando-ck) + * bug #45339 [Cache] fix error handling when using Redis (nicolas-grekas) + * bug #45331 [Security]  Fix wrong authenticator class in debug logs (chalasr) + * bug #45322 Fix generic type for FormErrorIterator (akalineskou) + * bug #45281 [Cache] Fix connecting to Redis via a socket file (alebedev80) + * bug #45289 [FrameworkBundle] Fix log channel of TagAwareAdapter (fancyweb) + * bug #45306 [PropertyAccessor] Add missing TypeError catch (b1rdex) + * bug #44868 [DependencyInjection][FrameworkBundle] Fix using PHP 8.1 enum as parameters (ogizanagi) + * bug #45298 [HttpKernel] Fix FileLinkFormatter with empty xdebug.file_link_format (fancyweb) + * bug #45299 [DependencyInjection] Fix AsEventListener not working on decorators (LANGERGabrielle) + * bug #45302 [HttpKernel][WebProfilerBundle] Fixed error count by log not displayed in WebProfilerBundle (SVillette) + * bug #45219 [WebProfilerBundle] Fixes weird spacing in log message context/trace output (jennevdmeer) + * bug #45290 [Notifier] fix Microsoft Teams webhook url (christophkoenig) + * bug #45274 [Mailer] allow Mailchimp to handle multiple TagHeader's (kbond) + * bug #45275 [Mailer] ensure only a single tag can be used with Postmark (kbond) + * bug #45261 [HttpClient] Fix Content-Length header when possible (nicolas-grekas) + * bug #45263 [Routing] AnnotationDirectoryLoader::load() may return null (mhujer) + * bug #45258 [DependencyInjection] Don't dump polyfilled classes in preload script (nicolas-grekas) + * bug #38534 [Serializer] make XmlEncoder stateless thus reentrant (connorhu) + * bug #42253 [Form] Do not fix URL protocol for relative URLs (bogkonstantin) + * bug #45256 [DomCrawler] ignore bad charsets (nicolas-grekas) + * bug #45255 [PropertyAccess] Fix handling of uninitialized property of parent class (filiplikavcan) + * bug #45204 [Validator] Fix minRatio and maxRatio when getting rounded (alexander-schranz) + * bug #45240 [Console] Revert StringInput bc break from #45088 (bobthecow) + * bug #45243 [DoctrineBridge] Fix compatibility with doctrine/orm 3 in Id generators (ostrolucky) + * 6.0.4 (2022-01-29) * security #cve-2022-xxxx [FrameworkBundle] Enable CSRF in FORM by default (jderusse) @@ -492,4 +993,3 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c * feature #41298 [Notifier] Remove deprecation in slack-notifier (jschaedl) * feature #41203 [FrameworkBundle] Add autowiring alias for `HttpCache\StoreInterface` (nicolas-grekas) * feature #41282 Bump Symfony 6 to PHP 8 (nicolas-grekas) - diff --git a/CHANGELOG-6.1.md b/CHANGELOG-6.1.md new file mode 100644 index 0000000000000..6d8e5b86edd3d --- /dev/null +++ b/CHANGELOG-6.1.md @@ -0,0 +1,541 @@ +CHANGELOG for 6.1.x +=================== + +This changelog references the relevant changes (bug and security fixes) done +in 6.1 minor versions. + +To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash +To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.1.0...v6.1.1 + +* 6.1.12 (2023-02-01) + + * bug #49141 [HttpFoundation] Fix bad return type in IpUtils::checkIp4() (tristankretzer) + * bug #49126 [DependencyInjection] Fix order of arguments when mixing positional and named ones (nicolas-grekas) + * bug #49104 [HttpClient] Fix collecting data non-late for the profiler (nicolas-grekas) + * bug #49103 [Security/Http] Fix compat of persistent remember-me with legacy tokens (nicolas-grekas) + * security #cve-2022-24895 [Security/Http] Remove CSRF tokens from storage on successful login (nicolas-grekas) + * security #cve-2022-24894 [HttpKernel] Remove private headers before storing responses with HttpCache (nicolas-grekas) + +* 6.1.11 (2023-01-24) + + * bug #49078 [Security/Http] Check tokens before loading users from providers (nicolas-grekas) + * bug #49077 [DependencyInjection] Fix named arguments when using ContainerBuilder before compilation (nicolas-grekas) + * bug #49031 [Cache] fix collecting cache stats when nesting computations (nicolas-grekas) + * bug #49046 Fix for Windows when projects are deployed on junctions/symlinks (nerdgod) + * bug #49025 [Notifier] [OvhCloud] handle invalid receiver (seferov) + * bug #48993 [VarDumper] Fix JS to expand / collapse (nicolas-grekas) + * bug #48983 Fix BC user_identifier support after deprecation username (vtsykun) + * bug #48986 [Validator] Fix Email validator logic (fabpot) + * bug #48969 [PropertyInfo] Fixes constructor extractor for mixed type (michael.kubovic) + * bug #48978 [Serializer] use method_exists() instead of catching reflection exceptions (xabbuh) + * bug #48937 [SecurityBundle] Fix using same handler for multiple authenticators (RobertMe) + * bug #48971 [DependencyInjection] Fix dump order of inlined deps (nicolas-grekas) + * bug #48966 [HttpClient] Let curl handle content-length headers (nicolas-grekas) + * bug #48968 [VarExporter] Fix exporting enums (nicolas-grekas) + * bug #48933 [Validator] Fix bad handling of nulls when the 'fields' option of the Unique constraint is set (plfort) + * bug #48926 [DependencyInjection] Fix support for named arguments on non-autowired services (nicolas-grekas) + * bug #48943 [FrameworkBundle] Fix deprecation when accessing a "container.private" service from the test container (nicolas-grekas) + * bug #48931 [DependencyInjection] Fix dumping inlined withers (nicolas-grekas) + * bug #48898 [HttpClient] Move Http clients data collecting at a late level (pforesi) + * bug #48896 [DoctrineBridge] Fix detecting mapping with one line annotations (franmomu) + * bug #48916 [FrameworkBundle] restore call to addGlobalIgnoredName (alexislefebvre) + * bug #48917 [Config] Fix XML dump when node example is an array (alexandre-daubois) + * bug #48904 [Validator] Allow egulias/email-validator v4 (chalasr) + * bug #48831 [Uid] Fix validating nil and max uuid (fancyweb) + +* 6.1.10 (2022-12-29) + + * bug #48823 [Cache] Fix possibly null value passed to preg_match() in RedisTrait (chalasr) + * bug #48816 [Cache] Fix for RedisAdapter without auth parameter (rikvdh) + +* 6.1.9 (2022-12-28) + + * bug #48787 [PhpUnitBridge] Use verbose deprecation output for quiet types only when it reaches the threshold (ogizanagi) + * bug #48784 [Console] Correctly overwrite progressbars with different line count per step (ncharalampidis) + * bug #48801 [Form] Make `ButtonType` handle `form_attr` option (MatTheCat) + * bug #48791 [DependencyInjection] Fix deduplicating service instances in circular graphs (nicolas-grekas) + * bug #48771 [CssSelector] Fix escape patterns (fancyweb) + * bug #48711 [Cache] RedisTrait::createConnection does not pass auth value from redis sentinel cluster DSN (evgkord) + * bug #48724 [VarExporter] Fix exporting classes with __unserialize() but not __serialize() (fancyweb) + * bug #48746 [Validator] Fix IBAN format for Tunisia and Mauritania (smelesh) + * bug #48738 [Workflow] Allow spaces in place names so the PUML dump doesn't break (Kamil Musial) + * bug #48718 Compatibility with doctrine/annotations 2 (derrabus) + * bug #48681 [Console] Revert "bug #48089 Fix clear line with question in section (maxbeckers) (chalasr) + * bug #48651 [HttpKernel] AbstractSessionListener should not override the cache lifetime for private responses (rodmen) + * bug #48591 [DependencyInjection] Shared private services becomes public after a public service is accessed (alexpott) + * bug #48126 [Mailer] Include all transports' debug messages in RoundRobin transport exception (mixdf) + * bug #48089 [Console] Fix clear line with question in section (maxbeckers) + * bug #48602 [HtmlSanitizer] Fix HtmlSanitizer default configuration behavior for allowed schemes (Titouan Galopin) + * bug #48635 [HttpFoundation] Use relative timestamps with MemcachedSessionHandler (tvlooy) + * bug #47979 [Cache] Fix dealing with ext-redis' multi/exec returning a bool (João Nogueira) + * bug #48612 [Messenger] [Amqp] Added missing rpc_timeout option (lyrixx) + * bug #48233 [Serializer] Prevent `GetSetMethodNormalizer` from creating invalid magic method call (klaussilveira) + * bug #48628 [HttpFoundation] Fix dumping array cookies (nicolas-grekas) + * bug #48048 [WebProfilerBundle] Fix dump header not being displayed (HypeMC) + * bug #47836 [HttpClient] TraceableHttpClient: increase decorator's priority (adpeyre) + * bug #48259 [FrameworkBundle] Allow configuring `framework.exceptions` with a config builder (MatTheCat) + * bug #48314 [Mime] Fix MessagePart serialization (Amunak) + * bug #48331 [Yaml] fix dumping top-level tagged values (xabbuh) + * bug #48615 Fix getting the name of closures on PHP 8.1.11+ (nicolas-grekas) + * bug #48624 [ErrorHandler][HttpKernel] Fix reading the SYMFONY_IDE env var (nicolas-grekas) + * bug #48618 [ErrorHandler] [DebugClassLoader] Fix some new return types support (fancyweb) + * bug #48421 [HttpFoundation] IPv4-mapped IPv6 addresses incorrectly rejected (bonroyage) + * bug #48501 [RateLimiter] Add `int` to `Reservation::wait()` (DaRealFreak) + * bug #48359 [VarDumper] Ignore \Error in __debugInfo() (fancyweb) + * bug #48534 [FrameworkBundle] add `kernel.locale_aware` tag to `LocaleSwitcher` (kbond) + * bug #48482 [DependencyInjection] Revert "bug #48027 Don't autoconfigure tag when it's already set with attributes" (nicolas-grekas) + * bug #48346 [HttpKernel] In DateTimeValueResolver, convert previously defined date attribute to the expected class (GromNaN) + * bug #48335 [TwigBridge] Amend `MoneyType` twig to include a space (mogilvie) + * bug #48046 [WebProfilerBundle] Remove redundant code from logger template (HypeMC) + * bug #48292 [Security] [LoginLink] Throw InvalidLoginLinkException on missing parameter (MatTheCat) + +* 6.1.8 (2022-11-28) + + * bug #48333 [Yaml] parse unquoted digits in tag values as integers (xabbuh) + * bug #48330 [FrameworkBundle] do not wire the MercureTransportFactory if the MercureBundle is not enabled (xabbuh) + * bug #48262 [Notifier] [SMSBiuras] `true`/`false` mismatch for `test_mode` option (StaffNowa) + * bug #48273 [HttpKernel] Fix message for unresovable arguments of invokable controllers (fancyweb) + * bug #48251 [PropertyInfo] ignore const expressions read by phpdocumentor (xabbuh) + * bug #48224 [DependencyInjection] Process bindings in `ServiceLocatorTagPass` (MatTheCat) + * bug #48179 [Console] Support completion for bash functions (Chi-teck) + * bug #48217 [Console] Improve error message when shell is not detected in completion command (GromNaN) + * bug #48222 [Translation] [Lokalize] Configure `replace_breaks` to prevent issues with multilines translations (Kocal) + * bug #48210 [Console]  Fix signal handlers called after event listeners and skip exit (GromNaN) + * bug #48198 [Messenger] Fix time-limit check exception (alamirault) + * bug #48122 [PhpUnitBridge] Fix language deprecations incorrectly marked as direct (wouterj) + * bug #47998 [Console] Fix console `ProgressBar::override()` after manual `ProgressBar::cleanup()` (maxbeckers) + * bug #48173 [HttpClient] Handle Amp HTTP client v5 incompatibility gracefully (fancyweb) + * bug #48172 [HttpKernel] Don’t try to wire Response argument with controller.service_arguments (MatTheCat) + * bug #48085 [Messenger] Tell about messenger:consume invalid limit options (MatTheCat) + * bug #48120 [Messenger] Do not throw 'no handlers' exception when skipping handlers due to duplicate handling (wouterj) + * bug #48112 [HttpFoundation] Compare cookie with null value as empty string in ResponseCookieValueSame (fancyweb) + * bug #48119 [FrameworkBundle][Lock] Allow to disable lock without defining a resource (MatTheCat) + * bug #48110 [HttpKernel] Fix deprecation for DateTimeValueResolver with null on non-nullable argument (GromNaN) + * bug #48093 [DependencyInjection] don't move locator tag for service subscriber (RobertMe) + * bug #48075 [Mailer] Stream timeout not detected fgets returns false (Sezil) + * bug #48092 Fix the notification email theme for asynchronously dispatched emails (krisbuist) + * bug #48097 Fix search scope when performing fallback mapping driver detection (spideyfusion) + * bug #48103 [HttpClient] Do not set http_version instead of setting it to null (Tetragramat) + * bug #48027 [DependencyInjection] Don't autoconfigure tag when it's already set with attributes (nicolas-grekas) + * bug #48050 [HttpFoundation] Check IPv6 is valid before comparing it (PhilETaylor) + +* 6.1.7 (2022-10-28) + + * bug #47990 [HttpClient] Fix retrying requests when the content is used by the strategy (nicolas-grekas) + * bug #48005 [ErrorHandler] s/
/
(PhilETaylor) + * bug #47907 [Console] Update Application.php (aleksandr-shevchenko) + * bug #47955 [Security][Serializer] Add missing args to trigger_deprecation (alamirault) + * bug #47932 Throw LogicException instead of Error when trying to generate logout-… (addiks) + * bug #47918 [Intl] Update the ICU data to 72.1 - 5.4 (jderusse) + * bug #47857 [HttpKernel] Fix empty request stack when terminating with exception (krzyc) + * bug #47879 [HttpClient] Fix buffering after calling AsyncContext::passthru() (nicolas-grekas, lubo13) + * bug #47878 [HttpKernel] Remove EOL when using error_log() in HttpKernel Logger (cyve) + * bug #47854 [HttpClient] Don't override header if is x-www-form-urlencoded (Oipnet) + * bug #47883 [Console] Fix error output on windows cli (Maximilian.Beckers) + * bug #47884 [Cache] Reserve numeric keys when doing memory leak prevention (simoheinonen) + * bug #47863 [DoctrineBridge] Allow doctrine/event-manager 2 (derrabus) + * bug #47831 [Messenger] Fix amqp socket lost (GurvanVgx) + * bug #47855 [Routing] TypeError in Router when using UrlGenerator (Maximilian.Beckers) + * bug #47822 [Mailer] fix: use message object from event (rogamoore) + * bug #47858 [DoctrineBridge] Implement `EventManager::getAllListeners()` (derrabus) + +* 6.1.6 (2022-10-12) + + * bug #47621 [Serializer] Allow getting discriminated type by class name (TamasSzigeti) + * bug #47833 [TwigBridge] Remove empty spaces between choices when using checkbox-inline or checkbox-switch (simondaigre) + * bug #47808 [HttpClient] Fix seeking in not-yet-initialized requests (nicolas-grekas) + * bug #47798 [DoctrineBridge] Fix auto mapping for bundles that contain only embeddables (jorissae) + * bug #47702 [Messenger] Fix default serializer not handling DateTime objects properly (barton-webwings) + * bug #47764 [Serializer] fixed traceable decoration priorities (mtarld) + * bug #47779 [Console] Fix `Helper::removeDecoration` hyperlink bug (greew) + * bug #47753 [Mime] sync message serializer code for forward-compatibility (xabbuh) + * bug #47763 [PropertyInfo] a readonly property must not be reported as being writable (xabbuh) + * bug #47731 [WebProfiler] Fix overflow issue in Forms panel (zolikonta) + * bug #46956 [FrameworkBundle] Allow to specify `null` for exception mapping configuration values (andrew-demb) + * bug #47746 [HttpFoundation] Fix BinaryFileResponse content type detection logic (X-Coder264) + * bug #47626 [Notifier] [Expo] Throw exception on error-response from expo api (sdrewergutland) + * bug #47317 [Security] Fix login url matching when app is not run with url rewriting or from a sub folder (sgehrig) + +* 6.1.5 (2022-09-30) + + * bug #47703 [Mailer][Mailjet] Apply the default value of 512 for max depths (nurtext) + * bug #47637 [FrameworkBundle] Fix passing `serializer.default_context` option to normalizers (wuchen90) + * bug #47695 [FrameworkBundle] Filter out trans paths that are covered by a parent folder path (natewiebe13) + * bug #45554 [Serializer] Fixed framework.serializer.default_context is not working for JsonEncoder (siganushka) + * bug #47547 [Ldap] Do not run ldap_set_option on failed connection (tatankat) + * bug #47635 [DependencyInjection] EnvPlaceholderParameterBag::get() can't return UnitEnum (jack.shpartko) + * bug #47675 [HttpKernel] Use Accept-Language header even if there are no enabled locales (MatTheCat) + * bug #47578 [Security] Fix AbstractFormLoginAuthenticator return types (AndrolGenhald) + * bug #47614 [FrameworkBundle] Fix a phpdoc in mailer assertions (HeahDude) + * bug #47227 [Messenger] Support for custom handler method containing a Union type tagged with #[AsMessageHandler] (ArchitectNate) + * bug #47516 [HttpFoundation] Prevent BinaryFileResponse::prepare from adding content type if no content is sent (naitsirch) + * bug #47533 [Messenger] decode URL-encoded characters in DSN's usernames/passwords (xabbuh) + * bug #47530 [HttpFoundation] Always return strings from accept headers (ausi) + * bug #47529 [Routing] Reject v2 UUIDs (nicolas-grekas) + * bug #47523 [Uid] Ensure ULIDs are monotonic even when the time goes backward (nicolas-grekas) + * bug #47528 [Form] fix UUID tranformer (nicolas-grekas) + * bug #47488 [Security] Fix valid remember-me token exposure to the second consequent request (Ivan Kurnosov) + * bug #47518 [Uid] Fix validating UUID variant bits (nicolas-grekas) + * bug #47441 [HttpClient] [HttpClientBundle] Bugfix for delayed retryableHttpClient (martkop26) + * bug #47499 [Uid][Validator] Stop to first ULID format violation (ogizanagi) + * bug #47491 [HttpKernel] Prevent exception in RequestDataCollector if request stack is empty (aschempp) + * bug #47497 [Bridge] Fix mkdir() race condition in ProxyCacheWarmer (andrey-tech) + * bug #47415 [HttpClient] Psr18Client ignore invalid HTTP headers (nuryagdym) + * bug #47463 [Console] [Completion] Make fish completion run in non interactive mode (Seldaek) + * bug #47394 [Console] [Completion] Make bash completion run in non interactive mode (Seldaek) + * bug #47455 [Mime] Fix TextPart broken after being serialized (fabpot) + * bug #47423 [String] CamelCase/SnakeCase on uppercase word (mpiot) + * bug #47435 [HttpKernel] lock when writting profiles (nicolas-grekas) + * bug #47417 [WebProfilerBundle] Fix profile search bar link query params (HeahDude) + * bug #47437 [Mime] Fix email rendering when having inlined parts that are not related to the content (fabpot) + * bug #47434 [HttpFoundation] move flushing outside of Response::closeOutputBuffers (nicolas-grekas) + * bug #47351 [FrameworkBundle] Do not throw when describing a factory definition (MatTheCat) + * bug #47403 [Mailer] Fix edge cases in STMP transports (fabpot) + +* 6.1.4 (2022-08-26) + + * bug #47372 [Console] Fix OutputFormatterStyleStack::getCurrent return type (alamirault) + * bug #47391 [LokaliseBridge] Fix push command --delete-missing options when there are no missing messages (rwionczek) + * bug #47368 [Security] Count remember me cookie parts before accessing the second (MatTheCat) + * bug #47358 Fix broken request stack state if throwable is thrown. (Warxcell) + * bug #47304 [Serializer] Fix caching context-aware encoders/decoders in ChainEncoder/ChainDecoder (Guite) + * bug #47150 [Serializer] Revert deprecation of `ContextAwareEncoderInterface` and `ContextAwareDecoderInterface` (nicolas-grekas) + * bug #47329 Email image parts: regex for single closing quote (rr-it) + * bug #47335 [Security] [AbstractToken] getUserIdentifier() must return a string (mpiot) + * bug #47283 [HttpFoundation] Prevent accepted rate limits with no remaining token to be preferred over denied ones (MatTheCat) + * bug #47128 [Serializer] Throw InvalidArgumentException if the data needed in the constructor doesn't belong to a backedEnum (allison guilhem) + * bug #47273 [HttpFoundation] Do not send Set-Cookie header twice for deleted session cookie (X-Coder264) + * bug #47255 [Serializer] Fix get accessor regex in AnnotationLoader (jsor) + * bug #47238 [HttpKernel] Fix passing `null` to `\trim()` method in LoggerDataCollector (SVillette) + * bug #47216 [Translation] Crowdin provider throw Exception when status is 50x (alamirault) + * bug #47209 Always attempt to listen for notifications (goetas) + * bug #47211 [Validator] validate nested constraints only if they are in the same group (xabbuh) + * bug #47218 [Console] fix dispatch signal event check for compatibility with the contract interface (xabbuh) + * bug #47200 [Form] ignore missing keys when mapping DateTime objects to uninitialized arrays (xabbuh) + * bug #47189 [Validator] Add additional hint when `egulias/email-validator` needs to be installed (mpdude) + * bug #47195 [FrameworkBundle] fix writes to static $kernel property (xabbuh) + * bug #47185 [String] Fix snake conversion (simPod) + * bug #47175 [DowCrawler] Fix locale-sensitivity of whitespace normalization (nicolas-grekas) + * bug #47172 [Translation] Fix reading intl-icu domains with LocoProvider (nicolas-grekas) + * bug #47171 [TwigBridge] suggest to install the Twig bundle when the required component is already installed (xabbuh) + * bug #47169 [Serializer] Fix throwing right exception in ArrayDenormalizer with invalid type (norkunas) + * bug #47162 [Mailer] Fix error message in case of an SMTP error (fabpot) + * bug #47161 [Mailer] Fix logic (fabpot) + * bug #47157 [Messenger] Fix Doctrine transport on MySQL (nicolas-grekas) + * bug #47155 [Filesystem] Remove needless `mb_*` calls (HellFirePvP) + * bug #46190 [Translation] Fix translator overlapse (Xavier RENAUDIN) + * bug #47142 [Mailer] Fix error message in case of an STMP error (fabpot) + * bug #45333 [Console] Fix ConsoleEvents::SIGNAL subscriber dispatch (GwendolenLynch) + * bug #47145 [HttpClient] Fix shared connections not being freed on PHP < 8 (nicolas-grekas) + * bug #47143 [HttpClient] Fix memory leak when using StreamWrapper (nicolas-grekas) + * bug #47130 [HttpFoundation] Fix invalid ID not regenerated with native PHP file sessions (BrokenSourceCode) + * bug #47129 [FrameworkBundle] remove the ChatterInterface alias when the chatter service is removed (xabbuh) + +* 6.1.3 (2022-07-29) + + * bug #47069 [Security] Allow redirect after login to absolute URLs (Tim Ward) + * bug #47073 [HttpKernel] Fix non-scalar check in surrogate fragment renderer (aschempp) + * bug #46849 [HtmlSanitizer] Allow null for sanitizer option `allowed_link_hosts` and `allowed_media_hosts` (plfort) + * bug #47104 [Serializer] Fix wrong needsNormalization in TraceableEncoder (ostrolucky) + * bug #47003 [Cache] Ensured that redis adapter can use multiple redis sentinel hosts (warslett) + * bug #43329 [Serializer] Respect default context in DateTimeNormalizer::denormalize (hultberg) + * bug #47070 [Messenger] Fix function name in TriggerSql on postgresql bridge to support table name with schema (zimny9932) + * bug #47086 Workaround disabled "var_dump" (nicolas-grekas) + * bug #40828 [BrowserKit] Merge fields and files recursively if they are multidimensional array (januszmk) + * bug #47010 [String] Fix `width` method in `AbstractUnicodeString` (TBoileau) + * bug #47048 [Serializer] Fix XmlEncoder encoding attribute false (alamirault) + * bug #46957 [HttpFoundation] Fix `\Stringable` support in `InputBag::get()` (chalasr) + * bug #47022 [Console] get full command path for command in search path (remicollet) + * bug #47000 [ErrorHandler] Fix return type patching for list and class-string pseudo types (derrabus) + * bug #43998 [HttpKernel] [HttpCache] Don't throw on 304 Not Modified (aleho) + * bug #46792 [Bridge] Corrects bug in test listener trait (magikid) + * bug #46985 [DoctrineBridge] Avoid calling `AbstractPlatform::hasNativeGuidType()` (derrabus) + * bug #46958 [Serializer] Ignore getter with required parameters (Fix #46592) (astepin) + * bug #46981 [Mime]  quote address names if they contain parentheses (xabbuh) + * bug #46960 [FrameworkBundle] Fail gracefully when forms use disabled CSRF (HeahDude) + * bug #46973 [DependencyInjection] Fail gracefully when attempting to autowire composite types (derrabus) + * bug #45884 [Serializer] Fix inconsistent behaviour of nullable objects in key/value arrays (phramz) + * bug #46963 [Mime] Fix inline parts when added via attachPart() (fabpot) + * bug #46968 [PropertyInfo] Make sure nested composite types do not crash ReflectionExtractor (derrabus) + * bug #46931 Flush backend output buffer after closing. (bradjones1) + * bug #46947 [Serializer] Prevent that bad Ignore method annotations lead to incorrect results (astepin) + * bug #46948 [Validator] : Fix "PHP Warning: Undefined array key 1" in NotCompromisedPasswordValidator (KevinVanSonsbeek) + * bug #46905 [BrowserKit] fix sending request to paths containing multiple slashes (xabbuh) + * bug #46244 [Validator] Fix traverse option on Valid constraint when used as Attribute (tobias-93) + * bug #42033 [HttpFoundation] Fix deleteFileAfterSend on client abortion (nerg4l) + * bug #46941 [Messenger] Fix calls to deprecated DBAL methods (derrabus) + * bug #46863 [Mime] Fix invalid DKIM signature with multiple parts (BrokenSourceCode) + * bug #46808 [HttpFoundation] Fix TypeError on null `$_SESSION` in `NativeSessionStorage::save()` (chalasr) + * bug #46811 [DoctrineBridge] Fix comment for type on Query::setValue (middlewares) (l-vo) + * bug #46790 [HttpFoundation] Prevent PHP Warning: Session ID is too long or contains illegal characters (BrokenSourceCode) + * bug #46700 [HttpClient] Prevent "Fatal error" in data collector (fmata) + * bug #46800 Spaces in system temp folder path cause deprecation errors in php 8 (demeritcowboy) + * bug #46797 [Messenger] Ceil waiting time when multiplier is a float on retry (WissameMekhilef) + +* 6.1.2 (2022-06-26) + + * bug #46779 [String] Add an invariable word in french (lemonlab) + * bug #46765 [Serializer] Fix denormalization union types with constructor (Gwemox) + * bug #46769 [HttpKernel] Fix a PHP 8.1 deprecation notice in HttpCache (mpdude) + * bug #46760 Fix double authentication via RememberMe resulting in wrong RememberMe cookie being set in client (heiglandreas) + * bug #46766 Initially set user null. (mogilvie) + * bug #46735 [Messenger] Do not log the message object itself (ajardin) + * bug #46748 [Security] Fix legacy impersonation system (dunglas) + * bug #46747 Fix global state pollution between tests run with ApplicationTester (Seldaek) + * bug #46730 [Intl] Fix the IntlDateFormatter::formatObject signature (damienalexandre) + * bug #46668 [FrameworkBundle] Lower JsonSerializableNormalizer priority (aprat84) + * bug #46711 [PhpUnitBridge] Exclude from baseline generation deprecations triggered in legacy test (mondrake) + * bug #46678 [HttpFoundation] Update "[Session] Overwrite invalid session id" to only validate when files session storage is used (alexpott) + * bug #46665 [HttpClient] Fix Copy as curl with base uri (HypeMC) + * bug #46670 [HttpClient] Fix json encode flags usage in copy-as-curl generation (welcoMattic) + * bug #45861 [Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false (T-bond) + * bug #46676 [DoctrineBridge] Extend type guessing on enum fields (Gigino Chianese) + * bug #46699 [Cache] Respect $save option in all adapters (jrjohnson) + * bug #46697 [HttpKernel] Disable session tracking while collecting profiler data (nicolas-grekas) + * bug #46704 Allow passing null in twig_is_selected_choice (raziel057) + * bug #46684 [MonologBridge] Fixed support of elasticsearch 7.+ in ElasticsearchLogstashHandler (lyrixx) + * bug #46650 [WebProfilerBundle] Bump http-kernel requirement to ^6.1 (ostrolucky) + * bug #46646 [Messenger] move resetting services at worker stopped into listener (Thomas Talbot) + * bug #46611 [PropertyInfo] Fix multi phpdoc covered promoted properties (ostrolucky, simPod) + * bug #46368 [Mailer] Fix for missing sender name in case with usage of the EnvelopeListener (bobahvas) + * bug #46603 [Mailer] Fix Error Handling for OhMySMTP Bridge (paul-oms) + +* 6.1.1 (2022-06-09) + + * bug #46570 [HttpClient][WebProfilerBundle] Catch errors when encoding body for c… (Phillip Look) + * bug #46583 [HttpClient] Copy as curl fixes (HypeMC) + * bug #46625 [FrameworkBundle] Disable Serializer data collect by default (chalasr) + * bug #46545 Fix getting class constraints on debug command (loic425) + * bug #46548 [Mime] Allow url as a path in the DataPart::fromPath (wkania) + * bug #46576 Fix choice filter error when loading mix of grouped and non-grouped choices (BreyndotEchse) + * bug #46594 [FrameworkBundle] Fix XML cache config (HeahDude) + * bug #46610 [Messenger] use the outermost wrapping DBAL connection (xabbuh) + * bug #46595 [Console] Escape in command name & description from getDefaultName() (ogizanagi) + * bug #46608 [Console] Fix deprecation when description is null (HypeMC) + * bug #46586 [HttpKernel] Fix BackedEnumValueResolver already resolved enum value (janatjak) + * bug #46574 [Console] Escape in command name & description from PHP (getDefault* methods) (ogizanagi) + * bug #46577 [Serializer] Fix ignore attribute in Xml files (alamirault) + * bug #46565 [WebProfilerBundle] Fix dark theme selected line highlight color & reuse css vars (ogizanagi) + * bug #46553 [WebProfilerBundle] normalizer and encoder can be undefined in template (kor3k) + * bug #46538 [FrameworkBundle][HtmlSanitizer] Fix calling `allowStaticElements` when setting `allow_all_static_elements: true` (norkunas) + * bug #46525 [Serializer] Get attributeContext after converting name (zenas1210) + * bug #46535 [Mime] Check that the path is a file in the DataPart::fromPath (wkania) + * bug #46543 [Cache] do not pass null to strlen() (xabbuh) + * bug #46523 [HttpFoundation] Revert "Send `Content-Length` when calling `Response::send()` and the content is a non-empty string" (nicolas-grekas) + * bug #46526 [Serializer] Added missing __call to TraceableEncoder (danielburger1337) + * bug #46527 [Serializer] Forget partially collected traces (mtarld) + * bug #46515 [PropertyInfo] Fix extracting int range type (norkunas) + * bug #46511 [Serializer] Added missing __call to TraceableNormalizer and TraceableSerializer (danielburger1337) + * bug #46478 [Contracts] remove static cache from `ServiceSubscriberTrait` (kbond) + * bug #46480 [FrameworkBundle][TwigBundle] Fix registering html-sanitizer services (nicolas-grekas) + * bug #46475 [MonologBridge] ensure that the $response property is initialized before being read (xabbuh) + +* 6.1.0 (2022-05-27) + + * bug #46453 [PropertyInfo] Fix resolution of partially docblock covered constructors (ostrolucky) + * bug #46454 [ExpressionLanguage] Fix null-safe chaining (HypeMC) + * bug #46386 [Console]  Fix missing negative variation of negatable options in shell completion (GromNaN) + * bug #46387 [Console] Complete negatable options (Fish) (GromNaN) + * bug #46448 [DependencyInjection] Fix "proxy" tag: resolve its parameters and pass it to child definitions (nicolas-grekas) + * bug #46442 [FrameworkBundle] Revert "bug #46125 Always add CacheCollectorPass (fancyweb)" (chalasr) + * bug #46443 [DoctrineBridge] Don't reinit managers when they are proxied as ghost objects (nicolas-grekas) + * bug #46427 [FrameworkBundle] fix wiring of annotations.cached_reader (nicolas-grekas) + * bug #46425 [DependencyInjection] Ignore unused bindings defined by attribute (nicolas-grekas) + * bug #46434 [FrameworkBundle] Fix BC break in abstract config commands (yceruto) + * bug #46424 [Form] do not accept array input when a form is not multiple (xabbuh) + * bug #46367 [Mime] Throw exception when body in Email attach method is not ok (alamirault) + * bug #46421 [VarDumper][VarExporter] Deal with DatePeriod->include_end_date on PHP 8.2 (nicolas-grekas) + * bug #46401 [Cache] Throw when "redis_sentinel" is used with a non-Predis "class" option (buffcode) + * bug #46414 Bootstrap 4 fieldset for row errors (konradkozaczenko) + * bug #46412 [FrameworkBundle] Fix dumping extension config without bundle (yceruto) + * bug #46385 [HttpKernel] New bundle path convention when `AbstractBundle` is used (yceruto) + * bug #46382 [HttpClient] Honor "max_duration" when replacing requests with async decorators (nicolas-grekas) + * bug #46407 [Filesystem] Safeguard (sym)link calls (derrabus) + * bug #46098 [Form] Fix same choice loader with different choice values (HeahDude) + * bug #46380 [HttpClient] Add missing HttpOptions::setMaxDuration() (nicolas-grekas) + * bug #46377 [HttpKernel] Fix missing null type in `ErrorListener::__construct()` (chalasr) + * bug #46249 [HttpFoundation] [Session] Regenerate invalid session id (peter17) + * bug #46373 [HtmlSanitizer] Fix default config service definition (wouterj) + * bug #46328 [Config] Allow scalar configuration in PHP Configuration (jderusse, HypeMC) + * bug #46366 [Mime] Add null check for EmailHeaderSame (magikid) + * bug #46361 [PropertyInfo] Ignore empty doc-block for promoted properties in PhpStanExtractor (BoShurik) + * bug #46364 [Config] Fix looking for single files in phars with GlobResource (nicolas-grekas) + * bug #46365 [HttpKernel] Revert "bug #46327 Allow ErrorHandler ^5.0 to be used" (nicolas-grekas) + +* 6.1.0-RC1 (2022-05-14) + + * feature #46335 [Form][FrameworkBundle][TwigBundle] Add Twig filter, form-type extension and improve service definitions for HtmlSanitizer (nicolas-grekas) + * bug #46114 Fixes "Incorrectly nested style tag found" error when using multi-line header content (Perturbatio) + * bug #46325 [Ldap] Fix LDAP connection options (buffcode) + * bug #46341 Fix aliases handling in command name completion (Seldaek) + * bug #46317 [Security/Http] Ignore invalid URLs found in failure/success paths (nicolas-grekas) + * bug #46309 [Security] Fix division by zero (tvlooy) + * bug #46327 [HttpKernel] Allow ErrorHandler ^5.0 to be used in HttpKernel 4.4 (mpdude) + * bug #46310 [MonologBridge] Fix LevelName being removed in Monolog 3.0 (Seldaek) + * bug #46297 [Serializer] Fix JsonSerializableNormalizer ignores circular reference handler in $context (BreyndotEchse) + * bug #46291 [Console] Suppress unhandled error in some specific use-cases. (rw4lll) + * bug #46302 [ErrorHandler] Fix list of tentative return types (nicolas-grekas) + * bug #46293 [HttpClient] "debug" is missing if a request failed to even start (weaverryan) + * bug #45981 [Serializer][PropertyInfo] Fix support for "false" built-in type on PHP 8.2 (alexandre-daubois) + * feature #41676 [Console] Table vertical rendering (yoannrenard) + * bug #46277 [HttpKernel] Fix SessionListener without session in request (edditor) + * bug #46282 [DoctrineBridge] Treat firstResult === 0 like null (derrabus) + * bug #46239 [Translation] Refresh local translations on PushCommand if the provider has domains (Florian-B) + * bug #46274 [HtmlSanitizer] Fix node renderer handling of self-closing (void) elements (omniError) + * bug #46276 [DependencyInjection] Fix lazyness of AutowiringFailedException (nicolas-grekas) + * bug #46278 [Workflow] Fix deprecated syntax for interpolated strings (nicolas-grekas) + * bug #46264 [Console] Better required argument check in InputArgument (jnoordsij) + * bug #46272 [DependencyInjection] Fix resolving parameters found in #[Autowire] (nicolas-grekas) + * bug #46262 [EventDispatcher] Fix removing listeners when using first-class callable syntax (javer) + * feature #46153 [MonologBridge] Add support for Monolog 3 (Seldaek) + * bug #46199 [HttpKernel] Handle previously converted `DateTime` arguments (mbabker) + * bug #46216 [Form] fix populating single widget time view data with different timezones (xabbuh) + * bug #46221 [DomCrawler][VarDumper] Fix html-encoding emojis (nicolas-grekas) + * bug #46220 [Console] Fix fish completion script (wouterj) + * bug #46167 [VarExporter] Fix exporting DateTime objects on PHP 8.2 (nicolas-grekas) + +* 6.1.0-BETA2 (2022-04-27) + + * feature #45282 [Serializer] Support canners in object normalizer (rmikalkenas) + * feature #46157 [Routing] Remove variadic constructor signature (wouterj) + * bug #46154 [Mailer] Restore X-Transport after failure (zenas1210) + * bug #46178 [DependencyInjection] Properly declare #[When] as allowed on functions (nicolas-grekas) + * bug #46171 [VarDumper] Fix dumping floats on PHP8 (nicolas-grekas) + * bug #46170 Fix dumping enums on PHP 8.2 (nicolas-grekas) + * bug #46143 [Cache] Prevent fatal errors on php 8 when running concurrently with TagAwareAdapter v6.1 (sbelyshkin) + * bug #45896 [Cache] Optimize caching of tags (sbelyshkin) + * bug #46149 Modify processing of uploaded files to be compatible with PHP 8.1 (p-golovin) + * feature #46112 [DependencyInjection] Rename `#[InnerService]` to `#[MapDecorated]` (chalasr) + * bug #46125 [FrameworkBundle] Always add CacheCollectorPass (fancyweb) + * feature #45989 [FrameworkBundle] deprecate not setting http_method_override (Tobion) + * feature #46042 [Routing] Add params variable to condition expression (HypeMC) + * feature #46115 [FrameworkBundle] Add support for route attributes in kernel controller methods (dunglas) + * bug #46121 Fix "Notice: Undefined index: headers" in messenger with Oracle (rjd22) + * feature #45834 [DependencyInjection] add AsDecorator class attribute and InnerService parameter attribute (Jean-Beru) + * bug #46106 [String] Fix ansi escape sequences regex (fancyweb) + * feature #46056 [PropertyInfo] Add support for promoted properties in PhpStanExtractor (simPod) + * feature #46047 [Notifier] smsapi - send messages in test mode (Patryk Kozłowski) + * bug #46097 [Routing] fix router base url when default uri has trailing slash (Tobion) + * feature #46052 [TwigBundle] Deprecate option "autoescape", use "autoescape_service[_method]" instead (nicolas-grekas) + * bug #46054 [SecurityBundle] Use config's secret in remember-me signatures (jderusse) + * feature #45528 [Routing] Add Requirement, a collection of universal regular-expressions constants to use as route parameter requirements (fancyweb) + * bug #46051 Don't replace symfony/security-guard (derrabus) + +* 6.1.0-BETA1 (2022-04-15) + + * feature #44798 [FrameworkBundle] Integrate the HtmlSanitizer component (tgalopin, wouterj) + * feature #46045 [Translation] Improve LocaleSwitcher a bit (nicolas-grekas) + * feature #42403 [Validator] Define which collection keys should be checked for uniqueness (wkania) + * feature #44405 [Routing] Allow using services in the route condition (renanbr) + * feature #46009 [FrameworkBundle] Add support for first-class callable route controller in MicroKernelTrait (fancyweb) + * feature #44155 [FrameworkBundle] Add semaphore configuration (jderusse) + * feature #45803 [Routing] Add EnumRequirement to help generate route requirements from a \BackedEnum (fancyweb) + * feature #45724 [FrameworkBundle] Add support to set BinaryFileResponse::trustXSendfileTypeHeader over config (alexander-schranz) + * feature #45092 [HttpFoundation] Send `Content-Length` when calling `Response::send()` and the content is a non-empty string (nicolas-grekas) + * feature #45967 [Messenger] Consume a PSR-14 dispatcher for dispatching events (derrabus) + * feature #45951 [Notifier] [OvhCloud] Add `no_stop_clause` to DSN (alamirault) + * feature #45795 [ExpressionLanguage] Add support for null-safe operator (mytuny) + * feature #45605 [Form] Add prototype_options to CollectionType (michaelKaefer) + * feature #45912 [ExpressionLanguage] Add some more operators (fabpot) + * feature #45656 [Serializer] Add serializer profiler (mtarld) + * feature #45072 [Validator] Allow creating constraints with required arguments (norkunas) + * feature #43239 [Finder] Look for gitignore patterns up to git root (julienfalque) + * feature #45845 [TwigBundle]  Pre-compile only *.twig files in cache warmup (GromNaN) + * feature #44446 [Mailer] Improve extensibility of `EsmtpTransport` (ampaze) + * feature #45226 [PhpUnitBridge] Add option `ignoreFile` to configure a file that lists deprecation messages to ignore (mondrake) + * feature #43163 [Messenger] Add Redis Sentinel support (norbertschultheisz) + * feature #43701 [HttpKernel] Simplifying Bundle/Extension config definition (yceruto) + * feature #45873 [HttpFoundation] Allow dynamic session "ttl" when using a remote storage (nicolas-grekas) + * feature #45878 [DependencyInjection] Add argument type `closure` to help passing closures to services (nicolas-grekas) + * feature #44898 [Ldap] LDAP authentication should return a meaningful error when the LDAP server is unavailable (Jayfrown) + * feature #45090 [Validator] Improve Image constraint invalid mime type message (fancyweb) + * feature #42997 [Cache] Improve reliability and performance of `TagAwareAdapter` by making tag versions an integral part of item value (Sergey Belyshkin, nicolas-grekas) + * feature #45512 [DependencyInjection] Allow using expressions as service factories (nicolas-grekas, jvasseur) + * feature #45273 [Messenger] Allow AsMessageHandler attribute on methods (mjpvandenberg, fabpot) + * feature #44284 [SecurityBundle] Display the inherited roles of the logged-in user in the WDT (jmsche) + * feature #44303 Add Engagespot bridge (danut007ro) + * feature #44532 Handle CSV DSN in ZookeeperStore (qkdreyer) + * feature #45047 [Notifier] Use Importance level to set flash message type (benr77, fabpot) + * feature #45166 [HttpFoundation] add stale while revalidate cache header (remieuronews) + * feature #45195 [Notifier] Add Sendberry notifier bridge (StaffNowa) + * feature #45793 [FrameworkBundle][Translation] add `LocaleSwitcher` service (kbond) + * feature #45833 [HttpKernel] Add Http Status 423 LockedHttpException (xosofox) + * feature #45705 [FrameworkBundle] Deprecate the messenger.reset_on_message config option (upyx) + * feature #45812 [HttpClient] Improve default content-type handling (nicolas-grekas) + * feature #45783 [DependencyInjection] adjust `Autowire` attribute implementation (kbond) + * feature #44171 [Config] Add comment on array methods (jderusse) + * feature #45657 [DependencyInjection] add `Autowire` parameter attribute (kbond) + * feature #45725 [Finder] Fix SplFileInfo PHPDoc (InvisibleSmiley) + * feature #44948 [Console] Add completion values to input definition (GromNaN) + * feature #45745 [ErrorHandler][HttpKernel] Read SYMFONY_IDE to render exception in case of fatal error (GromNaN) + * feature #45765 Mailer - Display email recipients in Profiler (raziel057) + * feature #45094 Add generics to ArgumentMetadata::getAttributes (Seldaek) + * feature #45761 Throw access denied if CurrentUser cannot be resolved instead of a 500 (Seldaek) + * feature #45680 [DependencyInjection] use `#[Required]` for `ServiceSubscriberTrait::setContainer()` (kbond) + * feature #45624 [Config] Allow using environment variables in `EnumNode` (ecourtial) + * feature #45484 Make constraint violation interfaces stringable (HypeMC) + * feature #43931 [HttpClient][WebProfilerBundle] Add button to copy a request as a cURL command (Deuchnord) + * feature #45515 [BrowserKit] Add `toArray` to `Response` (HypeMC) + * feature #45658 [Routing] Avoid double encoded slashes in query parameters (usu) + * feature #45062 [PropertyInfo] Add PHP 8.0 promoted properties `@param` mutation support to PhpDocExtractor (raphaelvoisin) + * feature #44522 [Messenger] add TransportMessageIdStamp to RedisSender (GaryPEGEOT) + * feature #45623 [Validator] Deprecate constraint "ExpressionLanguageSyntax", use "ExpressionSyntax" instead (mpiot) + * feature #45563 Deprecate requiring the "symfony/symfony" package (nicolas-grekas) + * feature #45616 [HttpClient] Remove credentials from requests redirected to same host but different port (GromNaN) + * feature #45377 Bump minimum version of PHP to 8.1 (nicolas-grekas) + * feature #45421 [Translation] Add the possibilty to export xliff translation with the .xliff suffix (DanielBadura) + * feature #45152 Ability to customize payload when sending mail through mailjet+api (gam6itko) + * feature #44665 [HttpKernel] Add the UidValueResolver argument value resolver (fancyweb) + * feature #44073 [ExpressionLanguage] Support lexing numbers with underscores and decimals with no leading zero (fancyweb) + * feature #44721 [Serializer] Deprecate support for abstract uid denormalization in UidNormalizer (fancyweb) + * feature #44615 [Routing] Support the "attribute" type (alias of "annotation") in annotation loaders (fancyweb) + * feature #45265 [HttpKernel] Add Profiler::isEnabled() method (Bilge) + * feature #45449 [Mime] Added getter for "TextPart::$name" (MasterRO94) + * feature #45402 make Message classes extensible (bitgandtter) + * feature #45476 [HttpKernel] Deprecate StreamedResponseListener, it serves no purpose anymore (nicolas-grekas) + * feature #45436 [Messenger] Support setting `connection_name` for AMQP (a.dmitryuk) + * feature #45450 [DependencyInjection] Add an env function to DI expression language (jvasseur) + * feature #45388 [Mailer] Allow manually start() of SmtpTransport (jannick-holm) + * feature #45376 [Mime] Fix embed logic for background attributes (flack) + * feature #45360 [ErrorHandler] trigger deprecations for ``@final`` properties (nicolas-grekas, fancyweb) + * feature #45371 [Validator] Deprecate `Constraint::$errorNames` in favor of `Constraint::ERROR_NAMES` (nicolas-grekas) + * feature #44692 [Cache][FrameworkBundle] add `cache:pool:invalidate-tags` command (kbond) + * feature #45361 [Console] Deprecate the `$defaultName` property (derrabus) + * feature #45313 [Cache] Add support for ACL auth in RedisAdapter (gam6itko) + * feature #45303 [ErrorHandler] Report overridden @final constants (fancyweb) + * feature #44484 [Translation] [Loco] Send `If-Modified-Since` header when possible (Kocal) + * feature #45307 [Mailer] Allow manually stop() of SmtpTransport (dvaeversted) + * feature #43973 [Serializer] Add context builders (mtarld) + * feature #45222 [Mailer] Implement EmailTags for Amazon Mailer (driesvints, kbond) + * feature #44670 [SecurityBundle] Allow to specify a RequestMatcher directly in an ACL definition (TristanPouliquen) + * feature #45139 [Notifier] smsapi-notifier `fast` option to sending message with the highest priority (marphi) + * feature #45155 [Serializer] Set context annotation as not final (benjaminmal) + * feature #44503 [FrameworkBundle] Allow PHP configuration in config/packages by default (dreadnip) + * feature #45101 [Form] Add inputmode attribute on NumberType (welcoMattic) + * feature #45075 [Routing] Enrich MissingMandatoryParametersException (adrienlucas) + * feature #45064 [Messenger] Add sessionToken option to SQS transport (filkaris) + * feature #44917 [Mailer] Add downloadable attachments to profiler (dbrekelmans) + * feature #45054 [Routing] Allow using UTF-8 parameter names (nicolas-grekas) + * feature #44360 [Notifier] [Bridge] [KazInfoTeh] added the bridge (taranovegor) + * feature #44874 [Notifier] Added 46elks notifier bridge (jongotlin) + * feature #44913 [Notifier] Add Orange SMS bridge (enigma972) + * feature #44971 [Messenger] Resolve handled classes when only method in tag is provided (angelov) + * feature #43982 [Messenger][Serializer] Deprecate "context aware" interfaces (mtarld) + * feature #44790 [Serializer] Give more hints when an attribute is not correctly used (lyrixx) + * feature #44831 [HttpKernel] Add a controller argument resolver for backed enums (ogizanagi) + * feature #44589 [Messenger] add SerializedMessageStamp (nikophil) + * feature #41750 [Yaml] Double-quote strings with single quote marks (Ostrzyciel) + * feature #44774 Add `exclude` to `TaggedIterator` and `TaggedLocator` (ruudk) + * feature #44681 [HtmlSanitizer] Introduce HtmlSanitizer component (tgalopin) + * feature #44311 [Mime] add DraftEmail (kbond) + * feature #44746 [Console] Add method `__toString()` to `InputInterface` (boesing) + * feature #44568 [HttpClient] Allow yielding Exception from MockResponse's $body to mock transport errors (fancyweb) + * feature #44672 [Translation] Translatable parameters (sylfabre) + * feature #44451 [PropertyInfo] Add support for phpDocumentor and PHPStan pseudo-types (EmilMassey) + * feature #44575 [Framework] Read env var SYMFONY_IDE by default for framework.ide (GromNaN) + * feature #43641 [Console] Issue 43602 : Add fish completion (guillaume-a) + * feature #44150 [Assets] Accept empty `base_url`, in order to simplify local dev configuration. (GromNaN) + * feature #44137 [Mailer] [Mailgun] Allow multiple TagHeaders with MailgunApiTransport (starred-gijs) + * feature #44543 [HttpFoundation] Update cookie date time format (chapterjason) + * feature #44483 [HttpKernel][WebProfilerBundle] adding xdebug_info page to webprofilerbundle (chr-hertel) + diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d287e27ee871e..016a12f53a9c9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -6,1085 +6,1302 @@ Symfony is the result of the work of many people who made the code better. The Symfony Connect username in parenthesis allows to get more information - Fabien Potencier (fabpot) - Nicolas Grekas (nicolas-grekas) - - Christian Flothmann (xabbuh) - Alexander M. Turek (derrabus) + - Christian Flothmann (xabbuh) + - Robin Chalas (chalas_r) - Bernhard Schussek (bschussek) - Tobias Schultze (tobion) - - Robin Chalas (chalas_r) - - Christophe Coevoet (stof) - - Wouter De Jong (wouterj) + - Thomas Calvet (fancyweb) - Jérémy DERUSSÉ (jderusse) - Grégoire Pineau (lyrixx) + - Wouter de Jong (wouterj) - Maxime Steinhausser (ogizanagi) - Kévin Dunglas (dunglas) + - Christophe Coevoet (stof) - Jordi Boggiano (seldaek) - - Thomas Calvet (fancyweb) + - Roland Franssen (ro0) - Victor Berchet (victor) + - Yonel Ceruto (yonelceruto) + - Tobias Nyholm (tobias) - Javier Eguiluz (javier.eguiluz) + - Oskar Stark (oskarstark) - Ryan Weaver (weaverryan) - - Roland Franssen (ro0) - - Jakub Zalas (jakubzalas) - Johannes S (johannes) + - Jakub Zalas (jakubzalas) - Kris Wallsmith (kriswallsmith) - - Tobias Nyholm (tobias) - - Yonel Ceruto González (yonelceruto) - - Oskar Stark (oskarstark) - Hugo Hamon (hhamon) - - Ait Boudad Abdellatif (aitboudad) + - Hamza Amrouche (simperfit) - Samuel ROZE (sroze) - - Romain Neutron (romain) - Pascal Borreli (pborreli) - Jules Pietri (heah) + - Romain Neutron - Joseph Bielawski (stloyd) - - Amrouche Hamza (simperfit) - - Karma Dordrak (drak) + - Drak (drak) + - Abdellatif Ait boudad (aitboudad) + - Jan Schädlich (jschaedl) - Lukas Kahwe Smith (lsmith) + - Jérôme Tamarelle (gromnan) - Martin Hasoň (hason) + - Kevin Bond (kbond) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - - Jan Schädlich (jschaedl) - - Igor Wiedler (igorw) - - Eriksen Costa (eriksencosta) - - Kevin Bond (kbond) - - Ener-Getick (energetick) - - Sarah Khalil (saro0h) - - Jérôme Tamarelle (gromnan) - - Pierre du Plessis (pierredup) - - Vasilij Duško (staff) + - Igor Wiedler + - HypeMC (hypemc) - Valentin Udaltsov (vudaltsov) - - Iltar van der Berg (kjarli) - - Jonathan Wage (jwage) + - Vasilij Duško (staff) - Matthias Pigulla (mpdude) - - Diego Saint Esteben (dosten) + - Laurent VOULLEMIER (lvo) + - Antoine Makdessi (amakdessi) + - Pierre du Plessis (pierredup) - Grégoire Paris (greg0ire) + - Gabriel Ostrolucký (gadelat) + - Jonathan Wage (jwage) + - Alexandre Daubois (alexandre-daubois) + - Titouan Galopin (tgalopin) + - David Maicher (dmaicher) + - Alexander Schranz (alexander-schranz) - Alexandre Salomé (alexandresalome) - - William Durand (couac) + - William DURAND - ornicar - - Titouan Galopin (tgalopin) - - Konstantin Myakshin (koc) - Dany Maillard (maidmaid) - - Francis Besset (francisbesset) + - Mathieu Santostefano (welcomattic) + - Eriksen Costa + - Diego Saint Esteben (dosten) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - - Laurent VOULLEMIER (lvo) + - Gábor Egyed (1ed) + - Francis Besset (francisbesset) - Vasilij Dusko | CREATION - Bulat Shakirzyanov (avalanche123) - - David Maicher (dmaicher) - - Gábor Egyed (1ed) - - gadelat (gadelat) - - Saša Stamenković (umpirsky) - - Peter Rehm (rpet) - - Henrik Bjørnskov (henrikbjorn) - - Miha Vrhovnik - - Antoine M (amakdessi) - - Diego Saint Esteben (dii3g0) + - Iltar van der Berg + - Miha Vrhovnik (mvrhov) - Mathieu Piot (mpiot) - - Konstantin Kudryashov (everzet) + - Saša Stamenković (umpirsky) + - Antoine Lamirault + - Alex Pott + - Mathieu Lechat (mat_the_cat) + - Vincent Langlet (deviling) + - Guilhem N (guilhemn) - Vladimir Reznichenko (kalessil) + - Sarah Khalil (saro0h) + - Tomas Norkūnas (norkunas) + - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) + - Eriksen Costa - Florin Patan (florinpatan) - - Jáchym Toušek (enumag) - - Alex Pott - - Michel Weimerskirch (mweimerskirch) + - Peter Rehm (rpet) + - Henrik Bjørnskov (henrikbjorn) + - David Buchmann (dbu) + - Konstantin Myakshin (koc) - Andrej Hudec (pulzarraider) + - Julien Falque (julienfalque) + - Massimiliano Arione (garak) + - Douglas Greenshields (shieldo) - Christian Raue - - Issei Murasawa (issei_m) - - Eric Clemmons (ericclemmons) + - Fran Moreno (franmomu) + - Jáchym Toušek (enumag) + - Mathias Arlaud (mtarld) - Graham Campbell (graham) - - Charles Sarrazin (csarrazi) + - Michel Weimerskirch (mweimerskirch) + - Eric Clemmons (ericclemmons) + - Issei Murasawa (issei_m) + - Malte Schlüter (maltemaltesich) - Vasilij Dusko - - Douglas Greenshields (shieldo) - - David Buchmann (dbu) - - Alexander Schranz (alexander-schranz) + - Denis (yethee) - Arnout Boks (aboks) - - Deni + - Charles Sarrazin (csarrazi) + - Przemysław Bogusz (przemyslaw-bogusz) - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Fran Moreno (franmomu) - - Mathieu Santostefano (welcomattic) - - Dariusz Ruminski + - Maxime Helias (maxhelias) + - Ener-Getick + - Ruud Kamphuis (ruudk) + - Sebastiaan Stok (sstok) - Jérôme Vasseur (jvasseur) + - Ion Bazan (ionbazan) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - Daniel Holmes (dholmes) - - Sebastiaan Stok (sstok) - - HypeMC (hypemc) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Smaine Milianni (ismail1432) - John Wards (johnwards) - - Tomas Norkūnas (norkunas) - - Alexandre Daubois (alexandre-daubois) - - Julien Falque (julienfalque) - - Baptiste Clavié (talus) + - Dariusz Ruminski + - Lars Strojny (lstrojny) + - Yanick Witschi (toflar) - Antoine Hérault (herzult) - - Paráda József (paradajozsef) - - Vincent Langlet (deviling) - - Massimiliano Arione (garak) - - Mathias Arlaud (mtarld) + - Konstantin.Myakshin + - Rokas Mikalkėnas (rokasm) + - Arman Hosseini (arman) + - Saif Eddin Gmati (azjezz) - Arnaud Le Blanc (arnaud-lb) - - Przemysław Bogusz (przemyslaw-bogusz) - Maxime STEINHAUSSER - - Michal Piotrowski (eventhorizon) - - Tomáš Votruba (tomas_votruba) + - Peter Kokot (maastermedia) + - jeremyFreeAgent (jeremyfreeagent) + - Ahmed TAILOULOUTE (ahmedtai) + - Simon Berger - Tim Nagel (merk) + - Andreas Braun + - Teoh Han Hui (teohhanhui) + - YaFou + - Gary PEGEOT (gary-p) - Chris Wilkinson (thewilkybarkid) - - Peter Kokot (maastermedia) - - Lars Strojny (lstrojny) - Brice BERNARD (brikou) - - Ahmed TAILOULOUTE (ahmedtai) + - Roman Martinuk (a2a4) - Gregor Harlan (gharlan) + - Baptiste Clavié (talus) + - Adrien Brault (adrienbrault) + - Michal Piotrowski - marc.weistroff - lenar - - Alexander Schwenn (xelaris) - - Jérémy Romey (jeremyfreeagent) + - Jesse Rushlow (geeshoe) + - Théo FIDRY + - Jeroen Spee (jeroens) + - Michael Babker (mbabker) - Włodzimierz Gajda (gajdaw) - Christian Scheb - - Adrien Brault (adrienbrault) - - Maxime Helias (maxhelias) - - Yanick Witschi (toflar) + - Guillaume (guill) + - Tugdual Saunier (tucksaun) - Jacob Dreesen (jdreesen) - - Malte Schlüter (maltemaltesich) - Joel Wurtz (brouznouf) - - Théo FIDRY (theofidry) + - Olivier Dolbeau (odolbeau) - Florian Voutzinos (florianv) - - Teoh Han Hui (teohhanhui) + - zairig imad (zairigimad) + - Hugo Alliaume (kocal) - Colin Frei + - Christopher Hertel (chertel) - Javier Spagnoletti (phansys) - - Ruud Kamphuis (ruudk) - - Joshua Thijssen - - Daniel Wehner (dawehner) - - Tugdual Saunier (tucksaun) - excelwebzone - - Gordon Franke (gimler) - - Saif Eddin Gmati (azjezz) + - Phil Taylor (prazgod) + - Jérôme Parmentier (lctrs) + - HeahDude - Richard van Laak (rvanlaak) - - Gary PEGEOT (gary-p) - - Jesse Rushlow (geeshoe) + - Paráda József (paradajozsef) + - Alessandro Lai (jean85) + - Alexander Schwenn (xelaris) - Fabien Pennequin (fabienpennequin) - - Olivier Dolbeau (odolbeau) - - Smaine Milianni (ismail1432) - - Eric GELOEN (gelo) - - Matthieu Napoli (mnapoli) - - Ion Bazan (ionbazan) - - Jannik Zschiesche (apfelbox) + - Gordon Franke (gimler) + - François-Xavier de Guillebon (de-gui_f) + - Andreas Schempp (aschempp) + - Gabriel Caruso + - Anthony GRASSIOT (antograssiot) + - Jan Rosier (rosier) + - Daniel Wehner (dawehner) + - Hugo Monteiro (monteiro) + - Baptiste Leduc (korbeil) + - Marco Pivetta (ocramius) - Robert Schönthal (digitalkaoz) - - Florian Lonqueu-Brochard (florianlb) + - Võ Xuân Tiến (tienvx) + - fd6130 (fdtvui) - Tigran Azatyan (tigranazatyan) - - YaFou - - Gabriel Caruso (carusogabriel) + - Eric GELOEN (gelo) + - Matthieu Napoli (mnapoli) + - Tomáš Votruba (tomas_votruba) + - Joshua Thijssen - Stefano Sala (stefano.sala) - - Andréia Bohner (andreia) - - Evgeniy (ewgraf) - - Vincent AUBERT (vincent) + - Alessandro Chitolina (alekitto) + - Valentine Boineau (valentineboineau) + - Jeroen Noten (jeroennoten) + - Gocha Ossinkine (ossinkine) + - Andreas Möller (localheinz) + - OGAWA Katsuhiro (fivestar) + - Jhonny Lidfors (jhonne) + - Martin Hujer (martinhujer) + - Wouter J + - Chi-teck + - Guilliam Xavier + - Antonio Pauletich (x-coder264) + - Timo Bakx (timobakx) - Juti Noppornpitak (shiroyuki) - - Simon Berger - - Anthony MARTIN (xurudragon) + - Joe Bennett (kralos) + - Nate Wiebe (natewiebe13) + - Farhad Safarov (safarov) + - Anthony MARTIN + - Nicolas Philippe (nikophil) + - Colin O'Dell (colinodell) - Sebastian Hörl (blogsh) + - Ben Davies (bendavies) - Daniel Gomes (danielcsgomes) + - Michael Käfer (michael_kaefer) - Hidenori Goto (hidenorigoto) - - Jan Rosier (rosier) - - Alessandro Chitolina (alekitto) + - Dāvis Zālītis (k0d3r1s) - Albert Casademont (acasademont) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) - - Marco Pivetta (ocramius) + - Sergey (upyx) + - Michael Voříšek - SpacePossum - - Alexander Menshchikov (zmey_kk) - Pablo Godel (pgodel) - - Andreas Braun - - Jérémie Augustin (jaugustin) - - François-Xavier de Guillebon (de-gui_f) - - Oleg Voronkovich - - hacfi (hifi) + - Hubert Lenoir (hubert_lenoir) + - Denis Brumann (dbrumann) + - Romaric Drigon (romaricdrigon) + - Andréia Bohner (andreia) + - Jannik Zschiesche - Rafael Dohms (rdohms) - George Mponos (gmponos) + - Fritz Michael Gschwantner (fritzmg) + - Aleksandar Jakovljevic (ajakov) - jwdeitch - - Jeroen Spee (jeroens) - - Jérôme Parmentier (lctrs) + - Jurica Vlahoviček (vjurica) + - David Prévot + - Vincent Touzet (vincenttouzet) - Fabien Bourigault (fbourigault) - - Joe Bennett (kralos) - - Michael Babker (mbabker) - - Mikael Pajunen - - Andreas Schempp (aschempp) - - Alessandro Lai (jean85) - - Romaric Drigon (romaricdrigon) - - Christopher Hertel (chertel) - - Arman Hosseini (arman) - - Rokas Mikalkėnas (rokasm) + - soyuka + - Jérémy Derussé + - Florent Mata (fmata) + - mcfedr (mcfedr) + - Maciej Malarz (malarzm) + - Soner Sayakci + - Artem Lopata + - Sokolov Evgeniy (ewgraf) + - Stadly + - Justin Hileman (bobthecow) + - Tom Van Looy (tvlooy) - Niels Keurentjes (curry684) - Vyacheslav Pavlov - - Andreas Möller (localheinz) - Richard Shank (iampersistent) - - Wouter J - - Thomas Rabaix (rande) - - Chi-teck - - Baptiste Leduc (korbeil) - - Timo Bakx (timobakx) - - Vincent Touzet (vincenttouzet) - - Nate Wiebe (natewiebe13) + - Thomas Landauer (thomas-landauer) + - Andre Rømcke (andrerom) + - Dmitrii Poddubnyi (karser) - Rouven Weßling (realityking) - - Ben Davies (bendavies) + - BoShurik + - Zmey - Clemens Tolboom + - Oleg Voronkovich - Helmer Aaviksoo - - Remon van de Kamp (rpkamp) + - Michał (bambucha15) + - Remon van de Kamp + - Ben Hakim + - Sylvain Fabre (sylfabre) - Filippo Tessarotto (slamdunk) - - Hiromi Hishida (77web) - - Michael Käfer (michael_kaefer) + - 77web + - Bohan Yang (brentybh) + - Bastien Jaillot (bastnic) + - W0rma - Matthieu Ouellette-Vachon (maoueh) + - Lynn van der Berg (kjarli) - Michał Pipa (michal.pipa) - Dawid Nowak - - Roman Martinuk (a2a4) - Amal Raghav (kertz) - - Jonathan Ingram (jonathaningram) + - Jonathan Ingram - Artur Kotyrba - Tyson Andre - GDIBass - Samuel NELA (snela) - - David Prévot - - Hugo Monteiro (monteiro) - - Dmitrii Poddubnyi (karser) - - zairig imad (zairigimad) - - Tien Vo (tienvx) - - Colin O'Dell (colinodell) + - dFayet + - Karoly Gossler (connorhu) + - Vincent AUBERT (vincent) + - Sebastien Morel (plopix) + - Yoann RENARD (yrenard) + - Thomas Lallement (raziel057) - Timothée Barray (tyx) + - Alexis Lefebvre - James Halsall (jaitsu) - - Florent Mata (fmata) + - Mikael Pajunen - Warnar Boekkooi (boekkooi) + - Marco Petersen (ocrampete16) - Benjamin Leveque (benji07) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Mathieu Lechat (mat_the_cat) - - Jeroen Noten (jeroennoten) + - Vilius Grigaliūnas - Marek Štípek (maryo) + - Patrick Landolt (scube) + - François Pluchino (francoispluchino) - Daniel Espendiller - - Possum + - Arnaud PETITPAS (apetitpa) - Dorian Villet (gnutix) - - Michaël Perrin (michael.perrin) + - Wojciech Kania + - Alexey Kopytko (sanmai) - Sergey Linnik (linniksa) - - Martin Hujer (martinhujer) - - Richard Miller (mr_r_miller) + - Warxcell (warxcell) + - Richard Miller + - Leo Feyer (leofeyer) - Mario A. Alvarez Garcia (nomack84) - - Dennis Benkert (denderello) + - Thomas Rabaix (rande) + - D (denderello) + - Jonathan Scheiber (jmsche) - DQNEO - - Hidde Wieringa (hiddewie) - - Antonio Pauletich (x-coder264) - - Andre Rømcke (andrerom) + - Romain Monteil (ker0x) + - Andrii Bodnar + - gnito-org + - Artem (artemgenvald) + - ivan + - Sergey Belyshkin (sbelyshkin) + - Urinbayev Shakhobiddin (shokhaa) + - Ahmed Raafat - Philippe Segatori - Thibaut Cheymol (tcheymol) - - Sebastien Morel (plopix) - - mcfedr (mcfedr) - - Nicolas Philippe (nikophil) + - Julien Pauli + - Islam Israfilov (islam93) + - Oleg Andreyev (oleg.andreyev) + - Daniel Gorgan + - Sébastien Alfaiate (seb33300) + - Hendrik Luup (hluup) + - Martin Herndl (herndlm) - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) - - Baptiste Lafontaine (magnetik) + - Pavel Kirpitsov (pavel-kirpichyov) - Mathieu Lemoine (lemoinem) - - Denis Brumann (dbrumann) - Christian Schmidt - Andreas Hucks (meandmymonkey) - - Tom Van Looy (tvlooy) - - Guillaume Pédelagrabe - Noel Guilbert (noel) - - Anthony GRASSIOT (antograssiot) - - Stadly + - Hamza Makraz (makraz) + - Loick Piera (pyrech) + - Vitalii Ekert (comrade42) + - Clara van Miert + - Martin Auswöger + - Alexander Menshchikov + - Marcin Sikoń (marphi) - Stepan Anchugov (kix) - - François Pluchino (francoispluchino) - bronze1man - sun (sun) + - Alan Poulain (alanpoulain) - Larry Garfield (crell) + - Fabien Villepinte + - SiD (plbsid) + - Thomas Bisignani (toma) - Edi Modrić (emodric) - - Gocha Ossinkine (ossinkine) - - Leo Feyer (leofeyer) + - Philipp Wahala (hifi) - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) - apetitpa - - Matthieu Bontemps (mbontemps) - - apetitpa - - Guilliam Xavier + - Vladyslav Loboda - Pierre Minnieur (pminnieur) - - fivestar + - Kyle - Dominique Bongiraud - - dFayet - - Jeremy Livingston (jeremylivingston) - - soyuka - - Michael Lee (zerustech) - - Matthieu Auger (matthieuauger) + - Hidde Wieringa (hiddewie) + - Christopher Davis (chrisguitarguy) + - Lukáš Holeczy (holicz) + - Florian Lonqueu-Brochard (florianlb) - Leszek Prabucki (l3l0) - Emanuele Panzeri (thepanz) + - Matthew Smeets - François Zaninotto (fzaninotto) - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) - - fd6130 (fdtvui) - - Justin Hileman (bobthecow) - - Blanchon Vincent (blanchonvincent) - - Maciej Malarz (malarzm) + - Bob van de Vijver (bobvandevijver) + - smoench - Michele Orselli (orso) - Sven Paulus (subsven) - Daniel STANCU + - Markus Fasselt (digilist) - Maxime Veber (nek-) - - Sylvain Fabre (sylfabre) - - Loick Piera (pyrech) - - Clara van Miert - - Valentine Boineau (valentineboineau) - - Bastien Jaillot (bastnic) + - Oleksiy (alexndlm) + - Sullivan SENECHAL (soullivaneuh) - Rui Marinho (ruimarinho) - - Patrick Landolt (scube) - - Michał (bambucha15) - - Eugene Wissner - - Bohan Yang (brentybh) + - Marc Weistroff (futurecat) + - Dimitri Gritsajuk (ottaviano) + - Possum + - Jérémie Augustin (jaugustin) - Pascal Montoya - - Julien Brochet (mewt) - - Tristan Darricau (nicofuma) + - Julien Brochet + - Michaël Perrin (michael.perrin) + - Tristan Darricau (tristandsensio) + - Fabien S (bafs) - Victor Bocharsky (bocharsky_bw) - - Bozhidar Hristov (warxcell) + - Jan Sorgalla (jsor) + - henrikbjorn + - Alex Bowers + - Simon Podlipsky (simpod) - Marcel Beerta (mazen) - - Thomas Landauer (thomas-landauer) - - Pavel Batanov (scaytrase) + - flack (flack) + - Craig Duncan (duncan3dc) - Mantis Development - - Loïc Faugeron + - Pablo Lozano (arkadis) - quentin neyrat (qneyrat) - - Karoly Gossler (connorhu) + - Antonio Jose Cerezo (ajcerezo) - Marcin Szepczynski (czepol) + - Lescot Edouard (idetox) - Rob Frawley 2nd (robfrawley) - - Ahmed Raafat - - julien pauli (jpauli) - - Lorenz Schori - - Sébastien Lavoie (lavoiesl) + - Mohammad Emran Hasan (phpfour) + - Dmitriy Mamontov (mamontovdmitriy) + - Nikita Konstantinov (unkind) + - Michael Lee (zerustech) - Dariusz - - Farhad Safarov (safarov) - - BoShurik - - Thomas Lallement (raziel057) - - Michael Voříšek - Francois Zaninotto + - Laurent Masforné (heisenberg) - Claude Khedhiri (ck-developer) - - Alexander Kotynia (olden) - Daniel Tschinder - Christian Schmidt - - Marcos Sánchez + - Alexander Kotynia (olden) + - Toni Rudolf (toooni) - Elnur Abdurrakhimov (elnur) + - Iker Ibarguren (ikerib) - Manuel Reinhard (sprain) + - Johann Pardanaud + - Indra Gunawan (indragunawan) + - Tim Goudriaan (codedmonkey) - Harm van Tilborg (hvt) - - Danny Berger (dpb587) - - Antonio J. García Lagar (ajgarlag) + - Baptiste Lafontaine (magnetik) + - Dries Vints - Adam Prager (padam87) - Judicaël RUFFIEUX (axanagor) - Benoît Burnichon (bburnichon) - - Roman Marintšenko (inori) + - maxime.steinhausser + - simon chrzanowski (simonch) + - Andrew M-Y (andr) + - Krasimir Bosilkov (kbosilkov) + - Marcin Michalski (marcinmichalski) + - Roman Ring (inori) - Xavier Montaña Carreras (xmontana) - - Mickaël Andrieu (mickaelandrieu) - - Soner Sayakci + - Tarmo Leppänen (tarlepp) + - AnneKir + - Tobias Weichart + - Miro Michalicka + - M. Vondano - Xavier Perez - Arjen Brouwer (arjenjb) - - Katsuhiro OGAWA - - Artem Lopata + - Tavo Nieves J (tavoniievez) + - Arjen van der Meijden - Patrick McDougle (patrick-mcdougle) - - Marc Weistroff (futurecat) + - Jerzy (jlekowski) + - Danny Berger (dpb587) + - Marek Zajac - Alif Rachmawadi - Anton Chernikov (anton_ch1989) - - Kristen Gilden (kgilden) - - Pierre-Yves LEBECQ (pylebecq) + - Pierre-Yves Lebecq (pylebecq) + - Alireza Mirsepassi (alirezamirsepassi) - Jordan Samouh (jordansamouh) - - Jakub Kucharovic (jkucharovic) - - Sullivan SENECHAL (soullivaneuh) - - Thomas Bisignani (toma) + - Koen Reiniers (koenre) + - Nathan Dench (ndenc2) + - Gijs van Lammeren + - Matthew Grasmick + - David Badura (davidbadura) - Uwe Jäger (uwej711) - - Dāvis Zālītis (k0d3r1s) - Eugene Leonovich (rybakit) + - Damien Alexandre (damienalexandre) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon - - Nguyen Xuan Quynh (xuanquynh) - - Jan Sorgalla (jsor) + - Roman Anasal + - Piotr Kugla (piku235) + - Quynh Xuan Nguyen (seriquynh) - Ray + - Philipp Cordes (corphi) + - Yannick Ihmels (ihmels) + - Andrii Dembitskyi - Chekote - - Aleksandar Jakovljevic (ajakov) + - bhavin (bhavin4u) + - Pavel Popov (metaer) - Thomas Adam - - Jhonny Lidfors (jhonne) - - Diego Agulló (aeoris) + - R. Achmad Dadang Nur Hidayanto (dadangnh) + - Stefan Kruppa + - Petr Duda (petrduda) + - Marcos Rezende (rezende79) - jdhoek - - Jurica Vlahoviček (vjurica) + - Ivan Kurnosov + - Dieter - Bob den Otter (bopp) + - Johan Vlaar (johjohan) - Thomas Schulz (king2500) - - Frank de Jonge (frenkynet) - - Artem Henvald (artemgenvald) - - Lescot Edouard (idetox) - - Nikita Konstantinov - - Wodor Wodorski - - Guilhem N (guilhemn) - - Mohammad Emran Hasan (phpfour) - - Dmitriy Mamontov (mamontovdmitriy) + - Benjamin Morel + - Bernd Stellwag + - Philippe SEGATORI (tigitz) + - Frank de Jonge + - Chris Tanaskoski + - julien57 + - Loïc Frémont (loic425) + - Ippei Sumida (ippey_s) - Ben Ramsey (ramsey) - - Laurent Masforné (heisenberg) - - Sergey (upyx) + - Matthieu Auger (matthieuauger) + - Kévin THERAGE (kevin_therage) + - Josip Kruslin (jkruslin) - Giorgio Premi - - Guillaume (guill) - renanbr - - Matthew Smeets - - Alex Rock Ancelet (pierstoval) + - Maxim Dovydenok (shiftby) + - Sébastien Lavoie (lavoiesl) + - Alex Rock (pierstoval) + - Wodor Wodorski - Beau Simensen (simensen) - - Johann Pardanaud - - Michael Hirschler (mvhirsch) - Robert Kiss (kepten) - - Zan Baldwin (zanderbaldwin) - - Roumen Damianoff (roumen) + - Zan Baldwin (zanbaldwin) + - Antonio J. García Lagar (ajgarlag) + - Alexandre Quercia (alquerci) + - Marcos Sánchez + - Jérôme Tanghe (deuchnord) - Kim Hemsø Rasmussen (kimhemsoe) - - Oleg Andreyev - - Martin Herndl (herndlm) - - Pavel Kirpitsov (pavel-kirpichyov) + - Maximilian Reichel (phramz) + - Dane Powell + - jaugustin + - Dmytro Borysovskyi (dmytr0) + - Mathias STRASSER (roukmoute) - Pascal Luna (skalpa) - Wouter Van Hecke - - Iker Ibarguren (ikerib) - - Bob van de Vijver (bobvandevijver) - Peter Kruithof (pkruithof) - Michael Holm (hollo) - - Arjen van der Meijden - - Markus Fasselt (digilist) - - Damien Alexandre (damienalexandre) - - Simon Mönch (sm) + - Giso Stallenberg (gisostallenberg) + - Blanchon Vincent (blanchonvincent) + - William Arslett (warslett) + - Jérémy REYNAUD (babeuloula) - Christian Schmidt - - Marcin Sikoń (marphi) - Gonzalo Vilaseca (gonzalovilaseca) - - Ben Hakim + - Vadim Borodavko (javer) - Haralan Dobrev (hkdobrev) - - Marco Petersen (ocrampete16) - - MatTheCat - - Vilius Grigaliūnas - - David Badura (davidbadura) - - Chad Sikorra (chadsikorra) - - Alan Poulain (alanpoulain) + - Soufian EZ ZANTAR (soezz) + - Jan van Thoor (janvt) + - Martin Kirilov (wucdbm) + - Axel Guckelsberger (guite) - Chris Smith (cs278) - Florian Klein (docteurklein) - - W0rma + - Bilge + - Cătălin Dan (dancatalin) + - Rhodri Pugh (rodnaph) - Manuel Kiessling (manuelkiessling) - - Dimitri Gritsajuk (ottaviano) - - Alexey Kopytko (sanmai) - - Gijs van Lammeren + - Patrick Reimers (preimers) + - Anatoly Pashin (b1rdex) - Pol Dellaiera (drupol) - Atsuhiro KUBO (iteman) - - Alireza Mirsepassi (alirezamirsepassi) - rudy onfroy (ronfroy) - Serkan Yildiz (srknyldz) + - Jeroen Thora (bolle) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) - - Sébastien Alfaiate (seb33300) + - Marc Morera (mmoreram) - Gabor Toth (tgabi333) - realmfoo - Thomas Tourlourat (armetiz) + - Gasan Guseynov (gassan) - Andrey Esaulov (andremaha) - Grégoire Passault (gregwar) - Jerzy Zawadzki (jzawadzki) - Ismael Ambrosi (iambrosi) - - Craig Duncan (duncan3dc) + - Saif Eddin G - Emmanuel BORGES (eborges78) + - siganushka (siganushka) - Aurelijus Valeiša (aurelijus) + - Evert Harmeling (evertharmeling) - Jan Decavele (jandc) - Gustavo Piltcher + - Shakhobiddin + - Grenier Kévin (mcsky_biig) - Stepan Tanasiychuk (stfalcon) - - Ivan Kurnosov - Tiago Ribeiro (fixe) - - Hidde Boomsma (hboomsma) - - John Bafford (jbafford) - Raul Fraile (raulfraile) - Adrian Rudnik (kreischweide) + - Pavel Batanov (scaytrase) - Francesc Rosàs (frosas) - - Romain Pierre (romain-pierre) - - Julien Galenski (ruian) - - Dieter - Bongiraud Dominique - - Kyle - janschoenherr + - Marko Kaznovac (kaznovac) - Emanuele Gaspari (inmarelibero) - Dariusz Rumiński - - Chris Tanaskoski + - Terje Bråten + - Gennadi Janzen - James Hemery - - Berny Cantos (xphere81) - - Andrii Bodnar - - Thierry Thuon (lepiaf) - - Antonio Jose Cerezo (ajcerezo) - - Ricard Clau (ricardclau) - - Mark Challoner (markchalloner) - - Loïc Frémont (loic425) + - Egor Taranov + - Philippe Segatori + - Adrian Nguyen (vuphuong87) + - benjaminmal + - Thierry T (lepiaf) + - Lorenz Schori + - Andrey Sevastianov - Oleksandr Barabolia (oleksandrbarabolia) - - Christopher Davis (chrisguitarguy) - - ivan + - Khoo Yong Jun + - Christin Gruber (christingruber) + - Jeremy Livingston (jeremylivingston) + - Julien Turby + - scyzoryck - Greg Anderson - Tri Pham (phamuyentri) - - Urinbayev Shakhobiddin (shokhaa) - - Gennady Telegin (gtelegin) + - marie + - Erkhembayar Gantulga (erheme318) + - Fractal Zombie + - Gunnstein Lye (glye) + - Thomas Talbot (ioni) + - Noémi Salaün (noemi-salaun) + - Michel Hunziker - Krystian Marcisz (simivar) - - Toni Rudolf (toooni) - - Dalibor Karlović (dkarlovi) + - Matthias Krauser (mkrauser) - Erin Millard - - Artur Melo (restless) + - Lorenzo Millucci (lmillucci) + - Jérôme Tamarelle (jtamarelle-prismamedia) + - Emil Masiakowski + - Alexandre Parent + - Angelov Dejan (angelov) + - DT Inier (gam6itko) - Matthew Lewinski (lewinski) - Magnus Nordlander (magnusnordlander) + - Ricard Clau (ricardclau) + - Dmitrii Tarasov (dtarasov) + - Philipp Kolesnikov - Carlos Pereira De Amorim (epitre) - Rodrigo Aguilera + - Roumen Damianoff - Vladimir Varlamov (iamvar) - Thomas Royer (cydonia7) + - Gildas Quéméner (gquemener) - Nicolas LEFEVRE (nicoweb) - - alquerci + - Asmir Mustafic (goetas) + - Martins Sipenko + - Guilherme Augusto Henschel + - Mardari Dorel (dorumd) + - Pierrick VIGNAND (pierrick) - Mateusz Sip (mateusz_sip) + - Andy Palmer (andyexeter) + - Marko H. Tamminen (gzumba) - Francesco Levorato + - DerManoMann + - David Molineus + - Desjardins Jérôme (jewome62) - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) + - Stefan Gehrig (sgehrig) - Benjamin Cremer (bcremer) - - Hendrik Luup (hluup) + - rtek - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - - Dmytro Borysovskyi (dmytr0) + - Artem Stepin (astepin) + - Adrien Jourdier (eclairia) + - Ivan Grigoriev (greedyivan) - Tomasz Kowalczyk (thunderer) + - Erik Saunier (snickers) + - Kevin SCHNEKENBURGER + - Fabien Salles (blacked) - Artur Eshenbrener + - Ahmed Ashraf (ahmedash95) + - Gert Wijnalda (cinamo) + - Luca Saba (lucasaba) - Thomas Perez (scullwm) - - Yoann RENARD (yrenard) + - Thomas P + - Kristijan Kanalaš (kristijan_kanalas_infostud) - Felix Labrecque + - mondrake (mondrake) - Yaroslav Kiliba + - “Filip + - FORT Pierre-Louis (plfort) + - Simon Watiau (simonwatiau) + - Ruben Jacobs (rubenj) + - Arkadius Stefanski (arkadius) + - Jérémy M (th3mouk) - Terje Bråten + - Pierre Rineau - Renan Gonçalves (renan_saddam) - - Tim Goudriaan (codedmonkey) - - Tarmo Leppänen (tarlepp) - - Martin Auswöger + - Raulnet + - Tomasz Kusy + - Jakub Kucharovic (jkucharovic) + - Kristen Gilden - Robbert Klarenbeek (robbertkl) - - Hamza Makraz (makraz) - Eric Masoero (eric-masoero) - - Vitalii Ekert (comrade42) - - JhonnyL + - Michael Lutz + - Michel Roca (mroca) + - Reedy - hossein zolfi (ocean) - Clément Gautier (clementgautier) - - Koen Reiniers (koenre) - - Hugo Alliaume (kocal) - - Sanpi + - Jelle Raaijmakers (gmta) + - Roberto Nygaard + - Joshua Nye + - Dalibor Karlović + - Randy Geraads + - Sanpi (sanpi) + - James Gilliland (neclimdul) - Eduardo Gulias (egulias) + - Andreas Leathley (iquito) + - Nathanael Noblet (gnat) - giulio de donato (liuggio) - Mohamed Gamal + - Eric COURTIAL + - Xesxen - ShinDarth + - Arun Philip - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) - - Rhodri Pugh (rodnaph) - - Grzegorz Zdanowski (kiler129) - - Kirill chEbba Chebunin (chebba) - - Fritz Michael Gschwantner (fritzmg) + - Carl Casbolt (carlcasbolt) + - battye + - BrokenSourceCode + - Grzegorz (Greg) Zdanowski (kiler129) + - Kirill chEbba Chebunin + - kylekatarnls (kylekatarnls) + - Steve Grunwell - - - Fabien Villepinte - - SiD (plbsid) - - Matthew Grasmick + - Alex (aik099) - Greg Thornton (xdissent) - BENOIT POLASZEK (bpolaszek) - - Alex Bowers - - Piotr Kugla (piku235) - - Philipp Cordes - - Jeroen Thora (bolle) + - Shaharia Azam + - Gerben Oolbekkink + - Alexandre Parent + - Thibault Richard (t-richard) + - Oleksii Zhurbytskyi + - Guillaume Verstraete + - vladimir.panivko + - Jason Tan (jt2k) - Costin Bereveanu (schniper) - - Loïc Chardonnet (gnusat) + - kick-the-bucket - Marek Kalnik (marekkalnik) + - Jeremiasz Major - Vyacheslav Salakhutdinov (megazoll) - - Antoine Lamirault - - Phil Taylor (prazgod) + - Trevor North + - Maksym Slesarenko (maksym_slesarenko) - Hassan Amouhzi - - Daniel Gorgan + - Antonin CLAUZIER (0x346e3730) + - Andrei C. (moldman) - Tamas Szijarto + - stlrnz + - Adrien Wilmet (adrienfr) + - Alex Bacart + - hugovms - Michele Locati - Pavel Volokitin (pvolok) + - DemigodCode - Arthur de Moulins (4rthem) - Matthias Althaus (althaus) - - Nicolas Dewez (nicolas_dewez) - - Saif Eddin G + - Maximilian Bösing + - Leevi Graham (leevigraham) - Endre Fejes + - Carlos Buenosvinos (carlosbuenosvinos) + - Jake (jakesoft) - Tobias Naumann (tna) - Greg ORIOL + - Bahman Mehrdad (bahman) - Daniel Beyer - Manuel Alejandro Paz Cetina + - Youssef Benhssaien (moghreb) + - Mario Ramundo (rammar) + - Ivan - Shein Alexey + - Nico Haase - Jacek Jędrzejewski (jacek.jedrzejewski) - - Romain Gautier (mykiwi) - Stefan Kruppa + - Shahriar56 + - Dhananjay Goratela + - Kien Nguyen - Joe Lencioni + - arai + - Mouad ZIANI (mouadziani) - Daniel Tschinder + - Diego Agulló (aeoris) + - Tomasz Ignatiuk + - Joachim Løvgaard (loevgaard) - vladimir.reznichenko - Kai - Lee Rowlands - - Krzysztof Piasecki (krzysztek) - - Maximilian Reichel (phramz) - Alain Hippolyte (aloneh) - - Grenier Kévin (mcsky_biig) - Karoly Negyesi (chx) - Xavier HAUSHERR + - Loïc Beurlet + - Ana Raro + - Ana Raro + - Tom Klingenberg + - Florian Wolfsjaeger (flowolf) + - Ivan Sarastov (isarastov) + - Jordi Sala Morales (jsala) - Albert Jessurum (ajessu) + - Samuele Lilli (doncallisto) + - Peter Bowyer (pbowyer) + - Romain Pierre - Laszlo Korte - - Miha Vrhovnik + - Gabrielle Langer - Alessandro Desantis - hubert lecorche (hlecorche) - - Vladyslav Loboda - - fritzmg - - flack (flack) + - bogdan + - mmokhi + - Daniel Tiringer + - Andrew Codispoti + - Lctrs + - Joppe De Cuyper (joppedc) - Marc Morales Valldepérez (kuert) - - Jean-Baptiste GOMOND (mjbgo) - - Vadim Kharitonov (virtuozzz) + - Vadim Kharitonov (vadim) - Oscar Cubo Medina (ocubom) - Karel Souffriau - Christophe L. (christophelau) + - Daniël Brekelmans (dbrekelmans) + - Simon Heimberg (simon_heimberg) + - Morten Wulff (wulff) - Sander Toonen (xatoo) - Anthon Pang (robocoder) - - Marko Kaznovac (kaznovac) - - Pablo Lozano (arkadis) + - Julien Galenski (ruian) + - Rimas Kudelis + - Ben Scott (bpscott) + - Andrii Dembitskyi + - a.dmitryuk + - Pavol Tuka + - Paulo Ribeiro (paulo) - Marc Laporte - Michał Jusięga - - Bernd Stellwag - - Sébastien Santoro (dereckson) - - Gennadi Janzen + - Dmitriy Derepko + - Sebastian Paczkowski (sebpacz) + - Dragos Protung (dragosprotung) + - Thiago Cordeiro (thiagocordeiro) + - Julien Maulny - Brian King - - Michel Salib (michelsalib) - - geoffrey + - Paul Oms - Steffen Roßkamp - Alexandru Furculita (afurculita) - - Valentin Jonovs (valentins-jonovs) + - Michel Salib (michelsalib) + - Quentin Dequippe (qdequippe) + - Valentin Jonovs + - geoffrey - Bastien DURAND (deamon) + - Benoit Galati (benoitgalati) + - Jon Gotlin (jongotlin) - Jeanmonod David (jeanmonod) - - Christin Gruber (christingruber) - - Andrey Sevastianov + - Daniel González (daniel.gonzalez) + - Renan (renanbr) - Webnet team (webnet) - - marie + - Tobias Bönner + - Berny Cantos (xphere81) + - Mátyás Somfai (smatyas) + - Simon Leblanc (leblanc_simon) - Jan Schumann - - Noémi Salaün (noemi-salaun) + - Matheo Daninos (mathdns) - Niklas Fiekas - - Philippe Segatori + - Mark Challoner (markchalloner) - Markus Bachmann (baachi) - - Kévin THERAGE (kevin_therage) - - Michel Hunziker - - Gunnstein Lye (glye) - - scyzoryck - - Matthias Krauser (mkrauser) - - Erkhembayar Gantulga (erheme318) - - Alexis Lefebvre - - Lorenzo Millucci (lmillucci) - - Jérôme Tamarelle (jtamarelle-prismamedia) + - Roger Guasch (rogerguasch) + - Luis Tacón (lutacon) + - Alex Hofbauer (alexhofbauer) - Andrii Popov (andrii-popov) - - Islam93 - lancergr - - Mihai Stancu - Ivan Nikolaev (destillat) - - Gildas Quéméner (gquemener) - - Pierrick VIGNAND (pierrick) - - Desjardins Jérôme (jewome62) + - Xavier Leune (xleune) + - Ben Roberts (benr77) + - Joost van Driel (j92) + - ampaze - Arturs Vonda - - Josip Kruslin - Xavier Briand (xavierbriand) - - Asmir Mustafic (goetas) - - DerManoMann - - Stefan Gehrig (sgehrig) + - Daniel Badura - vagrant - - Aurimas Niekis (gcds) - - EdgarPE - - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) + - AKeeman (akeeman) - Martijn Cuppens + - Restless-ET - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) + - Vladimir Tsykun (vtsykun) - Chris Sedlmayr (catchamonkey) - - Indra Gunawan (indragunawan) - - Mathias STRASSER (roukmoute) - - simon chrzanowski (simonch) - Kamil Kokot (pamil) - Seb Koelen - Christoph Mewes (xrstf) - - Andrew M-Y (andr) - - Krasimir Bosilkov (kbosilkov) - - Marcin Michalski (marcinmichalski) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Niklas Keller + - BASAK Semih (itsemih) - Dirk Pahl (dirkaholic) - - cedric lombardot (cedriclombardot) - - Dane Powell - - Arkadius Stefanski (arkadius) + - Cédric Lombardot (cedriclombardot) - Jonas Flodén (flojon) - - AnneKir - - Tobias Weichart - - Miro Michalicka - - M. Vondano - - Dominik Zogg (dominik.zogg) - - Marek Pietrzak - - Tavo Nieves J + - Adrien Lucas (adrienlucas) + - Dominik Zogg + - Kai Dederichs - Luc Vieillescazes (iamluc) - - Lukáš Holeczy (holicz) - - Erik Saunier (snickers) - - franek (franek) - - Jerzy (jlekowski) - - Raulnet - - Christian Wahler - - Dries Vints - - Giso Stallenberg (gisostallenberg) - - Gintautas Miselis + - Thomas Nunninger + - François Dume (franek) - Rob Bast - Roberto Espinoza (respinoza) - - Pierre Rineau - - Andreas Leathley (iquito) - - Soufian EZ-ZANTAR (soezz) - - Zander Baldwin - - Marek Zajac - Adam Harvey + - ilyes kooli (skafandri) - Anton Bakai - - Vadim Borodavko (javer) - - Xesxen - - battye - Sam Fleming (sam_fleming) - - William Arslett - Alex Bakhturin - - Patrick Reimers (preimers) + - Brayden Williams (redstar504) - insekticid - - Alexander Obuhovich (aik099) - - Jérémy M (th3mouk) + - Trent Steel (trsteel88) - Vitaliy Ryaboy (vitaliy) - boombatower - - Fabrice Bernhard (fabriceb) + - Douglas Hammond (wizhippo) - Jérôme Macias (jeromemacias) - Andrey Astakhov (aast) - ReenExe - - Adrien Lucas (adrienlucas) - Fabian Lange (codingfabian) - - Frank Neff (fneff) - - Roman Lapin (memphys) - Yoshio HANAWA - - Randy Geraads - - Jan van Thoor (janvt) - - Gladhon - - Joshua Nye - - Martin Kirilov (wucdbm) - - Nathan Dench (ndenc2) - - Thibault Richard (t-richard) + - Sergey Melesh (sergex) + - Toon Verwerft (veewee) + - Jiri Barous + - Gert de Pagter - Sebastian Bergmann - - Miroslav Sustek + - Miroslav Šustek (sustmi) - Pablo Díez (pablodip) - - Michel Roca (mroca) + - Damien Fa - Kevin McBride - Sergio Santoro - - Robin van der Vleuten (robinvdvleuten) + - AndrolGenhald - Philipp Rieber (bicpi) + - Dennis Væversted (srnzitcom) - Manuel de Ruiter (manuel) - - Nathanael Noblet (gnat) - nikos.sotiropoulos - Eduardo Oliveira (entering) - - Oleksii Zhurbytskyi - - Ilya Antipenko (aivus) + - Jonathan Johnson (jrjohnson) + - Eugene Wissner - Ricardo Oliveira (ricardolotr) - Roy Van Ginneken (rvanginneken) - - Steve Grunwell - ondrowan - Barry vd. Heuvel (barryvdh) - Jon Dufresne - - Fabien S (bafs) + - Chad Sikorra (chadsikorra) + - Mathias Brodala (mbrodala) + - naitsirch (naitsirch) - Evan S Kaufman (evanskaufman) - - Alex Bacart + - Jonathan Sui Lioung Lee Slew (jlslew) - mcben - Jérôme Vieilledent (lolautruche) - - Roman Anasal - - Maks Slesarenko - Filip Procházka (fprochazka) - - mmoreram - - Yannick Ihmels (ihmels) + - stoccc - Markus Lanthaler (lanthaler) + - Gigino Chianese (sajito) + - Xav` (xavismeh) - Remi Collet + - Mathieu Rochette (mathroc) - Vicent Soria Durá (vicentgodella) - Michael Moravec - - Carlos Buenosvinos (carlosbuenosvinos) - - Leevi Graham (leevigraham) - Anthony Ferrara + - Glodzienski + - Christian Gripp (core23) + - Marcel Hernandez - Ioan Negulescu - Jakub Škvára (jskvara) - Andrew Udvare (audvare) + - Volodymyr Panivko - alexpods - Dennis Langen (nijusan) - - Adrien Wilmet (adrienfr) - - Hubert Lenoir (hubert_lenoir) - - Adam Szaraniec (mimol) + - Adam Szaraniec - Dariusz Ruminski - - Erik Trapman (eriktrapman) + - Romain Gautier (mykiwi) + - Cyril Pascal (paxal) + - Matthieu Bontemps + - Erik Trapman - De Cock Xavier (xdecock) - - Almog Baku (almogbaku) - - Evert Harmeling (evertharmeling) + - Nicolas Dewez (nicolas_dewez) + - Quentin Dreyer - Scott Arciszewski - Xavier HAUSHERR + - Achilles Kaloeridis (achilles) - Norbert Orzechowicz (norzechowicz) - - stlrnz - - Denis Charrier (brucewouaigne) + - Robert-Jan de Dreu + - Fabrice Bernhard (fabriceb) - Matthijs van den Bos (matthijs) - - Simon Podlipsky (simpod) - - DemigodCode - - bhavin (bhavin4u) - Jaik Dean (jaikdean) - - Pavel Popov (metaer) + - Krzysztof Piasecki (krzysztek) - Lenard Palko - - arai - Nils Adermann (naderman) - - Tom Klingenberg - Gábor Fási - - DUPUCH (bdupuch) - - Dadang NH (dadangnh) - Nate (frickenate) - - Joachim Løvgaard (loevgaard) - - Stefan Kruppa - - jhonnyL - sasezaki - - Jonathan Scheiber (jmsche) - Kristof Van Cauwenbergh (kristofvc) - Dawid Pakuła (zulusx) - Marco Lipparini (liarco) - Florian Rey (nervo) - Rodrigo Borrego Bernabé (rodrigobb) + - John Bafford (jbafford) - Emanuele Iannone - - Jörn Lang (j.lang) - - Petr Duda (petrduda) - - Marcos Rezende (rezehnde) + - Ondrej Machulda (ondram) - Denis Gorbachev (starfall) - - Peter van Dommelen - - Tim van Densen - Martin Morávek (keeo) - - Steven Surowiec - Kevin Saliou (kbsali) + - Matthieu Mota (matthieumota) + - Steven Surowiec (steves) - Shawn Iwinski - - Samuele Lilli (doncallisto) - Gawain Lynch (gawain) - - Peter Bowyer (pbowyer) - - Wojciech Kania - - mmokhi - - NothingWeAre - - Andrii Dembitskyi - Ryan - - Lctrs - Alexander Deruwe (aderuwe) - Dave Hulbert (dave1010) - Konstantin Grachev (grachevko) - Ivan Rey (ivanrey) + - M. (mbontemps) - Marcin Chyłek (songoq) - - Ben Scott - Ned Schwartz - Anderson Müller - Ziumin - - Jeremy Benoist + - Matthias Schmidt - Lenar Lõhmus - - Daniël Brekelmans (dbrekelmans) - - Simon Heimberg (simon_heimberg) - - Benjamin Laugueux (yzalis) + - Ilija Tovilo (ilijatovilo) + - Samaël Villette (samadu61) - Zach Badgett (zachbadgett) + - Loïc Faugeron - Aurélien Fredouelle + - Jordane VASPARD (elementaire) - Pavel Campr (pcampr) - - Andrii Dembitskyi + - Forfarle (forfarle) - Johnny Robeson (johnny) - - Pavol Tuka + - Kai Eichinger (kai_eichinger) + - Kuba Werłos (kuba) + - Philipp Keck - Disquedur - - Michiel Boeckaert (milio) - - Benjamin Morel - - Dmitriy Derepko + - Markus S. (staabm) + - Guilherme Ferreira - Geoffrey Tran (geoff) - - Thiago Cordeiro (thiagocordeiro) - - Jan Behrens - - Dragos Protung (dragosprotung) - - Romain Monteil (ker0x) + - Elan Ruusamäe (glen) + - Brad Jones + - Nicolas de Marqué (nicola) + - Jannik Zschiesche + - Jan Ole Behrens (deegital) - Mantas Var (mvar) - - Terje Bråten + - Florent Morselli (spomky_) - Yann LUCAS (drixs6o9) - Sebastian Krebs + - Htun Htun Htet (ryanhhh91) + - Sorin Pop (sorinpop) - Piotr Stankowski - Stewart Malik - Stefan Graupner (efrane) - Gemorroj (gemorroj) - - Baptiste Leduc (bleduc) - - Julien Maulny + - Adrien Chinour - Mihail Krasilnikov (krasilnikovm) - iamvar - Pierre Tondereau + - Joel Lusavuvu (enigma97) - Alex Vo (votanlean) - - Daniel González (daniel.gonzalez) + - André Matthies - Piergiuseppe Longo - Kevin Auivinet + - Valentin Nazarov - Aurélien MARTIN - Malte Schlüter - Jules Matsounga (hyoa) - - Quentin Dequippe (qdequippe) - - khoptynskyi - - Jean-Christophe Cuvelier [Artack] - - julien57 - - Julien Montel (julienmgel) - - Mátyás Somfai (smatyas) + - Yewhen Khoptynskyi (khoptynskyi) + - Jérôme Nadaud (jnadaud) + - wuchen90 - Alexandre Tranchant (alexandre_t) - Anthony Moutte + - shreyadenny + - Daniel Iwaniec - Thomas Ferney (thomasf) - - Simon DELICATA - Hallison Boaventura (hallisonboaventura) + - Mas Iting + - Albion Bame (abame) + - Ivan Nemets - Dmitry Simushev + - Grégoire Hébert (gregoirehebert) - alcaeus - - Thomas Talbot (ioni) - Fred Cox - Iliya Miroslavov Iliev (i.miroslavov) - Safonov Nikita (ns3777k) + - Simon DELICATA + - Thibault Buathier (gwemox) + - Julien Boudry - vitaliytv - - Egor Taranov + - Andreas Hennings + - Arnaud Frézet - Nicolas Martin (cocorambo) - - Jon Gotlin (jongotlin) - - Adrian Nguyen (vuphuong87) - - Khoo Yong Jun + - luffy1727 + - Allison Guilhem (a_guilhem) + - LHommet Nicolas (nicolaslh) - Sebastian Blum + - Amirreza Shafaat (amirrezashafaat) - Laurent Clouet - - aubx - - Julien Turby - - Marvin Butkereit + - Adoni Pavlakis (adoni) + - Maarten Nusteling (nusje2000) + - Ahmed EBEN HASSINE (famas23) - Eduard Bulava (nonanerz) - - Renan - Ricky Su (ricky) - Igor Timoshenko (igor.timoshenko) + - “teerasak” - Kyle Evans (kevans91) - Benoit Mallo - - Charles-Henri Bruyand - Max Rath (drak3) + - Giuseppe Campanelli - Valentin - pizzaminded + - Matthieu Calie (matth--) - Stéphane Escandell (sescandell) - - Konstantin S. M. Möllers (ksmmoellers) - - Fractal Zombie + - ivan - linh + - Oleg Krasavin (okwinza) + - Mario Blažek (marioblazek) + - Jure (zamzung) - James Johnston + - Michael Nelson + - Eric Krona - Sinan Eldem + - Gennady Telegin - Kajetan Kołtuniak (kajtii) + - Sander Goossens (sandergo90) - Damien Fayet (rainst0rm) - Alexandre Dupuy (satchette) - MatTheCat - Malte Blättermann - - Islam Israfilov (islam93) + - Erfan Bahramali - Simeon Kolev (simeon_kolev9) - - Joost van Driel (j92) + - Abdiel Carrazana (abdielcs) + - Arman + - Gabi Udrescu + - Adamo Crespi (aerendir) - Jonas Elfering + - Luis Pabon (luispabon) + - boulei_n + - Anna Filina (afilina) + - Mihai Stancu - Nahuel Cuesta (ncuesta) + - Patrick Luca Fazzi (ap3ir0n) - Chris Boden (cboden) + - EStyles (insidestyles) - Christophe Villeger (seragan) + - Bruno Rodrigues de Araujo (brunosinister) - Julien Fredon - Jacek Wilczyński (jacekwilczynski) - - Xavier Leune (xleune) - Hany el-Kerdany - Wang Jingyu + - Benjamin Georgeault (wedgesama) - Åsmund Garfors - Maxime Douailin - - Jean Pasdeloup (pasdeloup) + - Jean Pasdeloup + - Laurent Moreau + - Michael Hirschler (mvhirsch) - Javier López (loalf) + - tamar peled - Reinier Kip + - Robert Meijers - Geoffrey Brier (geoffrey-brier) - - Alexandre Parent - - Roger Guasch (rogerguasch) - - Vladimir Tsykun + - Sofien Naas + - Christophe Meneses (c77men) - Andrei O - Dustin Dobervich (dustin10) - - Luis Tacón (lutacon) - - Dmitrii Tarasov (dtarasov) + - Alejandro Diaz Torres - Karl Shea - dantleech - - Philipp Kolesnikov - Valentin - - Maxim Dovydenok (shiftby) - - Anne-Sophie Bachelard (annesophie) - Sebastian Marek (proofek) + - Łukasz Chruściel (lchrusciel) - Jan Vernieuwe (vernija) - zenmate - - Michal Trojanowski - j.schmitt + - Georgi Georgiev - David Fuhr - Evgeny Anisiforov - - smoench - - Max Grigorian (maxakawizard) - - Martins Sipenko - - Guilherme Augusto Henschel + - TristanPouliquen + - Gwendolen Lynch + - mwos + - Aurimas Niekis (gcds) + - Volker Killesreiter (ol0lll) + - Vedran Mihočinec (v-m-i) + - creiner + - RevZer0 (rav) + - remieuronews + - Marek Binkowski + - Benjamin Schoch (bschoch) - Rostyslav Kinash + - Andrey Lebedev (alebedev) - Cristoforo Cervino (cristoforocervino) - Dennis Fridrich (dfridrich) - - Mardari Dorel (dorumd) + - Yoann MOROCUTTI - Daisuke Ohata - Vincent Simonin + - Alexander Onatskiy + - Philipp Fritsche + - tarlepp - Alex Bogomazov (alebo) - - maxime.steinhausser - Claus Due (namelesscoder) - - adev + - aaa2000 (aaa2000) + - Guillaume Aveline - Alexandru Patranescu - - Andy Palmer (andyexeter) - - Stefan Warman + - Arkadiusz Rzadkowolski (flies) + - Oksana Kozlova (oksanakozlova) + - Quentin Moreau (sheitak) + - Stefan Warman (warmans) + - Bert Ramakers - Tristan Maindron (tmaindron) - - Behnoush norouzali (behnoush) - - Marko H. Tamminen (gzumba) + - Behnoush Norouzali (behnoush) + - Marc Duboc (icemad) - Wesley Lancel - Ke WANG (yktd26) - Timothée BARRAY - Nilmar Sanchez Muguercia - Ivo Bathke (ivoba) - - Ippei SUmida (ippey_s) - - David Molineus + - Lukas Mencl - Strate - - Jon Green - Anton A. Sumin + - Atthaphon Urairat + - Jon Green (jontjs) + - Mickaël Isaert (misaert) - Israel J. Carberry + - Julius Kiekbusch - Miquel Rodríguez Telep (mrtorrent) + - Tamás Nagy (t-bond) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski + - Benjamin - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - - Shaun Simmons (simshaun) + - Oleksii Svitiashchuk + - Tristan Bessoussa (sf_tristanb) - Richard Bradley - - Ulumuddin Yunus (joenoez) - - rtek + - Nathanaël Martel (nathanaelmartel) + - Nicolas Jourdan (nicolasjc) + - Ulumuddin Cahyadi Yunus (joenoez) - Benjamin Dos Santos - - Jérémy Jarrié (gagnar) - - Adrien Jourdier + - GagnarTest (gagnartest) - Tomas Javaisis - - Ivan Grigoriev + - Florian Pfitzer (marmelatze) - Johann Saunier (prophet777) - - Kevin SCHNEKENBURGER - - Fabien Salles (blacked) - - Andreas Erhard + - Lucas Bäuerle + - Dario Savella + - Jack Thomas + - Andreas Erhard (andaris) + - Evgeny Efimov (edefimov) - John VanDeWeghe - - Sergey Belyshkin + - Oleg Mifle - Michael Devery (mickadoo) + - Loïc Ovigne (oviglo) - Antoine Corcy - - Ahmed Ashraf (ahmedash95) - - Gert Wijnalda (cinamo) - - Luca Saba (lucasaba) + - Markkus Millend + - Clément + - Jorrit Schippers (jorrit) + - Aurimas Niekis (aurimasniekis) - maxime.perrimond - - Sascha Grossenbacher + - rvoisin - cthulhu - - Arun Philip + - Sascha Grossenbacher (berdir) + - Dmitry Derepko - Rémi Leclerc + - Jan Vernarsky - Jonas Hünig + - Amine Yakoubi + - Robin Lehrmann - Szijarto Tamas - - Thomas P - - Robin Lehrmann (robinlehrmann) - - Catalin Dan + - Arend Hummeling + - Makdessi Alex + - Juan Miguel Besada Vidal (soutlink) + - dlorek + - Stuart Fyfe - Jaroslav Kuba - - Kristijan Kanalas - - Stephan Vock - Benjamin Zikarsky (bzikarsky) - - Marion Hurteau + - Jason Schilling (chapterjason) + - Nathan PAGE (nathix) + - Rodrigo Méndez (rodmen) + - sl_toto (sl_toto) + - Marek Pietrzak (mheki) - Dmitrii Lozhkin + - Marion Hurteau (marionleherisson) + - Mickaël Andrieu (mickaelandrieu) + - Oscar Esteve (oesteve) - Sobhan Sharifi (50bhan) + - Peter Potrowl - Stephen - Tomasz (timitao) - Nguyen Tuan Minh (tuanminhgp) - - Malte Schlüter - - Simon Watiau (simonwatiau) - - Ruben Jacobs (rubenj) + - dbrekelmans + - Piet Steinhart + - mousezheng + - Rémy LESCALLIER - Simon Schick (simonsimcity) - - redstar504 + - Victor Macko (victor_m) - Tristan Roussel + - Quentin Devos + - Jorge Vahldick (jvahldick) + - Vladimir Mantulo (mantulo) + - aim8604 + - Aleksandr Dankovtsev + - Maciej Zgadzaj + - David Legatt (dlegatt) + - Maarten de Boer (mdeboer) - Cameron Porter - Hossein Bukhamsin - Oliver Hoff - Christian Sciberras (uuf6429) - Arthur Woimbée - Théo DELCEY - - Disparity - Andrii Serdiuk (andreyserdjuk) - dangkhoagms (dangkhoagms) - Floran Brutel (notFloran) (floran) + - Vlad Gapanovich (gapik) - origaminal - Matteo Beccati (matteobeccati) + - Konstantin Bogomolov + - Mark Spink + - Cesar Scur (cesarscur) + - Maximilian Beckers (maxbeckers) - Kevin (oxfouzer) - Paweł Wacławczyk (pwc) - Sagrario Meneses @@ -1093,847 +1310,1073 @@ The Symfony Connect username in parenthesis allows to get more information - Stefano A. (stefano93) - Tales Santos (tsantos84) - Johannes Klauss (cloppy) + - PierreRebeilleau - Evan Villemez - Florian Hermann (fhermann) - fzerorubigd - Thomas Ploch - Benjamin Grandfond (benjamin) - Tiago Brito (blackmx) + - Gintautas Miselis (naktibalda) + - Christian Rishøj - Roromix + - Patrick Berenschot + - SuRiKmAn + - rtek - Maxime AILLOUD (mailloud) - Richard van den Brand (ricbra) - - Toon Verwerft (veewee) - mohammadreza honarkhah - develop - flip111 + - Artem Oliinyk (artemoliynyk) + - Marvin Feldmann (breyndotechse) + - fruty - VJ - RJ Garcia - Adam Wójs (awojs) + - Justin Reherman (jreherman) - Delf Tonder (leberknecht) - Paweł Niedzielski (steveb) - Peter Jaap Blaakmeer + - Agustin Gomes - Ondrej Exner - Mark Sonnabaum + - Adiel Cristo (arcristo) + - Fabian Kropfhamer (fabiank) - Junaid Farooq (junaidfarooq) + - Chris Jones (magikid) - Massimiliano Braglia (massimilianobraglia) + - Swen van Zanten (swenvanzanten) - Frankie Wittevrongel - Richard Quadling + - James Hudson (mrthehud) + - Adam Prickett - Raphaëll Roussel + - Luke Towers - Anton Kroshilin - - Michael Lutz + - Norman Soetbeer + - William Thomson (gauss) - Javier Espinosa (javespi) - jochenvdv - - Reedy + - František Maša - Arturas Smorgun (asarturas) - Andrea Sprega (asprega) - - Alexander Volochnev (exelenz) + - Aleksandr Volochnev (exelenz) - Viktor Bajraktar (njutn95) + - Robin van der Vleuten (robinvdvleuten) + - Grinbergs Reinis (shima5) + - Ruud Arentsen + - Harald Tollefsen + - Arend-Jan Tetteroo - Mbechezi Nawo - - Michael Piecko + - Klaus Silveira (klaussilveira) + - Andre Eckardt (korve) + - Michael Piecko (michael.piecko) + - Osayawe Ogbemudia Terry (terdia) - Toni Peric (tperic) - yclian - Aleksey Prilipko - - Jelle Raaijmakers (gmta) - - Damien Fa - Andrew Berry - - twifty - - Indra Gunawan (guind) - - Roberto Nygaard - - Peter Ward + - Wybren Koelmans (wybren_koelmans) + - Dmytro Dzubenko + - Benjamin RICHARD + - pdommelen + - Cedrick Oka - Davide Borsatto (davide.borsatto) - Guillaume Sainthillier (guillaume-sainthillier) - - Benjamin RICHARD (rebolon) - - James Gilliland (neclimdul) - - Gert de Pagter - - Ilya Ch. (ilya0) + - Jens Hatlak + - Tayfun Aydin + - Arne Groskurth + - Ilya Chekalsky + - zenas1210 + - Ostrzyciel - Julien DIDIER (juliendidier) - Ilia Sergunin (maranqz) + - Johan de Ruijter - marbul - - Dominik Ritter (dritter) + - Filippos Karailanidis + - David Brooks + - Volodymyr Kupriienko (greeflas) - Sebastian Grodzicki (sgrodzicki) - Florian Caron (shalalalala) - - Jeroen van den Enden (stoefke) + - Serhiy Lunak (slunak) + - Wojciech Błoszyk (wbloszyk) + - Jeroen van den Enden (endroid) + - abunch + - tamcy + - Mikko Pesari - Aurélien Fontaine - Pascal Helfenstein + - Malcolm Fell (emarref) + - phuc vo (phucwan) - Baldur Rensch (brensch) - - Carl Casbolt (carlcasbolt) + - Bogdan Scordaliu + - Daniel Rotter (danrot) + - Foxprodev + - developer-av - Vladyslav Petrovych + - Loïc Chardonnet - Hugo Sales + - Dale.Nash - Alex Xandra Albert Sim - - Carson Full - Sergey Yastrebov - - kylekatarnls (kylekatarnls) - - Trent Steel (trsteel88) + - Carson Full (carsonfull) - Yuen-Chi Lian + - Maxim Semkin + - BrokenSourceCode + - Fabian Haase + - Nikita Popov (nikic) + - Robert Fischer (sandoba) - Tarjei Huse (tarjei) - Besnik Br - - Axel Guckelsberger (guite) + - Michael Olšavský + - Benny Born + - Emirald Mateli + - Tristan Pouliquen - Jose Gonzalez - - Jonathan (jls-esokia) - - Dariusz Ruminski - Claudio Zizza + - Ivo Valchev - Zlatoslav Desyatnikov - Wickex - tuqqu - Neagu Cristian-Doru (cristian-neagu) - Dave Marshall (davedevelopment) - Jakub Kulhan (jakubkulhan) - - Shaharia Azam - avorobiev - - Gerben Oolbekkink + - Gladhon - Kai - Bartłomiej Zając - - stoccc + - Maximilian.Beckers - Grégoire Penverne (gpenverne) - Venu - - Lars Vierbergen - Jonatan Männchen - Dennis Hotson - Andrew Tchircoff (andrewtch) + - Lars Vierbergen (vierbergenlars) + - Barney Hanlon + - Bart Wach + - Jos Elstgeest + - Kirill Lazarev + - Serhii Smirnov + - Martins Eglitis - michaelwilliams + - Wouter Diesveld - Romain - Matěj Humpál + - Guillaume Loulier (guikingone) + - Pedro Casado (pdr33n) - Pierre Grimaud (pgrimaud) - - Alexandre Parent + - Alexander Janssen (tnajanssen) - 1emming - Nykopol (nykopol) + - Julien BERNARD + - Michael Zangerle - Jordan Deitch - Raphael Hardt - Casper Valdemar Poulsen - SnakePin - - vladimir.panivko + - Matthew Covey + - Anthony Massard (decap94) + - Chris Maiden (matason) + - Andrea Ruggiero (pupax) - Josiah (josiah) - - Guillaume Verstraete (versgui) + - Alexandre Beaujour + - George Yiannoulopoulos - Joschi Kuphal - John Bohn (jbohn) - - Marc Morera (mmoreram) - - Jason Tan - - Julien Pauli + - Peter Schultz + - Benhssaein Youssef + - bill moll + - PaoRuby + - Bizley + - Edvin Hultberg - Dominik Piekarski (dompie) - Rares Sebastian Moldovan (raresmldvn) - - Jérémy REYNAUD (babeuloula) - - Mathieu Rochette (mathroc) + - Felds Liscia (felds) + - dsech + - Gilbertsoft + - tadas + - Bastien Picharles + - mamazu - Victor Garcia - - Jérôme Tanghe (deuchnord) + - Juan Mrad + - Denis Yuzhanin + - knezmilos13 + - alireza + - Marcin Kruk - Marek Víger (freezy) - Andrew Hilobok (hilobok) + - Wahyu Kristianto (kristories) - Noah Heck (myesain) + - Stephan Wentz (temp) - Christian Soronellas (theunic) - - kick-the-bucket - fedor.f - - Bilge - Yosmany Garcia (yosmanyga) - - Jeremiasz Major - - Wouter de Wild - - Trevor North + - Markus Staab + - bahram + - Marie Minasyan (marie.minassyan) - Degory Valentine - izzyp - - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) - - Krzysiek Łabuś + - Martin (meckhardt) + - Radosław Kowalewski + - JustDylan23 + - buffcode - Juraj Surman - - Camille Dejoye - - 1ma (jautenim) - - Douglas Hammond (wizhippo) + - Victor + - Andreas Allacher + - Alexis + - Camille Dejoye (cdejoye) + - Krzysztof Łabuś (crozin) + - cybernet (cybernet2u) + - Stefan Kleff (stefanxl) + - Thijs-jan Veldhuizen (tjveldhuizen) - Xavier Lacot (xavier) - possum - Denis Zunke (donalberto) - - Ahmadou Waly Ndiaye (waly) - - Antonin CLAUZIER (0x346e3730) - - moldman - - Jonathan Johnson (jrjohnson) - - Olivier Maisonneuve (olineuve) + - _sir_kane (waly) + - Olivier Maisonneuve + - Bruno BOUTAREL + - John Stevenson + - everyx + - Stanislav Gamayunov (happyproff) + - Alexander McCullagh (mccullagh) + - Paul L McNeely (mcneely) + - Mike Meier (mykon) - Pedro Miguel Maymone de Resende (pedroresende) + - Sergey Fokin (tyraelqp) - Masterklavi - Franco Traversaro (belinde) - Francis Turmel (fturmel) - Nikita Nefedov (nikita2206) + - Bernat Llibre + - Daniel Burger - cgonzalez - - hugovms - Ben + - Joni Halme + - aetxebeste - roromix - - Dmitry Pigin (dotty) + - Vitali Tsyrkin + - Juga Paazmaya + - afaricamp + - riadh26 + - Konstantinos Alexiou + - Dilek Erkut + - WaiSkats + - Morimoto Ryosuke + - Christoph König (chriskoenig) + - Dmytro Pigin (dotty) - Vincent Composieux (eko) + - Jm Aribau (jmaribau) - Jayson Xu (superjavason) - fago - popnikos - Tito Costa - Jan Prieser - - GDIBass - - Maximilian Bösing - Thiago Melo + - Giorgio Premi + - Matt Johnson (gdibass) + - Gerhard Seidel (gseidel) - Zhuravlev Alexander (scif) - Stefano Degenkamp (steef) - James Michael DuPont - - Jake (jakesoft) + - kor3k kor3k (kor3k) + - Rustam Bakeev (nommyde) + - Eric Schildkamp + - agaktr + - Vincent CHALAMON + - Mostafa + - kernig + - Gennadi Janzen + - SenTisso + - Joe Springe + - Ivan Kurnosov - Flinsch - - Quentin Dreyer - - Bahman Mehrdad (bahman) + - botbotbot + - Timon van der Vorm + - G.R.Dalenoort + - Vladimir Khramtsov (chrome) + - Denys Voronin (hurricane) - Jordan de Laune (jdelaune) + - Juan Gonzalez Montes (juanwilde) + - Mathieu Dewet (mdewet) - Christopher Hall (mythmakr) - none (nelexa) - Patrick Dawkins (pjcdawkins) - Paul Kamer (pkamer) - Rafał Wrzeszcz (rafalwrzeszcz) - - Vincent CHALAMON (vincentchalamon) + - Reyo Stallenberg (reyostallenberg) + - Rémi Faivre (rfv) + - Nguyen Xuan Quynh - Reen Lokum - Martin Parsiegla (spea) - Bernhard Rusch - - Mario Ramundo (rammar) - - Ivan - - Quentin Schuler - - Nico Haase + - Ruben Jansen + - Marc Biorklund + - shreypuranik + - Thibaut Salanon + - Urban Suppiger + - Denis Charrier (brucewouaigne) + - Marcello Mönkemeyer (marcello-moenkemeyer) + - Sander De la Marche (sanderdlm) + - Philipp Scheit (pscheit) - Pierre Vanliefland (pvanliefland) - Roy Klutman (royklutman) - Sofiane HADDAG (sofhad) + - Quentin Schuler (sukei) + - VojtaB - frost-nzcr4 + - Yuri Karaban + - Johan + - Edwin + - Andriy - Taylor Otwell - - Shahriar56 - Sami Mussbach - - Dhananjay Goratela - - Kien Nguyen + - qzylalala + - Mikolaj Czajkowski + - Shiro + - Reda DAOUDI + - Jesper Skytte + - Christiaan Wiesenekker + - Bozhidar Hristov - Foxprodev - Eric Hertwig + - Sergey Panteleev + - Dmitry Hordinky + - Oliver Klee - Niels Robin-Aubertin - - Achilles Kaloeridis (achilles) + - Mikko Ala-Fossi + - Jan Christoph Beyer + - Daniel Tiringer + - Koray Zorluoglu + - Roy-Orbison + - kshida + - Yasmany Cubela Medina (bitgandtter) + - Aryel Tupinamba (dfkimera) + - Hans Höchtl (hhoechtl) + - Jawira Portugal (jawira) - Laurent Bassin (lbassin) - - Mouad ZIANI (mouadziani) - - Tomasz Ignatiuk + - Roman Igoshin (masterro) + - Jeroen van den Nieuwenhuisen (nieuwenhuisen) + - Pierre Rebeilleau (pierrereb) + - Raphael de Almeida (raphaeldealmeida) - andrey1s - Abhoryo - Fabian Vogler (fabian) - - Shakhobiddin - Korvin Szanto + - Simon Ackermann - Stéphan Kochen - Steven Dubois - Arjan Keeman - - siganushka + - Bálint Szekeres - Alaattin Kahramanlar (alaattin) - Sergey Zolotov (enleur) + - Nicole Cordes (ichhabrecht) + - Mark Beech (jaybizzle) - Maksim Kotlyar (makasim) + - Thibaut Arnoud (thibautarnoud) - Neil Ferreira - Julie Hourcade (juliehde) - Dmitry Parnas (parnas) - - Paul LE CORRE - - Loïc Beurlet + - Christian Weiske + - Maria Grazia Patteri - Sébastien COURJEAN - - Ana Raro - - Ana Raro + - Marko Vušak + - Ismo Vuorinen - Tony Malzhacker + - Valentin + - Ali Tavafi + - Viet Pham - Pchol - - Mathieu MARCHOIS + - divinity76 + - Yiorgos Kalligeros + - Arek Bochinski + - Rafael Tovar + - Amin Hosseini (aminh) + - Andreas Lutro (anlutro) + - DUPUCH (bdupuch) - Cyril Quintin (cyqui) - Cyrille Bourgois (cyrilleb) - Gerard van Helden (drm) - - Florian Wolfsjaeger (flowolf) - - Ivan Sarastov (isarastov) - Johnny Peck (johnnypeck) - - Jordi Sala Morales (jsala) + - Geoffrey Monte (numerogeek) + - Martijn Boers (plebian) + - Plamen Mishev (pmishev) + - Sergii Dolgushev (serhey) + - Rein Baarsma (solidwebcode) + - Stephen Lewis (tehanomalousone) + - wicliff wolda (wickedone) + - Wim Molenberghs (wimm) + - Loic Chardonnet - Ivan Menshykov - David Romaní - Patrick Allaert + - Alexander Li (aweelex) - Gustavo Falco (gfalco) - Matt Robinson (inanimatt) + - Marcel Berteler + - sdkawata - Aleksey Podskrebyshev - Calin Mihai Pristavu + - Rainrider + - Oliver Eglseder + - zcodes + - Jörn Lang - David Marín Carreño (davefx) - Fabien LUCAS (flucas2) - - Ondrej Machulda (ondram) - - Omar Yepez (oyepez003) + - Hidde Boomsma (hboomsma) + - Johan Wilfer (johanwilfer) + - Toby Griffiths (tog) - Ashura + - Alessandra Lai + - Ernest Hymel + - Andrea Civita + - Nicolás Alonso - mwsaz + - LoginovIlya - carlos-ea + - Olexandr Kalaidzhy - Jérémy Benoist - Ferran Vidal - - bogdan - - Jelle Kapitein - - Benoît Bourgeois + - youssef saoubou + - elattariyassine + - Carlos Tasada + - zors1 + - Peter Simoncic - lerminou - - mantulo + - Ahmad El-Bardan - pdragun - - corphi - - JoppeDC - - Daniel Tiringer + - Noel Light-Hilary + - Emre YILMAZ + - Marcos Labad + - Antoine M + - Frank Jogeleit + - Ondřej Frei + - Jenne van der Meer + - Storkeus + - Anton Zagorskii + - ging-dev + - zakaria-amm + - Geert De Deckere + - Agata + - dakur - grizlik + - florian-michael-mast + - Henry Snoek + - Vlad Dumitrache + - Alex Kalineskou - Derek ROTH + - Jeremy Benoist - Ben Johnson + - Jan Kramer - mweimerskirch - - Andrew Codispoti + - robmro27 + - Vallel Blanco + - Bastien Clément - Benjamin Franzke + - Pavinthan + - Sylvain METAYER + - Benjamin Laugueux + - Ivo Valchev - baron (bastien) + - Benoît Bourgeois (bierdok) + - Damien Harper (damien.harper) + - Dominik Pesch (dombn) - Dmytro Boiko (eagle) - Shin Ohno (ganchiku) - - Geert De Deckere (geertdd) - - Jan Kramer (jankramer) + - Jaap van Otterdijk (jaapio) - Kubicki Kamil (kubik) - - Simon Leblanc (leblanc_simon) - - Matthieu Mota (matthieumota) + - Vladislav Nikolayev (luxemate) + - Martin Mandl (m2mtech) + - Maxime Pinot (maximepinot) + - Misha Klomp (mishaklomp) + - Jean-Baptiste GOMOND (mjbgo) - Mikhail Prosalov (mprosalov) + - Ulrik Nielsen (mrbase) + - Artem (nexim) + - Nicolas ASSING (nicolasassing) + - Pierre Gasté (pierre_g) + - Pierre-Olivier Vares (povares) - Ronny López (ronnylt) + - Julius (sakalys) - abdul malik ikhsan (samsonasik) - - Henry Snoek (snoek09) - Dmitry (staratel) - Tito Miguel Costa (titomiguelcosta) - - Simone Di Maulo (toretto460) + - Wim Godden (wimg) + - Morgan Auchede - Christian Morgan - - Alexander Miehe (engerim) - - Morgan Auchede (mauchede) + - Alexander Miehe + - Simon (kosssi) - Sascha Dens (saschadens) - - Morten Wulff (wulff) + - Maxime Aknin (3m1x4m) + - Geordie + - Exploit.cz - Don Pinkster - Maksim Muruev - Emil Einarsson + - Jason Stephens - 243083df + - Tinjo Schöni - Thibault Duplessis - - Rimas Kudelis + - Quentin Favrie + - Matthias Derer + - vladyslavstartsev + - Kévin - Marc Abramowitz + - michal - Martijn Evers + - Sjoerd Adema - Tony Tran - Evgeniy Koval - - Jacques Moati - - Balazs Csaba (balazscsaba2006) - - Benoit Galati (benoitgalati) + - Claas Augner + - Balazs Csaba - Bill Hance (billhance) - Douglas Reith (douglas_reith) - - Forfarle (forfarle) - Harry Walter (haswalt) + - Jeffrey Moelands (jeffreymoelands) + - Jacques MOATI (jmoati) - Johnson Page (jwpage) - - Kuba Werłos (kuba) - Ruben Gonzalez (rubenruateltek) + - Ruslan Zavacky (ruslanzavacky) + - Stefano Cappellini (stefano_cappellini) - Michael Roterman (wtfzdotnet) - - Philipp Keck - Arno Geurts - Adán Lobato (adanlobato) - Ian Jenkins (jenkoian) - - Kai Eichinger (kai_eichinger) - Marcos Gómez Vilches (markitosgv) - Matthew Davis (mdavis1982) - - Paulo Ribeiro (paulo) - - Markus S. (staabm) - - Maks + - George Bateman + - misterx + - arend + - Vincent Godé + - helmi + - Michael Steininger + - Nardberjean + - jersoe + - Eric Grimois + - Beno!t POLASZEK + - Armando + - Jens Schulze + - Olatunbosun Egberinde - Knallcharge - - Antoine LA + - Michel Bardelmeijer + - Ikko Ashimine + - Erwin Dirks + - Markus Ramšak - den - - pawel-lewtak - - omerida + - George Dietrich + - jannick-holm + - Menno Holtkamp + - Ser5 + - Clemens Krack + - Bruno Baguette + - Alexis Lefebvre + - Michal Forbak + - Alexey Berezuev + - Pierrick Charron + - gechetspr + - brian978 + - Talha Zekeriya Durmuş + - bch36 + - Steve Hyde + - Ettore Del Negro + - dima-gr - Gábor Tóth + - Rodolfo Ruiz - tsilefy + - Enrico + - Jérémie Broutier + - Success Go + - Chris McGehee + - Benjamin Rosenberger + - Vladyslav Startsev - Markus Klein + - Bruno Nogueira Nascimento Wowk + - Tomanhez + - satalaondrej - Matthias Dötsch + - jonmldr + - ouardisoft + - RTUnreal + - Richard Hodgson + - Sven Fabricius - Bogdan + - Marco Pfeiffer - Daniel Cestari - Matt Janssen + - Kévin Gonella - Matteo Galli + - Ash014 - Loenix - Simon Frost - - David Lima + - Cantepie + - detinkin + - Harry Wiseman + - Steve Marvell + - Shyim + - sabruss + - Andrejs Leonovs + - Signor Pedro + - Matthias Larisch + - Maxime P - Sean Templeton + - Yendric - Stéphane Delprat + - Matthias Meyer + - Temuri Takalandze (abgeo) + - Bernard van der Esch (adeptofvoltron) + - Benedict Massolle (bemas) + - Gerard Berengue Llobera (bere) - Ronny (big-r) - - Brian Freytag (brianfreytag) - - Cătălin Dan (dancatalin) + - Anton (bonio) + - Alexandre Fiocre (demos77) - Erwan Nader (ernadoo) - - Elan Ruusamäe (glen) + - Faizan Akram Dar (faizanakram) + - Greg Szczotka (greg606) - Ian Littman (iansltx) + - Nathan DIdier (icz) + - Ilia Lazarev (ilzrv) - Arkadiusz Kondas (itcraftsmanpl) - Joao Paulo V Martins (jpjoao) - Brunet Laurent (lbrunet) - Jérémy (libertjeremy) - Florent Viel (luxifer) + - Maks 3w (maks3w) + - Mamikon Arakelyan (mamikon) + - Michiel Boeckaert (milio) + - Mike Milano (mmilano) + - Guillaume Lajarige (molkobain) + - Diego Aguiar (mollokhan) - Mikhail Yurasov (mym) - - LOUARDI Abdeltif (ouardisoft) + - PLAZANET Pierre (pedrotroller) + - Igor Tarasov (polosatus) - Robert Gruendler (pulse00) - - Sebastian Paczkowski (sebpacz) + - Ramazan APAYDIN (rapaydin) + - Babichev Maxim (rez1dent3) + - Christopher Georg (sky-chris) + - Francisco Alvarez (sormes) - Simon Terrien (sterrien) - - Success Go (successgo) + - Stephan Vierkant (svierkant) - Benoît Merlet (trompette) - Aaron Piotrowski (trowski) + - Roman Tymoshyk (tymoshyk) - Vincent MOULENE (vints24) - - Koen Kuipers - datibbaw - - Nicolas de Marqué (nicola) + - Koen Kuipers (koku) + - Ryan Linnit - Antoine Leblanc - Andre Johnson + - MaPePeR - Marco Pfeiffer + - Matthieu Bontemps + - Vivien - Rootie + - david-binda + - Alexandru Năstase + - ddegentesh + - Anne-Julia Seitz + - Alexander Bauer (abauer) + - Sébastien Santoro (dereckson) - Gabriel Solomon (gabrielsolomon) - Daniel Alejandro Castro Arellano (lexcast) - Aleksandar Dimitrov (netbull) - Gary Houbre (thegarious) - - sensio - Thomas Jarrand + - Baptiste Leduc (bleduc) - Antoine Bluchet (soyuka) - Patrick Kaufmann - Anton Dyshkant - - Paul Oms + - Kirill Nesmeyanov (serafim) - Reece Fowell (reecefowell) - - stefan.r - - Htun Htun Htet (ryanhhh91) + - Muhammad Aakash - Guillaume Gammelin - Valérian Galliat - - Sorin Pop (sorinpop) - d-ph - Renan Taranto (renan-taranto) - - Adrien Chinour - Rikijs Murgs - Uladzimir Tsykun - Amaury Leroux de Lens (amo__) - Christian Jul Jensen - - Alexandre GESLIN (alexandregeslin) + - Franck RANAIVO-HARISOA (franckranaivo) + - Alexandre GESLIN - The Whole Life to Learn - - joel lusavuvu (enigma97) - Mikkel Paulson - ergiegonzaga - - André Matthies + - kurozumi (kurozumi) - Liverbool (liverbool) - - Valentin Nazarov - - Jérôme Nadaud (jnadaud) + - Dalibor Karlović - Sam Malone - - Phan Thanh Ha (haphan) + - Ha Phan (haphan) - Chris Jones (leek) - neghmurken + - stefan.r - xaav + - Jean-Christophe Cuvelier [Artack] - Mahmoud Mostafa (mahmoud) - Ahmed Abdou - - shreyadenny - - Daniel Iwaniec - Pieter - Michael Tibben - - Mas Iting - Billie Thompson - - Albion Bame (abame) - - Ganesh Chandrasekaran + - Ganesh Chandrasekaran (gxc4795) - Sander Marechal - - Ivan Nemets - - Grégoire Hébert (gregoirehebert) - Franz Wilding (killerpoke) - - ProgMiner + - Ferenczi Krisztian (fchris82) - Oleg Golovakhin (doc_tr) - Icode4Food (icode4food) - Radosław Benkel - - EStyles (insidestyles) - - kevin.nadin + - Bert ter Heide (bertterheide) + - Kevin Nadin (kevinjhappy) - jean pasqualini (darkilliant) - Ross Motley (rossmotley) - ttomor - Mei Gwilym (meigwilym) - - Michael H. Arieli (excelwebzone) + - Michael H. Arieli + - Jitendra Adhikari (adhocore) - Tom Panier (neemzy) - Fred Cox - - luffy1727 - Luciano Mammino (loige) - - LHommet Nicolas (nicolaslh) - fabios - Sander Coolen (scoolen) - - Emil Masiakowski - - Amirreza Shafaat (amirrezashafaat) - - Adoni Pavlakis (adoni) - Nicolas Le Goff (nlegoff) - - Alex Hofbauer (alexhofbauer) - - Maarten Nusteling (nusje2000) - - Ahmed EBEN HASSINE (famas23) + - Anne-Sophie Bachelard + - Marvin Butkereit - Ben Oman + - Jack Worman (jworman) - Chris de Kok - - Andreas Kleemann + - Andreas Kleemann (andesk) + - Hubert Moreau (hmoreau) - Manuele Menozzi - - “teerasak” - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) + - Charles-Henri Bruyand - Danilo Silva - - Giuseppe Campanelli - - Matthieu Calie (matth--) - - Arnaud PETITPAS (apetitpa) + - Konstantin S. M. Möllers (ksmmoellers) - Ken Stanley - - ivan - Zachary Tong (polyfractal) - - Oleg Krasavin (okwinza) - - Mario Blažek (marioblazek) - - Jure (zamzung) - - Michael Nelson - Ashura - Hryhorii Hrebiniuk - - Eric Krona + - Alex Plekhanov - johnstevenson - hamza - dantleech - - Sander Goossens (sandergo90) - Rudy Onfroy - Tero Alén (tero) - - Stanislav Kocanda - DerManoMann - Guillaume Royer - - Erfan Bahramali - Artem (digi) - boite - Silvio Ginter - MGDSoft - - Abdiel Carrazana (abdielcs) + - joris - Vadim Tyukov (vatson) - - Arman - - Gabi Udrescu - - Adamo Crespi (aerendir) - David Wolter (davewww) - Sortex - chispita - Wojciech Sznapka - - Luis Pabon (luispabon) - - Gavin Staniforth - - boulei_n - - Anna Filina (afilina) + - Gavin (gavin-markup) - Ksaveras Šakys (xawiers) + - Shaun Simmons - Ariel J. Birnbaum - - Patrick Luca Fazzi (ap3ir0n) - Danijel Obradović - Pablo Borowicz - - Arjan Keeman - - Bruno Rodrigues de Araujo (brunosinister) + - Ondřej Frei - Máximo Cuadros (mcuadros) - - Lukas Mencl + - EXT - THERAGE Kevin - tamirvs - gauss - julien.galenski - - Christian Neff + - Florian Guimier + - Christian Neff (secondtruth) - Chris Tiearney - Oliver Hoff - Ole Rößner (basster) - - Laurent Moreau - Faton (notaf) - Tom Houdmont - - tamar peled + - mark burdett - Per Sandström (per) - Goran Juric - - Laurent Ghirardotti (laurentg) + - Laurent G. (laurentg) - Nicolas Macherey + - Asil Barkin Elik (asilelik) + - Bhujagendra Ishaya - Guido Donnari - - AKeeman (akeeman) - Mert Simsek (mrtsmsk0) - Lin Clark - - Meneses (c77men) - Jeremy David (jeremy.david) + - Michał Marcin Brzuchalski (brzuchal) - Jordi Rejas - Troy McCabe - Ville Mattila - - ilyes kooli - gr1ev0us + - Léo VINCENT - mlazovla - - Alejandro Diaz Torres - Max Beutel - - Łukasz Chruściel (lchrusciel) + - Nathan Sepulveda - Antanas Arvasevicius - Pierre Dudoret + - Michal Trojanowski - Thomas - - Georgi Georgiev + - Norbert Schultheisz - Maximilian Berghoff (electricmaxxx) - - nacho + - SOEDJEDE Felix (fsoedjede) + - otsch - Piotr Antosik (antek88) - - mwos - - Volker Killesreiter (ol0lll) - - Vedran Mihočinec (v-m-i) + - Nacho Martin (nacmartin) - Sergey Novikov (s12v) - - creiner + - ProgMiner - Marcos Quesada (marcos_quesada) - - Matthew Vickery (mattvick) + - Matthew (mattvick) - MARYNICH Mikhail (mmarynich-ext) - - Viktor Novikov (panzer_commander) + - Viktor Novikov (nowiko) - Paul Mitchum (paul-m) + - Phil E. Taylor (philetaylor) - Angel Koilov (po_taka) - - RevZer0 (rav) - Dan Finnie - - Marek Binkowski - Ken Marfilla (marfillaster) + - Max Grigorian (maxakawizard) + - allison guilhem - benatespina (benatespina) - Denis Kop - Jean-Guilhem Rouel (jean-gui) - - Yoann MOROCUTTI + - Ivan Yivoff + - EdgarPE - jfcixmedia - - Tomasz Kusy - Dominic Tubach - - Nikita Konstantinov - Martijn Evers - - Alexander Onatskiy - - Philipp Fritsche - - tarlepp - Benjamin Paap (benjaminpaap) - - Guillaume Aveline - Christian + - ju1ius - Denis Golubovskiy (bukashk0zzz) - - Arkadiusz Rzadkowolski (flies) - - Sergii Smertin (nfx) - - Oksana Kozlova (oksanakozlova) - - Quentin Moreau (sheitak) + - Serge (nfx) - Mikkel Paulson - Michał Strzelecki - - Bert Ramakers - - Angelov Dejan (angelov) - - hugofonseca (fonsecas72) - - Marc Duboc (icemad) + - Hugo Fonseca (fonsecas72) - Martynas Narbutas - Bailey Parker - - Eddie Jaoude + - curlycarla2004 - Antanas Arvasevicius + - Kris Kelly + - Eddie Abou-Jaoude (eddiejaoude) - Haritz Iturbe (hizai) - Nerijus Arlauskas (nercury) - - SPolischook - Diego Sapriza - Joan Cruz - inspiran + - Alex Demchenko - Cristobal Dabed - Daniel Mecke (daniel_mecke) - Matteo Giachino (matteosister) - - Alex Demchenko (pilot) + - Serhii Polishchuk (spolischook) - Tadas Gliaubicas (tadcka) - Thanos Polymeneas (thanos) - - Atthaphon Urairat - Benoit Garret + - HellFirePvP - Maximilian Ruta (deltachaos) - - Mickaël Isaert (misaert) - Jakub Sacha - - Julius Kiekbusch + - Kamil Musial - Olaf Klischat - - benjaminmal - orlovv - Claude Dioudonnat - Jonathan Hedstrom - Peter Smeets (darkspartan) - - Jhonny Lidfors (jhonny) - Julien Bianchi (jubianchi) - Robert Meijers + - Tijs Verkoyen - James Sansbury - Marcin Chwedziak - - Benjamin - hjkl - - Tony Cosentino (tony-co) - Dan Wilga - - Oleksii Svitiashchuk - Andrew Tch - Alexander Cheprasov - - Tristan Bessoussa (sf_tristanb) - Rodrigo Díez Villamuera (rodrigodiez) - - Nicolas Jourdan - - James Hudson - Stephen Clouse - e-ivanov - - Nathanaël Martel (nathanaelmartel) - - Einenlum + - Abderrahman DAIF (death_maker) + - Yann Rabiller (einenlum) - Jochen Bayer (jocl) - Patrick Carlo-Hickman - Bruno MATEU - Jeremy Bush - - Lucas Bäuerle - - wizhippo - Thomason, James - - Dario Savella - Gordienko Vladislav + - Ener-Getick - Viacheslav Sychov - - Alexandre Quercia (alquerci) + - Nicolas Sauveur (baishu) - Helmut Hummel (helhum) - Matt Brunt - - Jack Thomas - Carlos Ortega Huetos - - rpg600 - Péter Buri (burci) - - Evgeny Efimov (edefimov) - kaiwa - Charles Sanquer (csanquer) - Albert Ganiev (helios-ag) - Neil Katin - - Oleg Mifle - David Otton - Will Donohoe - - gnito-org - peter + - Jeroen de Boer - Jérémy Jourdin (jjk801) - BRAMILLE Sébastien (oktapodia) - - Loïc Ovigne (oviglo) - Artem Kolesnikov (tyomo4ka) - - Markkus Millend - - Clément - Gustavo Adrian - - Jorrit Schippers (jorrit) - Yannick - - Kai Dederichs + - Kuzia - Vladimir Luchaninov (luchaninov) - spdionis - rchoquet + - v.shevelev - gitlost - Taras Girnyk - - Dmitry Derepko - - Jan Vernarsky - - Amine Yakoubi + - Sergio + - Mehrdad - Eduardo García Sanz (coma) - - Sergio (deverad) - - Makdessi Alex - fduch (fduch) - - Juan Miguel Besada Vidal (soutlink) - - dlorek - - Stuart Fyfe - - Jason Schilling (chapterjason) - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) - - Nathan PAGE (nathix) + - Stephan Vock (glaubinix) + - Guillem Fondin (guillemfondin) - Ryan Rogers + - Arnaud - Klaus Purer - - arnaud (arnooo999) - Gilles Doge (gido) - - Oscar Esteve (oesteve) - - Peter Potrowl - abulford - Philipp Kretzschmar - - antograssiot + - Jairo Pastor - Ilya Vertakov - Brooks Boyd - - johnillo + - Axel Venet - Roger Webb - Dmitriy Simushev - Pawel Smolinski + - John Espiritu (johnillo) - Oxan van Leeuwen - pkowalczyk - - dbrekelmans - Soner Sayakci - Max Voloshin (maxvoloshin) - Nicolas Fabre (nfabre) - Raul Rodriguez (raul782) - - Piet Steinhart - - mousezheng - mshavliuk - - Rémy LESCALLIER - - WybrenKoelmans - - Derek Lambert + - Jesper Skytte - MightyBranch - Kacper Gunia (cakper) + - Derek Lambert (dlambert) + - Mark Pedron (markpedron) - Peter Thompson (petert82) - - Victor Macko (victor_m) - error56 - Felicitus - - Krzysztof Przybyszewski - alexpozzi - - Vladimir - - Quentin Devos - - Jorge Vahldick (jvahldick) + - Krzysztof Przybyszewski (kprzybyszewski) + - Boullé William (williamboulle) - Frederic Godfrin - Paul Matthews - - aim8604 - Jakub Kisielewski - Vacheslav Silyutin - - Aleksandr Dankovtsev - - Maciej Zgadzaj - Juan Traverso - - David Legatt (dlegatt) - Alain Flaus (halundra) - tsufeki - Philipp Strube - - Thomas Nunninger + - Petar Obradović - Clement Herreman (clemherreman) - Dan Ionut Dumitriu (danionut90) + - Evgeny (disparity) - Vladislav Rastrusny (fractalizer) - - Vlad Gapanovich (gapik) - Alexander Kurilo (kamazee) - - Nyro (nyro) + - nyro (nyro) - Marco - Marc Torres - - Mark Spink - - cesar + - gndk - Alberto Aldegheri - - Cesar Scur (cesarscur) - - “Filip + - Dalibor Karlović + - Cyril Vermandé (cyve) - Dmitri Petmanson - heccjj - Alexandre Melard - - PierreRebeilleau + - AlbinoDrought - Jay Klehr - Sergey Yuferev + - Monet Emilien + - voodooism - Tobias Stöckler - Mario Young + - martkop26 + - Sander Hagen - Ilia (aliance) - - Chris McCafferty (cilefen) + - cilefen (cilefen) - Mo Di (modi) - Pablo Schläpfer - - Christian Rishøj - - Patrick Berenschot - - SuRiKmAn - - rtek + - Nikos Charalampidis + - Xavier RENAUDIN + - Christian Wahler (christian) - Jelte Steijaert (jelte) - David Négrier (moufmouf) - Quique Porta (quiqueporta) - - Artem Oliynyk (artemoliynyk) - - Ben Roberts (benr77) + - Tobias Feijten (tobias93) - Andrea Quintino (dirk39) + - Andreas Heigl (heiglandreas) - Tomasz Szymczyk (karion) + - Peter Dietrich (xosofox) - Alex Vasilchenko - sez-open - - Xavier Coureau - - fruty - ConneXNL - Aharon Perkel - matze - - Justin Reherman (jreherman) - Rubén Calvo (rubencm) - Abdul.Mohsen B. A. A - - Swen van Zanten - - Agustin Gomes - - Benoît Burnichon + - Cédric Girard - pthompson - Malaney J. Hill + - Patryk Kozłowski - Alexandre Pavy - - Adiel Cristo (arcristo) - - Artem Stepin (astepin) + - Tim Ward - Christian Flach (cmfcmf) - - Cédric Girard (enk_) - - Fabian Kropfhamer (fabiank) - Lars Ambrosius Wallenborn (larsborn) - Oriol Mangas Abellan (oriolman) - Sebastian Göttschkes (sgoettschkes) - Tatsuya Tsuruoka - Ross Tuck - - Oleksiy (alexndlm) + - omniError + - Zander Baldwin + - László GÖRÖG - Kévin Gomez (kevin) + - Kevin van Sonsbeek (kevin_van_sonsbeek) - Mihai Nica (redecs) - Andrei Igna - - Adam Prickett - azine - - Luke Towers + - Wojciech Zimoń + - Pierre Tachoire - Dawid Sajdak - - Norman Soetbeer - Ludek Stepan + - Mark van den Berg - Aaron Stephens (astephens) - Craig Menning (cmenning) - Balázs Benyó (duplabe) - Erika Heidi Reinaldo (erikaheidi) - - Kyryll Maesh (gauss) - - Pierre Tachoire (krichprollsch) - Marc J. Schmidt (marcjs) - - František Maša - Sebastian Schwarz + - karolsojko - Marco Jantke - Saem Ghani - - Clément LEFEBVRE - - Conrad Kleinespel - Zacharias Luiten - Sebastian Utz - Adrien Gallou (agallou) - Maks Rafalko (bornfree) - - Karol Sójko (karolsojko) - - sl_toto (sl_toto) + - Conrad Kleinespel (conradk) + - Clément LEFEBVRE (nemoneph) - Walter Dal Mut (wdalmut) - abluchet - - Ruud Arentsen - - Harald Tollefsen + - PabloKowalczyk - Matthieu - - Arend-Jan Tetteroo - Albin Kerouaton - Sébastien HOUZÉ - Jingyu Wang - steveYeah - - Samy Dindane (dinduks) + - Samy D (dinduks) - Keri Henare (kerihenare) - - Andre Eckardt (korve) - Cédric Lahouste (rapotor) - Samuel Vogel (samuelvogel) - - Osayawe Ogbemudia Terry (terdia) - - AndrolGenhald - Berat Doğan - Guillaume LECERF - Juanmi Rodriguez Cerón + - twifty - Andy Raines - Anthony Ferrara - Geoffrey Pécro (gpekz) @@ -1941,161 +2384,137 @@ The Symfony Connect username in parenthesis allows to get more information - Klaas Cuvelier (kcuvelier) - Flavien Knuchel (knuch) - Mathieu TUDISCO (mathieutu) - - Dmytro Dzubenko + - Peter Ward - markusu49 - Steve Frécinaux - Constantine Shtompel - Jules Lamur - Renato Mendes Figueiredo - - pdommelen + - Raphaël Droz - Eric Stern - ShiraNai7 - - Cedrick Oka - Antal Áron (antalaron) - Vašek Purchart (vasek-purchart) - Janusz Jabłoński (yanoosh) - Fleuv - - Tayfun Aydin - - Sandro Hopf - Łukasz Makuch - - Arne Groskurth - - Ostrzyciel - George Giannoulopoulos - - Alexander Pasichnick + - Alexander Pasichnik (alex_brizzz) - Luis Ramirez (luisdeimos) - Daniel Richter (richtermeister) + - Sandro Hopf (senaria) - ChrisC - - JL - - Ilya Biryukov + - jack.shpartko + - Willem Verspyck - Kim Laï Trinh - - Johan de Ruijter - Jason Desrosiers - m.chwedziak - - Filippos Karailanidis - Andreas Frömer + - Bikal Basnet - Philip Frank - - David Brooks - Lance McNearney - - Volodymyr Kupriienko (greeflas) - - Serhiy Lunak (slunak) - - Wojciech Błoszyk (wbloszyk) + - Illia Antypenko (aivus) + - Jelizaveta Lemeševa (broken_core) + - Dominik Ritter (dritter) + - Frank Neff (fneff) + - Ilya Biryukov (ibiryukov) + - Roma (memphys) - Giorgio Premi - - abunch - - tamcy - - Mikko Pesari + - Matthias Bilger + - Krzysztof Pyrkosz - ncou - Ian Carroll - caponica - Daniel Kay (danielkay-cp) - Matt Daum (daum) - - Malcolm Fell (emarref) - Alberto Pirovano (geezmo) + - Pascal Woerde (pascalwoerde) - Pete Mitchell (peterjmit) - - phuc vo (phucwan) - Tom Corrigan (tomcorrigan) - Luis Galeas - - Bogdan Scordaliu - Martin Pärtel - - Daniel Rotter (danrot) - Frédéric Bouchery (fbouchery) - Patrick Daley (padrig) - - Foxprodev + - Phillip Look (plook) - Max Summe - - WedgeSama - - Dale.Nash - - Felds Liscia + - Ema Panz - Chihiro Adachi (chihiro-adachi) - Raphaëll Roussel - Tadcka + - Abudarham Yuval - Beth Binkovitz - - Maxim Semkin - Gonzalo Míguez - - BrokenSourceCode - - Fabian Haase - Romain Geissler - Adrien Moiruad - Tomaz Ahlin - - Philip Ardery - Nasim + - AnotherSymfonyUser (arderyp) - Marcus Stöhr (dafish) - Daniel González Zaballos (dem3trio) - Emmanuel Vella (emmanuel.vella) - Guillaume BRETOU (guiguiboy) - - Nikita Popov (nikic) + - Ibon Conesa (ibonkonesa) + - Yoann Chocteau (kezaweb) + - nuryagdy mustapayev (nueron) - Carsten Nielsen (phreaknerd) - - Michael Olšavský - Jay Severson - - Benny Born - - Emirald Mateli - - Tristan Pouliquen - René Kerner - Nathaniel Catchpole - Adrien Samson (adriensamson) - Samuel Gordalina (gordalina) - - Max Romanovsky (maxromanovsky) + - Maksym Romanowski (maxromanovsky) - Nicolas Eeckeloo (neeckeloo) - Andriy Prokopenko (sleepyboy) - - Mathieu Morlon - - Ivo Valchev + - Dariusz Ruminski + - Thomas Hanke - Daniel Tschinder - Arnaud CHASSEUX - Wojciech Gorczyca + - Mathieu Morlon (glutamatt) - Rafał Muszyński (rafmus90) - Sébastien Decrême (sebdec) - Timothy Anido (xanido) + - acoulton - Mara Blaga - Rick Prent - skalpa - - Martin Eckhardt + - Pierre Foresi - Pieter Jordaan - - Damien Tournoud + - Tournoud (damientournoud) - Michael Dowling (mtdowling) + - Arnaud POINTET (oipnet) - Karlos Presumido (oneko) - Tony Vermeiren (tony) - - Bart Wach - - Jos Elstgeest - - Kirill Lazarev - Thomas Counsell - BilgeXA - - r1pp3rj4ck - - phydevs - mmokhi - - Serhii Smirnov - Robert Queck - Peter Bouwdewijn - - Martins Eglitis - - mlively - - Wouter Diesveld + - Daniil Gentili + - Eduard Morcinek - Amine Matmati + - Kristen Gilden - caalholm - Nouhail AL FIDI (alfidi) - Fabian Steiner (fabstei) - - Felipy Tavares Amorim (felipyamorim) - - Guillaume Loulier (guikingone) - - Klaus Silveira (klaussilveira) - - Pedro Casado (pdr33n) - - Alexander Janssen (tnajanssen) + - Felipy Amorim (felipyamorim) + - Michael Lively (mlivelyjr) + - Abderrahim (phydev) + - Attila Bukor (r1pp3rj4ck) + - Thomas Boileau (tboileau) - Thomas Chmielowiec (chmielot) - Jānis Lukss - - Julien BERNARD - - Michael Zangerle - rkerner - Alex Silcock - Qingshan Luo - Ergie Gonzaga - Matthew J Mucklo - AnrDaemon - - Matthew Covey - - Anthony Massard (decap94) + - Charly Terrier (charlypoppins) - Emre Akinci (emre) - - Chris Maiden (matason) - - fdgdfg (psampaz) - - Andrea Ruggiero (pupax) - - Stéphane Seng + - psampaz (psampaz) - Maxwell Vandervelde - kaywalker - - Mike Meier - - Tim Jabs - Sebastian Ionescu - Robert Kopera - Pablo Ogando Ferreira @@ -2103,158 +2522,123 @@ The Symfony Connect username in parenthesis allows to get more information - Simon Neidhold - Valentin VALCIU - Jeremiah VALERIE - - Julien Menth - - George Yiannoulopoulos + - Patrik Patie Gmitter - Yannick Snobbert - Kevin Dew - James Cowgill + - sensio + - Julien Menth (cfjulien) + - Lyubomir Grozdanov (lubo13) - Nicolas Schwartz (nicoschwartz) - - Patrik Gmitter (patie) - - Peter Schultz + - Tim Jabs (rubinum) + - Stéphane Seng (stephaneseng) - Jonathan Gough - - Benhssaein Youssef - - bill moll + - Benoit Leveque - Benjamin Bender - - PaoRuby - Jared Farrish + - Yohann Tilotti - karl.rixon - raplider - Konrad Mohrfeldt - Lance Chen - Ciaran McNulty (ciaranmcnulty) - Andrew (drew) - - kor3k kor3k (kor3k) + - j4nr6n (j4nr6n) - Stelian Mocanita (stelian) - - Justin (wackymole) - - Flavian (2much) - Gautier Deuette - - dsech - - mike - - Gilbertsoft - - tadas - - Bastien Picharles - Kirk Madera - - mamazu - Keith Maika - Mephistofeles - Hoffmann András + - Cédric Anne - LubenZA - - Olivier - - Juan Mrad - - Denis Yuzhanin - - Youssef BENHSSAIEN - - knezmilos13 - - alireza - - Cyril PASCAL + - Flavian Sierk + - Rik van der Heijden - Michael Bessolov - - pscheit - - Wybren Koelmans - Zdeněk Drahoš - Dan Harper - moldcraft - - Marcin Kruk - Antoine Bellion (abellion) - Ramon Kleiss (akathos) - Antonio Peric-Mazar (antonioperic) - César Suárez (csuarez) - Bjorn Twachtmann (dotbjorn) - - Wahyu Kristianto (kristories) - Tobias Genberg (lorceroth) + - Michael Simonson (mikes) - Nicolas Badey (nico-b) + - Olivier Scherler (oscherler) - Shane Preece (shane) - - Stephan Wentz (temp) - Johannes Goslar - Geoff - georaldc - - Maarten de Boer - - Malte Wunsch - wusuopu - - Markus Staab + - Wouter de Wild + - Peter Potrowl - povilas - Gavin Staniforth - - bahram - Alessandro Tagliapietra (alex88) - - Biji (biji) + - Nikita Starshinov (biji) - Alex Teterin (errogaht) - Gunnar Lium (gunnarlium) - - Marie Minasyan (marie.minassyan) + - Malte Wunsch (maltewunsch) + - Simo Heinonen (simoheinonen) - Tiago Garcia (tiagojsag) - Artiom - Jakub Simon + - Brandon Antonio Lorenzo - Bouke Haarsma - mlievertz - - Radosław Kowalewski - - Stefan Kleff - Enrico Schultz - - JustDylan23 - - mschop + - tpetry - Martin Eckhardt - natechicago - - Victor - - Andreas Allacher - - Alexis + - Leonid Terentyev - Sergei Gorjunov - Jonathan Poston - Adrian Olek (adrianolek) - - cybernet (cybernet2u) - Jody Mickey (jwmickey) - Przemysław Piechota (kibao) - - Leonid Terentyev (li0n) + - Martin Schophaus (m_schophaus_adcada) - Martynas Sudintas (martiis) - - Thijs-jan Veldhuizen (tjveldhuizen) + - Anton Sukhachev (mrsuh) + - Marcel Siegert - ryunosuke - - Bruno BOUTAREL - - victoria - - John Stevenson + - Roy de Vos Burchart - Francisco Facioni (fran6co) - - Stanislav Gamayunov (happyproff) - Iwan van Staveren (istaveren) - - Alexander McCullagh (mccullagh) - - Paul L McNeely (mcneely) - - Andrei C. (moldman) - Povilas S. (povilas) - Laurent Negre (raulnet) - - Sergey Fokin (tyraelqp) + - Victoria Quirante Ruiz (victoria) - Evrard Boulou - pborreli - - Bernat Llibre - Boris Betzholz - Eric Caron + - Arnau González + - GurvanVgx - 2manypeople - Wing - Thomas Bibb - - Joni Halme + - Stefan Koopmanschap - Matt Farmer - catch - - aetxebeste - - Vitali Tsyrkin - - Juga Paazmaya - Alexandre Segura - - afaricamp + - Asier Etxebeste - Josef Cech - - Glodzienski - - riadh26 - - Konstantinos Alexiou - Andrii Boiko - Harold Iedema - - WaiSkats - - Morimoto Ryosuke - Ikhsan Agustian - - Arnau González (arnaugm) + - Benoit Lévêque (benoit_leveque) - Simon Bouland (bouland) + - Jakub Janata (janatjak) - Jibé Barth (jibbarth) - - Jm Aribau (jmaribau) - Matthew Foster (mfoster) - - Reyo Stallenberg (reyostallenberg) - Paul Seiffert (seiffert) - Vasily Khayrulin (sirian) - - Stefan Koopmanschap (skoop) - Stas Soroka (stasyan) - Stefan Hüsges (tronsha) - Jake Bishop (yakobeyak) - Dan Blows - Matt Wells - - Sander van der Vlugt - Nicolas Appriou - stloyd - Andreas @@ -2262,280 +2646,231 @@ The Symfony Connect username in parenthesis allows to get more information - Andrew Coulton - Ulugbek Miniyarov - Jeremy Benoist + - sdrewergutland - Michal Gebauer - Phil Davis - Gleb Sidora - David Stone - - Gerhard Seidel (gseidel) - Jovan Perovic (jperovic) - Pablo Maria Martelletti (pmartelletti) + - Sander van der Vlugt (stranding) - Yassine Guedidi (yguedidi) + - Florian Bogey - Waqas Ahmed - Bert Hekman - Luis Muñoz - Matthew Donadio + - Kris Buist - Houziaux mike - Phobetor - - Eric Schildkamp - - Andreas - Markus - - agaktr - - Mostafa - - kernig + - Janusz Mocek - Thomas Chmielowiec - shdev - Andrey Ryaguzov - - Gennadi Janzen - - SenTisso - Stefan - Peter Bex - Manatsawin Hanmongkolchai - Gunther Konig - - Joe Springe - Mickael GOETZ + - Tobias Speicher + - Jesper Noordsij + - DerStoffel - Maciej Schmidt - - botbotbot - - Dennis Væversted - - Timon van der Vorm + - tatankat - nuncanada + - Thierry Marianne - František Bereň - - Kamil Madejski - - G.R.Dalenoort - Jeremiah VALERIE - Mike Francis - - Vladimir Khramtsov (chrome) + - Nil Borodulia + - Almog Baku (almogbaku) + - Arrakis (arrakis) + - Benjamin Schultz (bschultz) - Gerd Christian Kunze (derdu) - - Christoph Nissle (derstoffel) - - Denys Voronin (hurricane) - Ionel Scutelnicu (ionelscutelnicu) - - Juan Gonzalez Montes (juanwilde) - - Mathieu Dewet (mdewet) + - Kamil Madejski (kmadejski) - Nicolas Tallefourtané (nicolab) - Botond Dani (picur) - - Rémi Faivre (rfv) - - Thierry Marianne (thierrymarianne) + - Radek Wionczek (rwionczek) - Nick Stemerdink - David Stone - - jjanvier - - Julius Beckmann - - Ruben Jansen - - Marc Biorklund - - shreypuranik - - loru88 - - Thibaut Salanon + - Vincent Bouzeran + - Grayson Koonce + - Wissame MEKHILEF - Romain Dorgueil - Christopher Parotat - Dennis Haarbrink - - me_shaon - 蝦米 - - Grayson Koonce (breerly) + - Julius Beckmann (h4cc) - Andrey Helldar (helldar) + - Julien JANVIER (jjanvier) - Karim Cassam Chenaï (ka) - - Maksym Slesarenko (maksym_slesarenko) - - Marcello Mönkemeyer (marcello-moenkemeyer) + - Lorenzo Adinolfi (loru88) + - Ahmed Shamim Hassan (me_shaon) - Michal Kurzeja (mkurzeja) - Nicolas Bastien (nicolas_bastien) - - Sander De la Marche (sanderdlm) - Nikola Svitlica (thecelavi) - - Denis (yethee) - Andrew Zhilin (zhil) - Sjors Ottjes - azjezz - Andy Stanberry - Felix Marezki - Normunds - - Luiz “Felds” Liscia - - Yuri Karaban - - Johan + - Walter Doekes - Thomas Rothe - - Edwin - - Martin + - Troy Crawford - nietonfir - - Andriy - alefranz - David Barratt - Andrea Giannantonio - Pavel.Batanov - avi123 - Pavel Prischepa - - qzylalala + - Philip Dahlstrøm + - Pierre Schmitz - alsar - downace - Aarón Nieves Fernández - - Mike Meier - - Mikolaj Czajkowski + - Ph3nol - Kirill Saksin - - Shiro - - Reda DAOUDI - Koalabaerchen - michalmarcinkowski - Warwick - - Jesper Skytte - Chris - Farid Jalilov - - Christiaan Wiesenekker - Florent Olivaud - - Sergey Panteleev - JakeFr - - Dmitry Hordinky - - Oliver Klee - Simon Sargeant - efeen - - Mikko Ala-Fossi - - Jan Christoph Beyer - Nicolas Pion - Muhammed Akbulut - - Daniel Tiringer - - Koray Zorluoglu - - Roy-Orbison + - Xesau - Aaron Somi - - kshida - Michał Dąbrowski (defrag) - - Aryel Tupinamba (dfkimera) - - Hans Höchtl (hhoechtl) - Simone Fumagalli (hpatoio) - Brian Graham (incognito) - Kevin Vergauwen (innocenzo) - Alessio Baglio (ioalessio) - - Jawira Portugal (jawira) - Johannes Müller (johmue) - Jordi Llonch (jordillonch) + - julien_tempo1 (julien_tempo1) - Nicholas Ruunu (nicholasruunu) - - Jeroen van den Nieuwenhuisen (nieuwenhuisen) - - Cyril Pascal (paxal) - - Cédric Dugat (ph3nol) - - Philip Dahlstrøm (phidah) - - Pierre Rebeilleau (pierrereb) - Milos Colakovic (project2481) - - Raphael de Almeida (raphaeldealmeida) - Rénald Casagraude (rcasagraude) - Robin Duval (robin-duval) - - Grinbergs Reinis (shima5) + - Mohammad Ali Sarbanha (sarbanha) + - Steeve Titeca (stiteca) - Artem Lopata (bumz) - alex - - Nicole Cordes - - Nicolas PHILIPPE + - evgkord - Roman Orlov - - Simon Ackermann + - Andreas Allacher - VolCh - Alexey Popkov - Gijs Kunze - Artyom Protaskin - Nathanael d. Noblet + - Yurun - helmer - ged15 + - Simon Asika - Daan van Renterghem - - Nicole Cordes - - Bálint Szekeres + - Boudry Julien - amcastror - - Alexander Li (aweelex) - Bram Van der Sype (brammm) - Guile (guile) - - Mark Beech (jaybizzle) - Julien Moulin (lizjulien) - Raito Akehanareru (raito) - Mauro Foti (skler) - - Thibaut Arnoud (thibautarnoud) + - skmedix (skmedix) - Yannick Warnier (ywarnier) + - Jörn Lang - Kevin Decherf + - Paul LE CORRE - Jason Woods - - Christian Weiske - - Maria Grazia Patteri - klemens - dened + - jpauli - Dmitry Korotovsky - - mcorteel - Michael van Tricht - ReScO - - JohJohan - Tim Strehle - Sam Ward + - Hans N. Hjort - Walther Lalk + - victor-prdh - Adam - Ivo - - Ismo Vuorinen - Sören Bernstein + - michael.kubovic - devel - taiiiraaa - - Ali Tavafi - - Trevor Suarez - gedrox - - Viet Pham - Alan Bondarchuk - dropfen - Andrey Chernykh - Edvinas Klovas - Drew Butler - Peter Breuls + - Kevin EMO - Chansig - Tischoi - - divinity76 - Andreas Hasenack - J Bruni - Alexey Prilipko - - Dmitriy Fedorenko - vlakoff - - bertillon - thib92 - - Yiorgos Kalligeros - Rudolf Ratusiński - Bertalan Attila - - Arek Bochinski - - Rafael Tovar - - Amin Hosseini (aminh) - AmsTaFF (amstaff) - Simon Müller (boscho) - Yannick Bensacq (cibou) - - Damien (damien_vauchel) + - Damien Vauchel (damien_vauchel) + - Dmitrii Fedorenko (dmifedorenko) - Frédéric G. Marand (fgm) - Freek Van der Herten (freekmurze) - Luca Genuzio (genuzio) - - Hans Nilsson (hansnilsson) - Andrew Marcinkevičius (ifdattic) - Ioana Hazsda (ioana-hazsda) - Jan Marek (janmarek) - Mark de Haan (markdehaan) + - Maxime Corteel (mcorteel) - Dan Patrick (mdpatrick) - - naitsirch (naitsirch) - - Geoffrey Monte (numerogeek) - - Martijn Boers (plebian) - - Plamen Mishev (pmishev) + - Mathieu MARCHOIS (mmar) - Pedro Magalhães (pmmaga) - Rares Vlaseanu (raresvla) - - Sergii Dolgushev (serhey) - - Rein Baarsma (solidwebcode) + - Trevor N. Suarez (rican7) + - Clément Bertillon (skigun) - tante kinast (tante) - - Stephen Lewis (tehanomalousone) - - Ahmed Hannachi (tiecoders) + - Adam RANDI (tiecoders) - Vincent LEFORT (vlefort) - Walid BOUGHDIRI (walidboughdiri) - - wicliff wolda (wickedone) - - Wim Molenberghs (wimm) - Darryl Hein (xmmedia) - - Sadicov Vladimir (xtech) - - Kevin EMO (zarcox) - - Marcel Berteler - - sdkawata + - Vladimir Sadicov (xtech) + - Peter van Dommelen + - Tim van Densen - Andrzej - Alexander Zogheb - Rémi Blaise - Nicolas Séverin + - Houssem - Joel Marcey + - zolikonta - David Christmann - root - pf + - Zoli Konta - Vincent Chalnot - - James Hudson + - Roeland Jago Douma + - Patrizio Bekerle - Tom Maguire - Mateusz Lerczak - Richard Quadling - - Rainrider - David Zuelke - Adrian - - Oleg Andreyev - - Oliver Eglseder - neFAST - - zcodes + - Peter Gribanov - Pierre Rineau - Florian Morello - Maxim Lovchikov @@ -2544,85 +2879,64 @@ The Symfony Connect username in parenthesis allows to get more information - Ari Pringle (apringle) - Dan Ordille (dordille) - Jan Eichhorn (exeu) + - Georg Ringer (georgringer) - Grégory Pelletier (ip512) - - Johan Wilfer (johanwilfer) - John Nickell (jrnickell) - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) + - Omar Yepez (oyepez003) - Jonny Schmid (schmidjon) - - Toby Griffiths (tog) - Götz Gottwald - - Alessandra Lai - - Veres Lajos - - Ernest Hymel - - Andrea Civita - - LoginovIlya + - Adrien Peyre + - Christoph Krapp - Nick Chiu - - grifx - Robert Campbell - Matt Lehner - - Olexandr Kalaidzhy - Helmut Januschka - Hein Zaw Htet™ - Ruben Kruiswijk - Cosmin-Romeo TANASE - Michael J - - youssef saoubou - Joseph Maarek - Alexander Menk - Alex Pods - - hadriengem - timaschew + - Jelle Kapitein - Jochen Mandl - - elattariyassine - Marin Nicolae + - Gerrit Addiks + - Albert Prat - Alessandro Loffredo - Ian Phillips - - Carlos Tasada + - Remi Collet - Haritz - Matthieu Prat - - Grummfy - - zors1 - - Peter Simoncic + - Brieuc Thomas + - mantulo - Paul Le Corre - - Noel Light-Hilary - Filipe Guerra - Jean Ragouin - Gerben Wijnja - - Emre YILMAZ - Rowan Manning - - Marcos Labad + - qsz - Per Modin - David Windell - - Frank Jogeleit - - Ondřej Frei - Gabriel Birke - - skafandri - Derek Bonner - martijn - - Storkeus + - annesosensio + - NothingWeAre + - goabonga - Alan Chen - - Anton Zagorskii - - ging-dev - - zakaria-amm - - insidestyles - Maerlyn - Even André Fiskvik - - Agata - - dakur - - florian-michael-mast - - Александр Ли - - Arjan Keeman - - Vlad Dumitrache - Erik van Wingerden - Valouleloup - - robmro27 - - Vallel Blanco - Alexis MARQUIS + - Matheus Gontijo - Gerrit Drost - Linnaea Von Lavia - - Bastien Clément - - Julius Šakalys + - Simon Mönch - Javan Eskander - Lenar Lõhmus - Cristian Gonzalez @@ -2631,247 +2945,206 @@ The Symfony Connect username in parenthesis allows to get more information - hainey - Juan M Martínez - Gilles Gauthier - - Pavinthan - - Sylvain METAYER - ddebree - Gyula Szucs - Tomas Liubinas - - Ivo Valchev - - Alex - Jan Hort - Klaas Naaijkens - - Daniel González Cerviño - Rafał - - Ahmad El-Bardan (absahmad) - Adria Lopez (adlpz) - Aaron Scherer (aequasi) + - Alexandre Jardin (alexandre.jardin) + - Bart Brouwer (bartbrouwer) - Rosio (ben-rosio) - Simon Paarlberg (blamh) - - Brieuc THOMAS (brieucthomas) - Masao Maeda (brtriver) - - Damien Harper (damien.harper) - Darius Leskauskas (darles) - david perez (davidpv) - David Joos (djoos) - Denis Klementjev (dklementjev) - - Dominik Pesch (dombn) - Dominik Hajduk (dominikalp) - Tomáš Polívka (draczris) - Dennis Smink (dsmink) - Franz Liedke (franzliedke) + - Alex (garrett) - Gaylord Poillon (gaylord_p) - - Christophe BECKER (goabonga) - gondo (gondo) + - Joris Garonian (grifx) + - Grummfy (grummfy) + - Hadrien Cren (hcren) - Gusakov Nikita (hell0w0rd) - - Osman Üngür (import) - - Jaap van Otterdijk (jaapio) + - Oz (import) - Javier Núñez Berrocoso (javiernuber) - Jelle Bekker (jbekker) - - Jonathan Sui Lioung Lee Slew (jlslew) - - Johan Vlaar (johjohan) - Giovanni Albero (johntree) - Jorge Martin (jorgemartind) - Joeri Verdeyen (jverdeyen) - Kevin Verschaeve (keversc) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - - Martin Mandl (m2mtech) - Mehdi Mabrouk (mehdidev) - Bart Reunes (metalarend) - Muriel (metalmumu) - Michael Pohlers (mick_the_big) - - Misha Klomp (mishaklomp) - mlpo (mlpo) - - Ulrik Nielsen (mrbase) - Marek Šimeček (mssimi) - Dmitriy Tkachenko (neka) - Cayetano Soriano Gallego (neoshadybeat) - - Artem (nexim) - - Nicolas ASSING (nicolasassing) - Olivier Laviale (olvlvl) - - Pierre Gasté (pierre_g) - Pablo Monterde Perez (plebs) - - Pierre-Olivier Vares (povares) - Jimmy Leger (redpanda) + - Mokhtar Tlili (sf-djuba) + - Gregor Nathanael Meyer (spackmat) - Marcin Szepczynski (szepczynski) + - Simone Di Maulo (toretto460) - Cyrille Jouineau (tuxosaurus) + - Lajos Veres (vlajos) - Vladimir Chernyshev (volch) - - Wim Godden (wimg) - Yorkie Chadwick (yorkie76) - - Maxime Aknin (3m1x4m) - - Geordie - - Exploit.cz + - Pavel Barton - GuillaumeVerdon - - Angel Fernando Quiroz Campos - - Ondrej Mirtes + - ureimers - akimsko - Youpie - - Jason Stephens - srsbiz - - Tinjo Schöni - Taylan Kasap - Michael Orlitzky - Nicolas A. Bérard-Nault - - Quentin Favrie - - Matthias Derer - - vladyslavstartsev + - Francois Martin - Saem Ghani - Stefan Oderbolz - - Curtis + - Tamás Szigeti - Gabriel Moreira - Alexey Popkov - ChS + - Jannik Zschiesche - Alexis MARQUIS - Joseph Deray - Damian Sromek - Ben - Evgeniy Tetenchuk - - Sjoerd Adema - Shrey Puranik - Lars Moelleken - dasmfm - - Claas Augner - Mathias Geat + - Angel Fernando Quiroz Campos (angelfqc) - Arnaud Buathier (arnapou) + - Curtis (ccorliss) - chesteroni (chesteroni) - Mauricio Lopez (diaspar) - HADJEDJ Vincent (hadjedjvincent) - Daniele Cesarini (ijanki) - Ismail Asci (ismailasci) - - Jeffrey Moelands (jeffreymoelands) - - Simon CONSTANS (kosssi) + - Ondřej Mirtes (mirtes) - Paulius Jarmalavičius (pjarmalavicius) - - Ramon Henrique Ornelas (ramonornela) - - Ricardo de Vries (ricknox) - - Ruslan Zavacky (ruslanzavacky) - - Stefano Cappellini (stefano_cappellini) + - Ramon Ornelas (ramonornela) + - Ricardo de Vries (ricardodevries) - Thomas Dutrion (theocrite) - Till Klampaeckel (till) - Tobias Weinert (tweini) - - Ulf Reimers (ureimers) - Wotre - goohib - Tom Counsell - - George Bateman + - Sepehr Lajevardi - Xavier HAUSHERR - - Ron Gähler - Edwin Hageman - Mantas Urnieža - temperatur - - misterx + - Paul Andrieux + - Sezil - Cas - - arend - - Vincent Godé - - Dusan Kasan - - helmi - - Michael Steininger - - Nardberjean + - ghazy ben ahmed - Karolis - Myke79 - - jersoe - Brian Debuire - - Eric Grimois - Piers Warmers - Sylvain Lorinet - klyk50 - - Andreas Lutro - jc - BenjaminBeck - Aurelijus Rožėnas - - Beno!t POLASZEK - - Armando - Jordan Hoff - znerol - Christian Eikermann + - Sergei Shitikov + - Steffen Keuper - Antonio Angelino - - Jens Schulze + - Pavel Golovin - Matt Fields - - Olatunbosun Egberinde - Andras Debreczeni - Vladimir Sazhin - - Michel Bardelmeijer - Tomas Kmieliauskas - - Ikko Ashimine - - Brad Jones - Billie Thompson - lol768 - jamogon + - Antoine LA - Vyacheslav Slinko + - Benjamin Laugueux - Jakub Chábek + - William Pinaud (DocFX) - Johannes - Jörg Rühl - - George Dietrich - wesleyh - - sergey - - Menno Holtkamp - - Ser5 - Michael Hudson-Doyle - Daniel Bannert - Karim Miladi - Michael Genereux - patrick-mcdougle + - Tyler Stroud - Dariusz Czech - - Bruno Baguette - Jack Wright - MrNicodemuz - Anonymous User + - demeritcowboy - Paweł Tomulik - Eric J. Duran + - Blackfelix - Alexandru Bucur - - Alexis Lefebvre - cmfcmf - - Michal Forbak - Drew Butler - - Alexey Berezuev - - Pierrick Charron + - pawel-lewtak - Steve Müller + - omerida - Andras Ratz - andreabreu98 - - gechetspr - - brian978 - Michael Schneider - - Cédric Bertolini - n-aleha - - Talha Zekeriya Durmuş - Anatol Belski - - Şəhriyar İmanov - Alexis BOYER - - bch36 - Kaipi Yann - adam-mospan - - Steve Hyde + - nerdgod - Sam Williams - - Ettore Del Negro - Guillaume Aveline - Adrian Philipp - James Michael DuPont + - Markus Tacker - Kasperki - - dima-gr - Tammy D - - Rodolfo Ruiz - - Enrico + - Adrien Foulon - Ryan Rud - - Christopher Georg - Ondrej Slinták - vlechemin - Brian Corrigan - Ladislav Tánczos + - Brian Freytag - Skorney - Lucas Matte - fmarchalemisys + - MGatner - mieszko4 - Steve Preston + - ibasaw - Wojciech Skorodecki - Kevin Frantz - Neophy7e - bokonet - Arrilot - - ampaze + - andrey-tech + - Shaun Simmons - Markus Staab - Pierre-Louis LAUNAY - djama - - Benjamin Rosenberger - - Vladyslav Startsev - Michael Gwynne - Eduardo Conceição - changmin.keum @@ -2879,20 +3152,14 @@ The Symfony Connect username in parenthesis allows to get more information - Sébastien HOUZE - Abdulkadir N. A. - Adam Klvač - - Bruno Nogueira Nascimento Wowk - - Tomanhez - - satalaondrej - - jonmldr - Yevgen Kovalienia - Lebnik - - nsbx - Shude - - Richard Hodgson - - Sven Fabricius - Ondřej Führer - Sema + - Ayke Halder - Thorsten Hallwas - - Marco Pfeiffer + - Brian Freytag - Alex Nostadt - Michael Squires - Egor Gorbachev @@ -2901,115 +3168,91 @@ The Symfony Connect username in parenthesis allows to get more information - zorn - Yuriy Potemkin - Emilie Lorenzo + - prudhomme victor - enomotodev - - Babichev Maxim - - Edvin Hultberg + - Vincent - Benjamin Long - - Kévin Gonella - Ben Miller - Peter Gribanov - - Ash014 + - Bart Ruysseveldt - kwiateusz - - jspee - Ilya Bulakh - David Soria Parra - Sergiy Sokolenko - - detinkin - Ahmed Abdulrahman - dinitrol - Penny Leach - Yurii K - Richard Trebichavský - g123456789l + - Mark Ogilvie - Jonathan Vollebregt + - Vladimir Vasilev - oscartv - DanSync - Peter Zwosta + - Michal Čihař - parhs - - Harry Wiseman - Diego Campoy - - TeLiXj - Oncle Tom - Sam Anthony - Christian Stocker - Oussama Elgoumri - - Steve Marvell + - Gert de Pagter + - David Lima - Dawid Nowak - Lesnykh Ilia - - Shyim - - sabruss - darnel - - Karolis Daužickas - Nicolas - Sergio Santoro - tirnanog06 - - Andrejs Leonovs + - Alfonso Fernández García - phc - Дмитрий Пацура - - Signor Pedro - - Matthias Larisch - - Maxime P - - ilyes kooli - - Ilia Lazarev - Michaël VEROUX - Julia - Lin Lu - arduanov - sualko - - Molkobain - - Yendric + - Fabien + - Martin Komischke - ADmad - Nicolas Roudaire - - Matthias Meyer - - Temuri Takalandze (abgeo) - - Bernard van der Esch (adeptofvoltron) - - Alfonso (afgar) + - Abdouni Karim (abdounikarim) - Andreas Forsblom (aforsblo) - Alex Olmos (alexolmos) + - Cedric BERTOLINI (alsciende) - Antonio Mansilla (amansilla) - Robin Kanters (anddarerobin) - Juan Ases García (ases) - Siragusa (asiragusa) - Daniel Basten (axhm3a) - - Dude (b1rdex) - - Benedict Massolle (bemas) - - Gerard Berengue Llobera (bere) - Bernd Matzner (bmatzner) - - Anton (bonio) - Bram Tweedegolf (bram_tweedegolf) - Brandon Kelly (brandonkelly) - Choong Wei Tjeng (choonge) - Kousuke Ebihara (co3k) - Loïc Vernet (coil) - - Christian Gripp (core23) - - Christoph Schaefer (cvschaefer) + - Christoph Vincent Schaefer (cvschaefer) - Damon Jones (damon__jones) - - Alexandre Fiocre (demos77) + - David Courtey (david-crty) - Łukasz Giza (destroyer) - Daniel Londero (dlondero) + - Dušan Kasan (dudo1904) - Sebastian Landwehr (dword123) - Adel ELHAIBA (eadel) - Damián Nohales (eagleoneraptor) - - Jordane VASPARD (elementaire) - Elliot Anderson (elliot) - Fabien D. (fabd) - - Faizan Akram Dar (faizanakram) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) - Yohan Giarelli (frequence-web) - - Gasan Gouseynov (gassan) - Gerry Vandermaesen (gerryvdm) - - Ghazy Ben Ahmed (ghazy) - - Arash Tabriziyan (ghost098) - - Greg Szczotka (greg606) - - ibasaw (ibasaw) - - Nathan DIdier (icz) + - Arash Tabrizian (ghost098) - Vladislav Krupenkin (ideea) - - Ilija Tovilo (ilijatovilo) - Peter Orosz (ill_logical) - Imangazaliev Muhammad (imangazaliev) - j0k (j0k) - - Jeremie Broutier (jbroutier) - joris de wit (jdewit) - Jérémy CROMBEZ (jeremy) - Jose Manuel Gonzalez (jgonzalez) @@ -3020,6 +3263,7 @@ The Symfony Connect username in parenthesis allows to get more information - JuntaTom (juntatom) - Julien Manganne (juuuuuu) - Ismail Faizi (kanafghan) + - Karolis Daužickas (kdauzickas) - Sébastien Armand (khepin) - Pierre-Chanel Gauthier (kmecnin) - Krzysztof Menżyk (krymen) @@ -3027,99 +3271,79 @@ The Symfony Connect username in parenthesis allows to get more information - Laurent Bachelier (laurentb) - Luís Cobucci (lcobucci) - Mehdi Achour (machour) - - Mamikon Arakelyan (mamikon) - - Matthieu Moquet (mattketmo) + - Matt Ketmo (mattketmo) - Moritz Borgmann (mborgmann) - - Mathias Brodala (mbrodala) - - Michal Čihař (mcihar) - Matt Drollette (mdrollette) - Adam Monsen (meonkeys) - - Mike Milano (mmilano) - - Youssef Benhssaien (moghreb) - - diego aguiar (mollokhan) + - Steffen Persch (n3o77) - Ala Eddine Khefifi (nayzo) - emilienbouard (neime) - Nicholas Byfleet (nickbyfleet) + - Nicolas Bondoux (nsbx) + - Cedric Kastner (nurtext) - ollie harridge (ollietb) - - Paul Andrieux (paulandrieux) - - Paweł Szczepanek (pauluz) + - Pawel Szczepanek (pauluz) - Philippe Degeeter (pdegeeter) - - PLAZANET Pierre (pedrotroller) - Christian López Espínola (penyaskito) - Petr Jaroš (petajaros) - Philipp Hoffmann (philipphoffmann) - Alex Carol (picard89) - Daniel Perez Pinazo (pitiflautico) - - Igor Tarasov (polosatus) - - Maxim Pustynnikov (pustynnikov) - - Ralf Kuehnel (ralfkuehnel) - - Ramazan APAYDIN (rapaydin) - - Brayden Williams (redstar504) + - Maksym Pustynnikov (pustynnikov) + - Ralf Kühnel (ralfkuehnel) - Rich Sage (richsage) - - Bart Ruysseveldt (ruyss) - scourgen hung (scourgen) - Sebastian Busch (sebu) - - Sepehr Lajevardi (sepehr) + - Sergey Stavichenko (sergey_stavichenko) - André Filipe Gonçalves Neves (seven) - Bruno Ziegler (sfcoder) - Andrea Giuliano (shark) + - Şəhriyar İmanov (shehriyari) - Thomas Baumgartner (shoplifter) - Schuyler Jager (sjager) - Volker (skydiablo) - - Francisco Alvarez (sormes) - Julien Sanchez (sumbobyboys) - - Stephan Vierkant (svierkant) + - Sylvain BEISSIER (sylvain-beissier) + - Ron Gähler (t-ronx) - Guillermo Gisinger (t3chn0r) - - Markus Tacker (tacker) - Tom Newby (tomnewbyau) - Andrew Clark (tqt_andrew_clark) - David Lumaye (tux1124) - - Roman Tymoshyk (tymoshyk) - - Tyler Stroud (tystr) - Moritz Kraft (userfriendly) - Víctor Mateo (victormateo) - - Vincent (vincent1870) - - David Herrmann (vworldat) + - David Grüner (vworldat) - Eugene Babushkin (warl) - Wouter Sioen (wouter_sioen) - Xavier Amado (xamado) - Jesper Søndergaard Pedersen (zerrvox) - Florent Cailhol - szymek - - Ryan Linnit + - Konrad - Kovacs Nicolas - craigmarvelley - Stano Turza - - simpson - drublic - - MaPePeR - Andreas Streichardt - Alexandre Segura - - Vivien - Pascal Hofmann - - david-binda - smokeybear87 - Gustavo Adrian - damaya - Kevin Weber - - Ben Scott - - Alexandru Năstase - Dionysis Arvanitis - Sergey Fedotov - Konstantin Scheumann - Michael - fh-github@fholzhauer.de + - rogamoore - AbdElKader Bouadjadja - - ddegentesh - DSeemiller - Jan Emrich - - Anne-Julia Seitz - Mark Topper + - Romain - Xavier REN - - Zander Baldwin - - Philipp Scheit + - Kevin Meijer - max - - Alexander Bauer (abauer) - Ahmad Mayahi (ahmadmayahi) - Mohamed Karnichi (amiral) - Andrew Carter (andrewcarteruk) @@ -3133,9 +3357,12 @@ The Symfony Connect username in parenthesis allows to get more information - Maxime COLIN (maximecolin) - Muharrem Demirci (mdemirci) - Evgeny Z (meze) + - Pierre-Henry Soria 🌴 (pierrehenry) - Pierre Geyer (ptheg) - Thomas BERTRAND (sevrahk) + - Vladislav (simpson) - Matej Žilák (teo_sk) - Vladislav Vlastovskiy (vlastv) - RENAUDIN Xavier (xorrox) - Yannick Vanhaeren (yvh) + - Zan Baldwin (zanderbaldwin) diff --git a/LICENSE b/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index e70e3e5d2a917..718b729e55a2c 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -146,6 +146,11 @@ Inflector * The component has been removed, use `EnglishInflector` from the String component instead. +Ldap +---- + + * Remove `LdapAuthenticator::createAuthenticatedToken()`, use `LdapAuthenticator::createToken()` instead + Lock ---- diff --git a/UPGRADE-6.1.md b/UPGRADE-6.1.md index 7d24e202f8410..333731b4e1f83 100644 --- a/UPGRADE-6.1.md +++ b/UPGRADE-6.1.md @@ -4,6 +4,7 @@ UPGRADE FROM 6.0 to 6.1 All components -------------- + * Deprecate requiring the "symfony/symfony" package; replace it with standalone components instead * Public and protected properties are now considered final; instead of overriding a property, consider setting its value in the constructor @@ -11,16 +12,43 @@ Console ------- * Deprecate `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead + * Add argument `$suggestedValues` to `Command::addArgument` and `Command::addOption` + * Add argument `$suggestedValues` to `InputArgument` and `InputOption` constructors + +DependencyInjection +------------------- + + * Deprecate `ReferenceSetArgumentTrait` + +FrameworkBundle +--------------- + + * Deprecate the `reset_on_message` config option. It can be set to `true` only and does nothing now. + To prevent services resetting after each message the "--no-reset" option in "messenger:consume" command can be set + * Deprecate not setting the `http_method_override` config option. The default value will change to `false` in 7.0. + +HttpKernel +---------- + + * Deprecate StreamedResponseListener, it's not needed anymore + +Routing +------- + + * Add argument `$routeParameters` to `UrlMatcher::handleRouteRequirements()` Serializer ---------- * Deprecate `ContextAwareNormalizerInterface`, use `NormalizerInterface` instead * Deprecate `ContextAwareDenormalizerInterface`, use `DenormalizerInterface` instead - * Deprecate `ContextAwareEncoderInterface`, use `EncoderInterface` instead - * Deprecate `ContextAwareDecoderInterface`, use `DecoderInterface` instead + * Deprecate supporting denormalization for `AbstractUid` in `UidNormalizer`, use one of `AbstractUid` child class instead + * Deprecate denormalizing to an abstract class in `UidNormalizer` Validator --------- * Deprecate `Constraint::$errorNames`, use `Constraint::ERROR_NAMES` instead + * Deprecate constraint `ExpressionLanguageSyntax`, use `ExpressionSyntax` instead + * Implementing the `ConstraintViolationInterface` or `ConstraintViolationListInterface` + without implementing the `__toString()` method is deprecated diff --git a/composer.json b/composer.json index c1987e3d1dd1c..c3e263eb0752b 100644 --- a/composer.json +++ b/composer.json @@ -32,12 +32,12 @@ "symfony/translation-implementation": "2.3|3.0" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "composer-runtime-api": ">=2.1", "ext-xml": "*", "friendsofphp/proxy-manager-lts": "^1.0.2", - "doctrine/event-manager": "~1.0", - "doctrine/persistence": "^2", + "doctrine/event-manager": "^1|^2", + "doctrine/persistence": "^2|^3", "twig/twig": "^2.13|^3.0.4", "psr/cache": "^2.0|^3.0", "psr/container": "^1.1|^2.0", @@ -51,7 +51,6 @@ "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.23", "symfony/polyfill-uuid": "^1.15" }, "replace": { @@ -95,7 +94,6 @@ "symfony/security-bundle": "self.version", "symfony/security-core": "self.version", "symfony/security-csrf": "self.version", - "symfony/security-guard": "self.version", "symfony/security-http": "self.version", "symfony/semaphore": "self.version", "symfony/serializer": "self.version", @@ -122,23 +120,22 @@ "async-aws/sqs": "^1.0", "async-aws/sns": "^1.0", "cache/integration-tests": "dev-master", - "doctrine/annotations": "^1.13.1", - "doctrine/collections": "~1.0", + "doctrine/annotations": "^1.13.1|^2", + "doctrine/collections": "^1.0|^2.0", "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.13.1|^3.0", "doctrine/orm": "^2.7.4", "guzzlehttp/promises": "^1.4", - "masterminds/html5": "^2.6", + "masterminds/html5": "^2.7.2", "monolog/monolog": "^1.25.1|^2", "nyholm/psr7": "^1.0", - "paragonie/sodium_compat": "^1.8", "pda/pheanstalk": "^4.0", "php-http/httplug": "^1.0|^2.0", "phpstan/phpdoc-parser": "^1.0", "predis/predis": "~1.1", "psr/http-client": "^1.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "egulias/email-validator": "^2.1.10|^3.1", + "egulias/email-validator": "^2.1.10|^3.1|^4", "symfony/mercure-bundle": "^0.3", "symfony/phpunit-bridge": "^5.4|^6.0", "symfony/runtime": "self.version", @@ -156,7 +153,7 @@ "egulias/email-validator": "~3.0.0", "masterminds/html5": "<2.6", "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.5.1", + "phpdocumentor/type-resolver": "<1.5.1|>=1.7.0", "ocramius/proxy-manager": "<2.1", "phpunit/phpunit": "<5.4.3" }, @@ -177,6 +174,9 @@ "files": [ "src/Symfony/Component/String/Resources/functions.php" ], + "classmap": [ + "src/Symfony/Component/Cache/Traits/ValueWrapper.php" + ], "exclude-from-classmap": [ "**/Tests/" ] diff --git a/phpunit b/phpunit index 7ca6ceeccbee8..e26fecd73cc9d 100755 --- a/phpunit +++ b/phpunit @@ -13,7 +13,7 @@ if (!getenv('SYMFONY_PHPUNIT_VERSION')) { if (\PHP_VERSION_ID < 70200) { putenv('SYMFONY_PHPUNIT_VERSION=7.5'); } elseif (\PHP_VERSION_ID < 70300) { - putenv('SYMFONY_PHPUNIT_VERSION=8.5'); + putenv('SYMFONY_PHPUNIT_VERSION=8.5.26'); } else { putenv('SYMFONY_PHPUNIT_VERSION=9.5'); } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5ad6175de7a31..5f5207576f4f6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -74,13 +74,14 @@ Cache\IntegrationTests - Symfony\Component\Cache - Symfony\Component\Cache\Tests\Fixtures - Symfony\Component\Cache\Tests\Traits - Symfony\Component\Cache\Traits - Symfony\Component\Console - Symfony\Component\HttpFoundation - Symfony\Component\Uid + Symfony\Bridge\Doctrine\Middleware\Debug + Symfony\Component\Cache + Symfony\Component\Cache\Tests\Fixtures + Symfony\Component\Cache\Tests\Traits + Symfony\Component\Cache\Traits + Symfony\Component\Console + Symfony\Component\HttpFoundation + Symfony\Component\Uid diff --git a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php index 91cc25026a8b6..861510150b93c 100644 --- a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php +++ b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php @@ -50,7 +50,7 @@ public function warmUp(string $cacheDir): array foreach ($this->registry->getManagers() as $em) { // we need the directory no matter the proxy cache generation strategy if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) { - if (false === @mkdir($proxyCacheDir, 0777, true)) { + if (false === @mkdir($proxyCacheDir, 0777, true) && !is_dir($proxyCacheDir)) { throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir)); } } elseif (!is_writable($proxyCacheDir)) { diff --git a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php index d262c5e3591e4..18ea49df2b423 100644 --- a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php +++ b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php @@ -74,15 +74,23 @@ public function dispatchEvent($eventName, EventArgs $eventArgs = null): void */ public function getListeners($event = null): array { + if (null === $event) { + return $this->getAllListeners(); + } if (!$this->initializedSubscribers) { $this->initializeSubscribers(); } - if (null !== $event) { - if (!isset($this->initialized[$event])) { - $this->initializeListeners($event); - } + if (!isset($this->initialized[$event])) { + $this->initializeListeners($event); + } - return $this->listeners[$event]; + return $this->listeners[$event]; + } + + public function getAllListeners(): array + { + if (!$this->initializedSubscribers) { + $this->initializeSubscribers(); } foreach ($this->listeners as $event => $listeners) { diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php index a8e55ee881e01..c5318414dbf68 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php @@ -15,6 +15,7 @@ use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use Doctrine\Persistence\ManagerRegistry; +use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; @@ -28,7 +29,6 @@ */ class DoctrineDataCollector extends DataCollector { - private ManagerRegistry $registry; private array $connections; private array $managers; @@ -37,9 +37,10 @@ class DoctrineDataCollector extends DataCollector */ private array $loggers = []; - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; + public function __construct( + private ManagerRegistry $registry, + private ?DebugDataHolder $debugDataHolder = null, + ) { $this->connections = $registry->getConnectionNames(); $this->managers = $registry->getManagerNames(); } @@ -56,23 +57,43 @@ public function addLogger(string $name, DebugStack $logger) * {@inheritdoc} */ public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $this->data = [ + 'queries' => $this->collectQueries(), + 'connections' => $this->connections, + 'managers' => $this->managers, + ]; + } + + private function collectQueries(): array { $queries = []; + + if (null !== $this->debugDataHolder) { + foreach ($this->debugDataHolder->getData() as $name => $data) { + $queries[$name] = $this->sanitizeQueries($name, $data); + } + + return $queries; + } + foreach ($this->loggers as $name => $logger) { $queries[$name] = $this->sanitizeQueries($name, $logger->queries); } - $this->data = [ - 'queries' => $queries, - 'connections' => $this->connections, - 'managers' => $this->managers, - ]; + return $queries; } public function reset() { $this->data = []; + if (null !== $this->debugDataHolder) { + $this->debugDataHolder->reset(); + + return; + } + foreach ($this->loggers as $logger) { $logger->queries = []; $logger->currentQuery = 0; diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index fc8910eb93f6d..cd5fc91cb32b7 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -266,8 +266,8 @@ protected function detectMetadataDriver(string $dir, ContainerBuilder $container } $container->fileExists($resource, false); - if ($container->fileExists($dir.'/'.$this->getMappingObjectDefaultName(), false)) { - return $this->detectMappingType($dir, $container); + if ($container->fileExists($discoveryPath = $dir.'/'.$this->getMappingObjectDefaultName(), false)) { + return $this->detectMappingType($discoveryPath, $container); } return null; @@ -294,10 +294,16 @@ private function detectMappingType(string $directory, ContainerBuilder $containe foreach ($glob as $file) { $content = file_get_contents($file); - if (preg_match('/^#\[.*'.$quotedMappingObjectName.'\b/m', $content)) { + if ( + preg_match('/^#\[.*'.$quotedMappingObjectName.'\b/m', $content) || + preg_match('/^#\[.*Embeddable\b/m', $content) + ) { break; } - if (preg_match('/^ \* @.*'.$quotedMappingObjectName.'\b/m', $content)) { + if ( + preg_match('/^(?: \*|\/\*\*) @.*'.$quotedMappingObjectName.'\b/m', $content) || + preg_match('/^(?: \*|\/\*\*) @.*Embeddable\b/m', $content) + ) { $type = 'annotation'; break; } @@ -343,7 +349,7 @@ protected function loadCacheDriver(string $cacheName, string $objectManagerName, $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)), $memcachedInstance); $cacheDef->addMethodCall('setMemcached', [new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)))]); break; - case 'redis': + case 'redis': $redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%'; $redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%'; $redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%'; diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index b0121df1b1da5..3364ffa4c4edb 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -51,7 +51,7 @@ public function getEntities(): array */ public function getEntitiesByIds(string $identifier, array $values): array { - if (null !== $this->queryBuilder->getMaxResults() || null !== $this->queryBuilder->getFirstResult()) { + if (null !== $this->queryBuilder->getMaxResults() || 0 < (int) $this->queryBuilder->getFirstResult()) { // an offset or a limit would apply on results including the where clause with submitted id values // that could make invalid choices valid $choices = []; diff --git a/src/Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php b/src/Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php index 3c1141c54860d..d5dc1a23b72a6 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php +++ b/src/Symfony/Bridge/Doctrine/Form/DataTransformer/CollectionToArrayTransformer.php @@ -46,9 +46,7 @@ public function transform(mixed $collection): mixed } /** - * Transforms choice keys into entities. - * - * @param mixed $array An array of entities + * Transforms an array into a collection. */ public function reverseTransform(mixed $array): Collection { diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index 191a853ac5c93..f2e65a7f0a8c0 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -17,6 +17,17 @@ use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\MappingException; use Doctrine\Persistence\Proxy; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\CollectionType; +use Symfony\Component\Form\Extension\Core\Type\DateIntervalType; +use Symfony\Component\Form\Extension\Core\Type\DateTimeType; +use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\Extension\Core\Type\IntegerType; +use Symfony\Component\Form\Extension\Core\Type\NumberType; +use Symfony\Component\Form\Extension\Core\Type\TextareaType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\Extension\Core\Type\TimeType; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; @@ -39,7 +50,7 @@ public function __construct(ManagerRegistry $registry) public function guessType(string $class, string $property): ?TypeGuess { if (!$ret = $this->getMetadata($class)) { - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); + return new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE); } [$metadata, $name] = $ret; @@ -48,47 +59,32 @@ public function guessType(string $class, string $property): ?TypeGuess $multiple = $metadata->isCollectionValuedAssociation($property); $mapping = $metadata->getAssociationMapping($property); - return new TypeGuess('Symfony\Bridge\Doctrine\Form\Type\EntityType', ['em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple], Guess::HIGH_CONFIDENCE); + return new TypeGuess(EntityType::class, ['em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple], Guess::HIGH_CONFIDENCE); } - switch ($metadata->getTypeOfField($property)) { - case Types::ARRAY: - case Types::SIMPLE_ARRAY: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE); - case Types::BOOLEAN: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE); - case Types::DATETIME_MUTABLE: - case Types::DATETIMETZ_MUTABLE: - case 'vardatetime': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE); - case Types::DATETIME_IMMUTABLE: - case Types::DATETIMETZ_IMMUTABLE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case Types::DATEINTERVAL: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE); - case Types::DATE_MUTABLE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE); - case Types::DATE_IMMUTABLE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case Types::TIME_MUTABLE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE); - case Types::TIME_IMMUTABLE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case Types::DECIMAL: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', ['input' => 'string'], Guess::MEDIUM_CONFIDENCE); - case Types::FLOAT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE); - case Types::INTEGER: - case Types::BIGINT: - case Types::SMALLINT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE); - case Types::STRING: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE); - case Types::TEXT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE); - default: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); - } + return match ($metadata->getTypeOfField($property)) { + Types::ARRAY, + Types::SIMPLE_ARRAY => new TypeGuess(CollectionType::class, [], Guess::MEDIUM_CONFIDENCE), + Types::BOOLEAN => new TypeGuess(CheckboxType::class, [], Guess::HIGH_CONFIDENCE), + Types::DATETIME_MUTABLE, + Types::DATETIMETZ_MUTABLE, + 'vardatetime' => new TypeGuess(DateTimeType::class, [], Guess::HIGH_CONFIDENCE), + Types::DATETIME_IMMUTABLE, + Types::DATETIMETZ_IMMUTABLE => new TypeGuess(DateTimeType::class, ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE), + Types::DATEINTERVAL => new TypeGuess(DateIntervalType::class, [], Guess::HIGH_CONFIDENCE), + Types::DATE_MUTABLE => new TypeGuess(DateType::class, [], Guess::HIGH_CONFIDENCE), + Types::DATE_IMMUTABLE => new TypeGuess(DateType::class, ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE), + Types::TIME_MUTABLE => new TypeGuess(TimeType::class, [], Guess::HIGH_CONFIDENCE), + Types::TIME_IMMUTABLE => new TypeGuess(TimeType::class, ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE), + Types::DECIMAL => new TypeGuess(NumberType::class, ['input' => 'string'], Guess::MEDIUM_CONFIDENCE), + Types::FLOAT => new TypeGuess(NumberType::class, [], Guess::MEDIUM_CONFIDENCE), + Types::INTEGER, + Types::BIGINT, + Types::SMALLINT => new TypeGuess(IntegerType::class, [], Guess::MEDIUM_CONFIDENCE), + Types::STRING => new TypeGuess(TextType::class, [], Guess::MEDIUM_CONFIDENCE), + Types::TEXT => new TypeGuess(TextareaType::class, [], Guess::MEDIUM_CONFIDENCE), + default => new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE), + }; } /** @@ -180,9 +176,9 @@ protected function getMetadata(string $class) foreach ($this->registry->getManagers() as $name => $em) { try { return $this->cache[$class] = [$em->getClassMetadata($class), $name]; - } catch (MappingException $e) { + } catch (MappingException) { // not an entity or mapped super class - } catch (LegacyMappingException $e) { + } catch (LegacyMappingException) { // not an entity or mapped super class, using Doctrine ORM 2.2 } } diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index f91d240451470..cd4dc42393059 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -156,7 +156,7 @@ public function configureOptions(OptionsResolver $resolver) $choiceValue = function (Options $options) { // If the entity has a single-column ID, use that ID as value if ($options['id_reader'] instanceof IdReader && $options['id_reader']->isSingleId()) { - return ChoiceList::value($this, [$options['id_reader'], 'getIdValue'], $options['id_reader']); + return ChoiceList::value($this, $options['id_reader']->getIdValue(...), $options['id_reader']); } // Otherwise, an incrementing integer is used as value automatically diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php b/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php index 6b73af766536f..d50ca5c339b95 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php @@ -82,7 +82,7 @@ public function getQueryBuilderPartsForCachingHash(object $queryBuilder): ?array return [ $queryBuilder->getQuery()->getSQL(), - array_map([$this, 'parameterToArray'], $queryBuilder->getParameters()->toArray()), + array_map($this->parameterToArray(...), $queryBuilder->getParameters()->toArray()), ]; } diff --git a/src/Symfony/Bridge/Doctrine/LICENSE b/src/Symfony/Bridge/Doctrine/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bridge/Doctrine/LICENSE +++ b/src/Symfony/Bridge/Doctrine/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index 7be0473590231..5e958d1865300 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Doctrine; use Doctrine\Persistence\AbstractManagerRegistry; +use ProxyManager\Proxy\GhostObjectInterface; use ProxyManager\Proxy\LazyLoadingInterface; use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Component\DependencyInjection\Container; @@ -19,7 +20,7 @@ /** * References Doctrine connections and entity/document managers. * - * @author Lukas Kahwe Smith + * @author Lukas Kahwe Smith */ abstract class ManagerRegistry extends AbstractManagerRegistry { @@ -49,6 +50,9 @@ protected function resetService($name): void if (!$manager instanceof LazyLoadingInterface) { throw new \LogicException('Resetting a non-lazy manager service is not supported. '.(interface_exists(LazyLoadingInterface::class) && class_exists(RuntimeInstantiator::class) ? sprintf('Declare the "%s" service as lazy.', $name) : 'Try running "composer require symfony/proxy-manager-bridge".')); } + if ($manager instanceof GhostObjectInterface) { + throw new \LogicException('Resetting a lazy-ghost-object manager service is not supported.'); + } $manager->setProxyInitializer(\Closure::bind( function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { if (isset($this->aliases[$name])) { diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php index de925284d09dc..105a1c6ffe76e 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php @@ -39,7 +39,7 @@ private function pingConnection(EntityManagerInterface $entityManager) try { $connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL()); - } catch (DBALException $e) { + } catch (DBALException) { $connection->close(); $connection->connect(); } diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/Connection.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Connection.php new file mode 100644 index 0000000000000..27eb35c004ab4 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Connection.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +use Doctrine\DBAL\Driver\Connection as ConnectionInterface; +use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware; +use Doctrine\DBAL\Driver\Result; +use Doctrine\DBAL\Driver\Statement as DriverStatement; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Laurent VOULLEMIER + * + * @internal + */ +final class Connection extends AbstractConnectionMiddleware +{ + private int $nestingLevel = 0; + + public function __construct( + ConnectionInterface $connection, + private DebugDataHolder $debugDataHolder, + private ?Stopwatch $stopwatch, + private string $connectionName, + ) { + parent::__construct($connection); + } + + public function prepare(string $sql): DriverStatement + { + return new Statement( + parent::prepare($sql), + $this->debugDataHolder, + $this->connectionName, + $sql, + ); + } + + public function query(string $sql): Result + { + $this->debugDataHolder->addQuery($this->connectionName, $query = new Query($sql)); + + $this->stopwatch?->start('doctrine', 'doctrine'); + $query->start(); + + try { + $result = parent::query($sql); + } finally { + $query->stop(); + $this->stopwatch?->stop('doctrine'); + } + + return $result; + } + + public function exec(string $sql): int + { + $this->debugDataHolder->addQuery($this->connectionName, $query = new Query($sql)); + + $this->stopwatch?->start('doctrine', 'doctrine'); + $query->start(); + + try { + $affectedRows = parent::exec($sql); + } finally { + $query->stop(); + $this->stopwatch?->stop('doctrine'); + } + + return $affectedRows; + } + + public function beginTransaction(): bool + { + $query = null; + if (1 === ++$this->nestingLevel) { + $this->debugDataHolder->addQuery($this->connectionName, $query = new Query('"START TRANSACTION"')); + } + + $this->stopwatch?->start('doctrine', 'doctrine'); + $query?->start(); + + try { + $ret = parent::beginTransaction(); + } finally { + $query?->stop(); + $this->stopwatch?->stop('doctrine'); + } + + return $ret; + } + + public function commit(): bool + { + $query = null; + if (1 === $this->nestingLevel--) { + $this->debugDataHolder->addQuery($this->connectionName, $query = new Query('"COMMIT"')); + } + + $this->stopwatch?->start('doctrine', 'doctrine'); + $query?->start(); + + try { + $ret = parent::commit(); + } finally { + $query?->stop(); + $this->stopwatch?->stop('doctrine'); + } + + return $ret; + } + + public function rollBack(): bool + { + $query = null; + if (1 === $this->nestingLevel--) { + $this->debugDataHolder->addQuery($this->connectionName, $query = new Query('"ROLLBACK"')); + } + + $this->stopwatch?->start('doctrine', 'doctrine'); + $query?->start(); + + try { + $ret = parent::rollBack(); + } finally { + $query?->stop(); + $this->stopwatch?->stop('doctrine'); + } + + return $ret; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/DebugDataHolder.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/DebugDataHolder.php new file mode 100644 index 0000000000000..14c338e63d691 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/DebugDataHolder.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +/** + * @author Laurent VOULLEMIER + */ +class DebugDataHolder +{ + private array $data = []; + + public function addQuery(string $connectionName, Query $query): void + { + $this->data[$connectionName][] = [ + 'sql' => $query->getSql(), + 'params' => $query->getParams(), + 'types' => $query->getTypes(), + 'executionMS' => [$query, 'getDuration'], // stop() may not be called at this point + ]; + } + + public function getData(): array + { + foreach ($this->data as $connectionName => $dataForConn) { + foreach ($dataForConn as $idx => $data) { + if (\is_callable($data['executionMS'])) { + $this->data[$connectionName][$idx]['executionMS'] = $data['executionMS'](); + } + } + } + + return $this->data; + } + + public function reset(): void + { + $this->data = []; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/Driver.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Driver.php new file mode 100644 index 0000000000000..c66bed90d08fd --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Driver.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +use Doctrine\DBAL\Driver as DriverInterface; +use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Laurent VOULLEMIER + * + * @internal + */ +final class Driver extends AbstractDriverMiddleware +{ + public function __construct( + DriverInterface $driver, + private DebugDataHolder $debugDataHolder, + private ?Stopwatch $stopwatch, + private string $connectionName, + ) { + parent::__construct($driver); + } + + public function connect(array $params): Connection + { + return new Connection( + parent::connect($params), + $this->debugDataHolder, + $this->stopwatch, + $this->connectionName, + ); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/Middleware.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Middleware.php new file mode 100644 index 0000000000000..56b03f51335a8 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Middleware.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +use Doctrine\DBAL\Driver as DriverInterface; +use Doctrine\DBAL\Driver\Middleware as MiddlewareInterface; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * Middleware to collect debug data. + * + * @author Laurent VOULLEMIER + */ +final class Middleware implements MiddlewareInterface +{ + public function __construct( + private DebugDataHolder $debugDataHolder, + private ?Stopwatch $stopwatch, + private string $connectionName = 'default', + ) { + } + + public function wrap(DriverInterface $driver): DriverInterface + { + return new Driver($driver, $this->debugDataHolder, $this->stopwatch, $this->connectionName); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/Query.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Query.php new file mode 100644 index 0000000000000..9813d712132f4 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Query.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +use Doctrine\DBAL\ParameterType; + +/** + * @author Laurent VOULLEMIER + * + * @internal + */ +class Query +{ + private array $params = []; + private array $types = []; + + private ?float $start = null; + private ?float $duration = null; + + public function __construct( + private string $sql, + ) { + } + + public function start(): void + { + $this->start = microtime(true); + } + + public function stop(): void + { + if (null !== $this->start) { + $this->duration = microtime(true) - $this->start; + } + } + + public function setParam(string|int $param, null|string|int|float|bool &$variable, int $type): void + { + // Numeric indexes start at 0 in profiler + $idx = \is_int($param) ? $param - 1 : $param; + + $this->params[$idx] = &$variable; + $this->types[$idx] = $type; + } + + public function setValue(string|int $param, mixed $value, int $type): void + { + // Numeric indexes start at 0 in profiler + $idx = \is_int($param) ? $param - 1 : $param; + + $this->params[$idx] = $value; + $this->types[$idx] = $type; + } + + /** + * @param array $values + */ + public function setValues(array $values): void + { + foreach ($values as $param => $value) { + $this->setValue($param, $value, ParameterType::STRING); + } + } + + public function getSql(): string + { + return $this->sql; + } + + /** + * @return array + */ + public function getParams(): array + { + return $this->params; + } + + /** + * @return array + */ + public function getTypes(): array + { + return $this->types; + } + + /** + * Query duration in seconds. + */ + public function getDuration(): ?float + { + return $this->duration; + } + + public function __clone() + { + $copy = []; + foreach ($this->params as $param => $valueOrVariable) { + $copy[$param] = $valueOrVariable; + } + $this->params = $copy; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Middleware/Debug/Statement.php b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Statement.php new file mode 100644 index 0000000000000..0157c5db11e84 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Middleware/Debug/Statement.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Middleware\Debug; + +use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware; +use Doctrine\DBAL\Driver\Result as ResultInterface; +use Doctrine\DBAL\Driver\Statement as StatementInterface; +use Doctrine\DBAL\ParameterType; + +/** + * @author Laurent VOULLEMIER + * + * @internal + */ +final class Statement extends AbstractStatementMiddleware +{ + private Query $query; + + public function __construct( + StatementInterface $statement, + private DebugDataHolder $debugDataHolder, + private string $connectionName, + string $sql, + ) { + parent::__construct($statement); + + $this->query = new Query($sql); + } + + public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool + { + $this->query->setParam($param, $variable, $type); + + return parent::bindParam($param, $variable, $type, ...\array_slice(\func_get_args(), 3)); + } + + public function bindValue($param, $value, $type = ParameterType::STRING): bool + { + $this->query->setValue($param, $value, $type); + + return parent::bindValue($param, $value, $type); + } + + public function execute($params = null): ResultInterface + { + if (null !== $params) { + $this->query->setValues($params); + } + + // clone to prevent variables by reference to change + $this->debugDataHolder->addQuery($this->connectionName, $query = clone $this->query); + + $query->start(); + + try { + $result = parent::execute($params); + } finally { + $query->stop(); + } + + return $result; + } +} diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index c7e51cb172105..4f9c97186450c 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -97,16 +97,16 @@ public function getTypes(string $class, string $property, array $context = []): $fieldName = $associationMapping['indexBy']; if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { $fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']); - //Not a property, maybe a column name? + // Not a property, maybe a column name? if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) { - //Maybe the column name is the association join column? + // Maybe the column name is the association join column? $associationMapping = $subMetadata->getAssociationMapping($fieldName); /** @var ClassMetadataInfo $subMetadata */ $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName); $subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']); - //Not a property, maybe a column name? + // Not a property, maybe a column name? if (null === ($typeOfField = $subMetadata->getTypeOfField($indexProperty))) { $fieldName = $subMetadata->getFieldForColumn($indexProperty); $typeOfField = $subMetadata->getTypeOfField($fieldName); @@ -135,17 +135,18 @@ public function getTypes(string $class, string $property, array $context = []): } if ($metadata->hasField($property)) { - $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); - if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) { - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass)]; - } - $typeOfField = $metadata->getTypeOfField($property); if (!$builtinType = $this->getPhpType($typeOfField)) { return null; } + $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); + $enumType = null; + if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) { + $enumType = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass); + } + switch ($builtinType) { case Type::BUILTIN_TYPE_OBJECT: switch ($typeOfField) { @@ -171,11 +172,23 @@ public function getTypes(string $class, string $property, array $context = []): switch ($typeOfField) { case Types::ARRAY: case 'json_array': + // return null if $enumType is set, because we can't determine if collectionKeyType is string or int + if ($enumType) { + return null; + } + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; case Types::SIMPLE_ARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), $enumType ?? new Type(Type::BUILTIN_TYPE_STRING))]; + } + break; + case Type::BUILTIN_TYPE_INT: + case Type::BUILTIN_TYPE_STRING: + if ($enumType) { + return [$enumType]; } + break; } return [new Type($builtinType, $nullable)]; @@ -212,7 +225,7 @@ private function getMetadata(string $class): ?ClassMetadata { try { return $this->entityManager->getClassMetadata($class); - } catch (MappingException|OrmMappingException $exception) { + } catch (MappingException|OrmMappingException) { return null; } } @@ -247,47 +260,33 @@ private function isAssociationNullable(array $associationMapping): bool */ private function getPhpType(string $doctrineType): ?string { - switch ($doctrineType) { - case Types::SMALLINT: - case Types::INTEGER: - return Type::BUILTIN_TYPE_INT; - - case Types::FLOAT: - return Type::BUILTIN_TYPE_FLOAT; - - case Types::BIGINT: - case Types::STRING: - case Types::TEXT: - case Types::GUID: - case Types::DECIMAL: - return Type::BUILTIN_TYPE_STRING; - - case Types::BOOLEAN: - return Type::BUILTIN_TYPE_BOOL; - - case Types::BLOB: - case Types::BINARY: - return Type::BUILTIN_TYPE_RESOURCE; - - case Types::OBJECT: - case Types::DATE_MUTABLE: - case Types::DATETIME_MUTABLE: - case Types::DATETIMETZ_MUTABLE: - case 'vardatetime': - case Types::TIME_MUTABLE: - case Types::DATE_IMMUTABLE: - case Types::DATETIME_IMMUTABLE: - case Types::DATETIMETZ_IMMUTABLE: - case Types::TIME_IMMUTABLE: - case Types::DATEINTERVAL: - return Type::BUILTIN_TYPE_OBJECT; - - case Types::ARRAY: - case Types::SIMPLE_ARRAY: - case 'json_array': - return Type::BUILTIN_TYPE_ARRAY; - } - - return null; + return match ($doctrineType) { + Types::SMALLINT, + Types::INTEGER => Type::BUILTIN_TYPE_INT, + Types::FLOAT => Type::BUILTIN_TYPE_FLOAT, + Types::BIGINT, + Types::STRING, + Types::TEXT, + Types::GUID, + Types::DECIMAL => Type::BUILTIN_TYPE_STRING, + Types::BOOLEAN => Type::BUILTIN_TYPE_BOOL, + Types::BLOB, + Types::BINARY => Type::BUILTIN_TYPE_RESOURCE, + Types::OBJECT, + Types::DATE_MUTABLE, + Types::DATETIME_MUTABLE, + Types::DATETIMETZ_MUTABLE, + 'vardatetime', + Types::TIME_MUTABLE, + Types::DATE_IMMUTABLE, + Types::DATETIME_IMMUTABLE, + Types::DATETIMETZ_IMMUTABLE, + Types::TIME_IMMUTABLE, + Types::DATEINTERVAL => Type::BUILTIN_TYPE_OBJECT, + Types::ARRAY, + Types::SIMPLE_ARRAY, + 'json_array' => Type::BUILTIN_TYPE_ARRAY, + default => null, + }; } } diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index 8d497086a1422..4d8dcb260467d 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -163,7 +163,7 @@ public function verifyToken(PersistentTokenInterface $token, string $tokenValue) // we also accept it as a valid value. try { $tmpToken = $this->loadTokenBySeries($tmpSeries); - } catch (TokenNotFoundException $e) { + } catch (TokenNotFoundException) { return false; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php index 1631fa8ae37e7..9d86eeed54ef1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php @@ -180,6 +180,15 @@ public function testGetListeners() $this->assertSame([$listener1, $listener2], array_values($this->evm->getListeners()['foo'])); } + public function testGetAllListeners() + { + $this->container->set('lazy', $listener1 = new MyListener()); + $this->evm->addEventListener('foo', 'lazy'); + $this->evm->addEventListener('foo', $listener2 = new MyListener()); + + $this->assertSame([$listener1, $listener2], array_values($this->evm->getAllListeners()['foo'])); + } + public function testRemoveEventListener() { $this->container->set('lazy', $listener1 = new MyListener()); diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index 35fc48ff1536f..25cc33fb4ae9f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -12,11 +12,14 @@ namespace Symfony\Bridge\Doctrine\Tests\DataCollector; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Logging\DebugStack; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; +use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; +use Symfony\Bridge\Doctrine\Middleware\Debug\Query; +use Symfony\Bridge\PhpUnit\ClockMock; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\VarDumper\Cloner\Data; @@ -27,66 +30,40 @@ class_exists(\Doctrine\DBAL\Platforms\MySqlPlatform::class); class DoctrineDataCollectorTest extends TestCase { - public function testCollectConnections() - { - $c = $this->createCollector([]); - $c->collect(new Request(), new Response()); - $this->assertEquals(['default' => 'doctrine.dbal.default_connection'], $c->getConnections()); - } - - public function testCollectManagers() - { - $c = $this->createCollector([]); - $c->collect(new Request(), new Response()); - $this->assertEquals(['default' => 'doctrine.orm.default_entity_manager'], $c->getManagers()); - } + use DoctrineDataCollectorTestTrait; - public function testCollectQueryCount() + protected function setUp(): void { - $c = $this->createCollector([]); - $c->collect(new Request(), new Response()); - $this->assertEquals(0, $c->getQueryCount()); - - $queries = [ - ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 0], - ]; - $c = $this->createCollector($queries); - $c->collect(new Request(), new Response()); - $this->assertEquals(1, $c->getQueryCount()); + ClockMock::register(self::class); + ClockMock::withClockMock(1500000000); } - public function testCollectTime() + public function testReset() { - $c = $this->createCollector([]); - $c->collect(new Request(), new Response()); - $this->assertEquals(0, $c->getTime()); - $queries = [ ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], ]; $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); - $this->assertEquals(1, $c->getTime()); - $queries = [ - ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], - ['sql' => 'SELECT * FROM table2', 'params' => [], 'types' => [], 'executionMS' => 2], - ]; - $c = $this->createCollector($queries); + $c->reset(); $c->collect(new Request(), new Response()); - $this->assertEquals(3, $c->getTime()); + $c = unserialize(serialize($c)); + + $this->assertEquals([], $c->getQueries()); } /** * @dataProvider paramProvider */ - public function testCollectQueries($param, $types, $expected, $explainable, bool $runnable = true) + public function testCollectQueries($param, $types, $expected) { $queries = [ ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], ]; $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); $collectedQueries = $c->getQueries(); @@ -102,8 +79,8 @@ public function testCollectQueries($param, $types, $expected, $explainable, bool $this->assertEquals($expected, $collectedParam); } - $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); - $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); + $this->assertTrue($collectedQueries['default'][0]['explainable']); + $this->assertTrue($collectedQueries['default'][0]['runnable']); } public function testCollectQueryWithNoParams() @@ -114,6 +91,7 @@ public function testCollectQueryWithNoParams() ]; $c = $this->createCollector($queries); $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); $collectedQueries = $c->getQueries(); $this->assertInstanceOf(Data::class, $collectedQueries['default'][0]['params']); @@ -126,36 +104,10 @@ public function testCollectQueryWithNoParams() $this->assertTrue($collectedQueries['default'][1]['runnable']); } - public function testCollectQueryWithNoTypes() - { - $queries = [ - ['sql' => 'SET sql_mode=(SELECT REPLACE(@@sql_mode, \'ONLY_FULL_GROUP_BY\', \'\'))', 'params' => [], 'types' => null, 'executionMS' => 1], - ]; - $c = $this->createCollector($queries); - $c->collect(new Request(), new Response()); - - $collectedQueries = $c->getQueries(); - $this->assertSame([], $collectedQueries['default'][0]['types']); - } - - public function testReset() - { - $queries = [ - ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], - ]; - $c = $this->createCollector($queries); - $c->collect(new Request(), new Response()); - - $c->reset(); - $c->collect(new Request(), new Response()); - - $this->assertEquals(['default' => []], $c->getQueries()); - } - /** * @dataProvider paramProvider */ - public function testSerialization($param, array $types, $expected, $explainable, bool $runnable = true) + public function testSerialization($param, array $types, $expected) { $queries = [ ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], @@ -178,55 +130,17 @@ public function testSerialization($param, array $types, $expected, $explainable, $this->assertEquals($expected, $collectedParam); } - $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); - $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); + $this->assertTrue($collectedQueries['default'][0]['explainable']); + $this->assertTrue($collectedQueries['default'][0]['runnable']); } public function paramProvider(): array { return [ - ['some value', [], 'some value', true], - [1, [], 1, true], - [true, [], true, true], - [null, [], null, true], - [new \DateTime('2011-09-11'), ['date'], '2011-09-11', true], - [fopen(__FILE__, 'r'), [], '/* Resource(stream) */', false, false], - [ - new \stdClass(), - [], - <<method('getConnection') ->willReturn($connection); - $logger = $this->createMock(DebugStack::class); - $logger->queries = $queries; + $debugDataHolder = new DebugDataHolder(); + $collector = new DoctrineDataCollector($registry, $debugDataHolder); + foreach ($queries as $queryData) { + $query = new Query($queryData['sql'] ?? ''); + foreach (($queryData['params'] ?? []) as $key => $value) { + if (\is_int($key)) { + ++$key; + } - $collector = new DoctrineDataCollector($registry); - $collector->addLogger('default', $logger); + $query->setValue($key, $value, $queryData['type'][$key] ?? ParameterType::STRING); + } - return $collector; - } -} + $query->start(); -class StringRepresentableClass -{ - public function __toString(): string - { - return 'string representation'; + $debugDataHolder->addQuery('default', $query); + + if (isset($queryData['executionMS'])) { + sleep($queryData['executionMS']); + } + $query->stop(); + } + + return $collector; } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTestTrait.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTestTrait.php new file mode 100644 index 0000000000000..4ca941f10094d --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTestTrait.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +trait DoctrineDataCollectorTestTrait +{ + public function testCollectConnections() + { + $c = $this->createCollector([]); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(['default' => 'doctrine.dbal.default_connection'], $c->getConnections()); + } + + public function testCollectManagers() + { + $c = $this->createCollector([]); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(['default' => 'doctrine.orm.default_entity_manager'], $c->getManagers()); + } + + public function testCollectQueryCount() + { + $c = $this->createCollector([]); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(0, $c->getQueryCount()); + + $queries = [ + ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 0], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(1, $c->getQueryCount()); + } + + public function testCollectTime() + { + $c = $this->createCollector([]); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(0, $c->getTime()); + + $queries = [ + ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(1, $c->getTime()); + + $queries = [ + ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], + ['sql' => 'SELECT * FROM table2', 'params' => [], 'types' => [], 'executionMS' => 2], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + $this->assertEquals(3, $c->getTime()); + } + + public function testCollectQueryWithNoTypes() + { + $queries = [ + ['sql' => 'SET sql_mode=(SELECT REPLACE(@@sql_mode, \'ONLY_FULL_GROUP_BY\', \'\'))', 'params' => [], 'types' => null, 'executionMS' => 1], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + + $collectedQueries = $c->getQueries(); + $this->assertSame([], $collectedQueries['default'][0]['types']); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorWithDebugStackTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorWithDebugStackTest.php new file mode 100644 index 0000000000000..f0962eff3132d --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorWithDebugStackTest.php @@ -0,0 +1,195 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\DataCollector; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Logging\DebugStack; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +// Doctrine DBAL 2 compatibility +class_exists(\Doctrine\DBAL\Platforms\MySqlPlatform::class); + +/** + * @group legacy + */ +class DoctrineDataCollectorWithDebugStackTest extends TestCase +{ + use DoctrineDataCollectorTestTrait; + + public function testReset() + { + $queries = [ + ['sql' => 'SELECT * FROM table1', 'params' => [], 'types' => [], 'executionMS' => 1], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + + $c->reset(); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + + $this->assertEquals(['default' => []], $c->getQueries()); + } + + /** + * @dataProvider paramProvider + */ + public function testCollectQueries($param, $types, $expected, $explainable, bool $runnable = true) + { + $queries = [ + ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + + $collectedQueries = $c->getQueries(); + + $collectedParam = $collectedQueries['default'][0]['params'][0]; + if ($collectedParam instanceof Data) { + $dumper = new CliDumper($out = fopen('php://memory', 'r+')); + $dumper->setColors(false); + $collectedParam->dump($dumper); + $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } elseif (\is_string($expected)) { + $this->assertStringMatchesFormat($expected, $collectedParam); + } else { + $this->assertEquals($expected, $collectedParam); + } + + $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); + $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); + } + + /** + * @dataProvider paramProvider + */ + public function testSerialization($param, array $types, $expected, $explainable, bool $runnable = true) + { + $queries = [ + ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], + ]; + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + $c = unserialize(serialize($c)); + + $collectedQueries = $c->getQueries(); + + $collectedParam = $collectedQueries['default'][0]['params'][0]; + if ($collectedParam instanceof Data) { + $dumper = new CliDumper($out = fopen('php://memory', 'r+')); + $dumper->setColors(false); + $collectedParam->dump($dumper); + $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } elseif (\is_string($expected)) { + $this->assertStringMatchesFormat($expected, $collectedParam); + } else { + $this->assertEquals($expected, $collectedParam); + } + + $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); + $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); + } + + public function paramProvider(): array + { + return [ + ['some value', [], 'some value', true], + [1, [], 1, true], + [true, [], true, true], + [null, [], null, true], + [new \DateTime('2011-09-11'), ['date'], '2011-09-11', true], + [fopen(__FILE__, 'r'), [], '/* Resource(stream) */', false, false], + [ + new \stdClass(), + [], + <<getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + $connection->expects($this->any()) + ->method('getDatabasePlatform') + ->willReturn(new MySqlPlatform()); + + $registry = $this->createMock(ManagerRegistry::class); + $registry + ->expects($this->any()) + ->method('getConnectionNames') + ->willReturn(['default' => 'doctrine.dbal.default_connection']); + $registry + ->expects($this->any()) + ->method('getManagerNames') + ->willReturn(['default' => 'doctrine.orm.default_entity_manager']); + $registry->expects($this->any()) + ->method('getConnection') + ->willReturn($connection); + + $collector = new DoctrineDataCollector($registry); + $logger = $this->createMock(DebugStack::class); + $logger->queries = $queries; + $collector->addLogger('default', $logger); + + return $collector; + } +} + +class StringRepresentableClass +{ + public function __toString(): string + { + return 'string representation'; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php index c24c4b53005c9..fecc532a0b609 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection\CompilerPass; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterUidTypePassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterUidTypePassTest.php index 9b87c051702ee..03398e4245ebe 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterUidTypePassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterUidTypePassTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection\CompilerPass; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index 17df373369d95..2ca6eda3e74b8 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -79,7 +79,6 @@ public function testFixManagersAutoMappingsWithTwoAutomappings() $reflection = new \ReflectionClass(\get_class($this->extension)); $method = $reflection->getMethod('fixManagersAutoMappings'); - $method->setAccessible(true); $method->invoke($this->extension, $emConfigs, $bundles); } @@ -168,7 +167,6 @@ public function testFixManagersAutoMappings(array $originalEm1, array $originalE $reflection = new \ReflectionClass(\get_class($this->extension)); $method = $reflection->getMethod('fixManagersAutoMappings'); - $method->setAccessible(true); $newEmConfigs = $method->invoke($this->extension, $emConfigs, $bundles); @@ -186,7 +184,6 @@ public function testMappingTypeDetection() $reflection = new \ReflectionClass(\get_class($this->extension)); $method = $reflection->getMethod('detectMappingType'); - $method->setAccessible(true); // The ordinary fixtures contain annotation $mappingType = $method->invoke($this->extension, __DIR__.'/../Fixtures', $container); @@ -279,7 +276,10 @@ public function testUnrecognizedCacheDriverException() public function providerBundles() { yield ['AnnotationsBundle', 'annotation', '/Entity']; + yield ['AnnotationsOneLineBundle', 'annotation', '/Entity']; + yield ['FullEmbeddableAnnotationsBundle', 'annotation', '/Entity']; yield ['AttributesBundle', 'attribute', '/Entity']; + yield ['FullEmbeddableAttributesBundle', 'attribute', '/Entity']; yield ['XmlBundle', 'xml', '/Resources/config/doctrine']; yield ['PhpBundle', 'php', '/Resources/config/doctrine']; yield ['YamlBundle', 'yml', '/Resources/config/doctrine']; @@ -329,7 +329,6 @@ public function testBundleAutoMapping(string $bundle, string $expectedType, stri $reflection = new \ReflectionClass(\get_class($this->extension)); $method = $reflection->getMethod('getMappingDriverBundleConfigDefaults'); - $method->setAccessible(true); $this->assertSame( [ @@ -347,8 +346,6 @@ protected function invokeLoadCacheDriver(array $objectManager, ContainerBuilder { $method = new \ReflectionMethod($this->extension, 'loadObjectManagerCacheDriver'); - $method->setAccessible(true); - $method->invokeArgs($this->extension, [$objectManager, $container, $cacheName]); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/AnnotationsOneLineBundle.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/AnnotationsOneLineBundle.php new file mode 100644 index 0000000000000..6d401bae4f987 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/AnnotationsOneLineBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\AnnotationsOneLineBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class AnnotationsOneLineBundle extends Bundle +{ +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/Entity/Person.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/Entity/Person.php new file mode 100644 index 0000000000000..b55fe6f86503b --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AnnotationsOneLineBundle/Entity/Person.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\AnnotationsOneLineBundle\Entity; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\Id; + +/** @Entity */ +class Person +{ + /** @Id @Column(type="integer") */ + protected $id; + + /** @Column(type="string") */ + public $name; + + public function __construct($id, $name) + { + $this->id = $id; + $this->name = $name; + } + + public function __toString(): string + { + return (string) $this->name; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AttributesBundle/AnnotatedEntity/Person.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AttributesBundle/AnnotatedEntity/Person.php new file mode 100644 index 0000000000000..0ec41bb096861 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/AttributesBundle/AnnotatedEntity/Person.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\AttributesBundle\AnnotatedEntity; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\Id; + +/** + * @Entity + */ +class Person +{ + /** @Id @Column(type="integer") */ + protected $id; + + /** @Column(type="string") */ + public $name; + + public function __construct($id, $name) + { + $this->id = $id; + $this->name = $name; + } + + public function __toString(): string + { + return (string) $this->name; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/Entity/Address.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/Entity/Address.php new file mode 100644 index 0000000000000..d311a3f1ad1a1 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/Entity/Address.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\FullEmbeddableAnnotationsBundle\Entity; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Embeddable; +use Doctrine\ORM\Mapping\Id; + +/** + * @Embeddable + */ +class Address +{ + + /** @Column(type="string") */ + public $street; + + /** @Column(type="string") */ + public $zipCode; + + /** @Column(type="string") */ + public $city; + + public function __construct($street, $zipCode, $city) + { + $this->street = $street; + $this->zipCode = $zipCode; + $this->city = $city; + } + + public function __toString(): string + { + return sprintf('%s %s %s', $this->street, $this->zipCode, $this->city); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/FullEmbeddableAnnotationsBundle.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/FullEmbeddableAnnotationsBundle.php new file mode 100644 index 0000000000000..ac03c9b0ce870 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAnnotationsBundle/FullEmbeddableAnnotationsBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\FullEmbeddableAnnotationsBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class FullEmbeddableAnnotationsBundle extends Bundle +{ +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/Entity/Address.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/Entity/Address.php new file mode 100644 index 0000000000000..c0c58d6a21ce2 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/Entity/Address.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\FullEmbeddableAttributesBundle\Entity; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Embeddable; +use Doctrine\ORM\Mapping\Id; + +#[Embeddable] +class Address +{ + + #[Column(type: 'string')] + public $street; + + #[Column(type: 'string')] + public $zipCode; + + #[Column(type: 'string')] + public $city; + + public function __construct($street, $zipCode, $city) + { + $this->street = $street; + $this->zipCode = $zipCode; + $this->city = $city; + } + + public function __toString(): string + { + return sprintf('%s %s %s', $this->street, $this->zipCode, $this->city); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/FullEmbeddableAttributesBundle.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/FullEmbeddableAttributesBundle.php new file mode 100644 index 0000000000000..374f63dbf5422 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Bundles/FullEmbeddableAttributesBundle/FullEmbeddableAttributesBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Fixtures\Bundles\FullEmbeddableAttributesBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class FullEmbeddableAttributesBundle extends Bundle +{ +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php index 98b3c96d9b3a7..bdbb3e9a9b4fd 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php @@ -153,8 +153,7 @@ public function testLoadChoiceListUsesObjectLoaderIfAvailable() $this->assertEquals($choiceList, $loaded = $loader->loadChoiceList()); // no further loads on subsequent calls - - $this->assertSame($loaded, $loader->loadChoiceList()); + $this->assertEquals($loaded, $loader->loadChoiceList()); } public function testLoadValuesForChoices() @@ -319,8 +318,8 @@ public function testLegacyLoadChoicesForValuesLoadsOnlyChoicesIfValueUseIdReader $this->assertSame( [4 => $this->obj3, 7 => $this->obj2], - $loader->loadChoicesForValues([4 => '3', 7 => '2'] - )); + $loader->loadChoicesForValues([4 => '3', 7 => '2']) + ); } public function testLoadChoicesForValuesLoadsOnlyChoicesIfValueUseIdReader() @@ -355,8 +354,8 @@ public function testLoadChoicesForValuesLoadsOnlyChoicesIfValueUseIdReader() $this->assertSame( [4 => $this->obj3, 7 => $this->obj2], - $loader->loadChoicesForValues([4 => '3', 7 => '2'], [$this->idReader, 'getIdValue'] - )); + $loader->loadChoicesForValues([4 => '3', 7 => '2'], [$this->idReader, 'getIdValue']) + ); } public function testLoadChoicesForValuesLoadsAllIfSingleIntIdAndValueGiven() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 7d253dc59b85d..efb3b04824b6b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -14,7 +14,6 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\GuidType; use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Version; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; @@ -226,12 +225,6 @@ public function testUidThrowProperException($entityClass) public function testEmbeddedIdentifierName() { - if (Version::compare('2.5.0') > 0) { - $this->markTestSkipped('Applicable only for Doctrine >= 2.5.0'); - - return; - } - $em = DoctrineTestHelper::createTestEntityManager(); $query = $this->getMockBuilder(\QueryMock::class) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index d1c2c04b88956..18f918dd3b522 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -1310,10 +1310,7 @@ public function testLoaderCachingWithParameters() $this->assertSame($choiceList1, $choiceList3); } - /** - * @return MockObject&ManagerRegistry - */ - protected function createRegistryMock($name, $em): ManagerRegistry + protected function createRegistryMock($name, $em): MockObject&ManagerRegistry { $registry = $this->createMock(ManagerRegistry::class); $registry->expects($this->any()) @@ -1779,4 +1776,32 @@ public function testSubmitNullMultipleUsesDefaultEmptyData() $this->assertEquals($collection, $form->getNormData()); $this->assertEquals($collection, $form->getData()); } + + public function testWithSameLoaderAndDifferentChoiceValueCallbacks() + { + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $entity2 = new SingleIntIdEntity(2, 'Bar'); + $this->persist([$entity1, $entity2]); + + $view = $this->factory->create(FormTypeTest::TESTED_TYPE) + ->add('entity_one', self::TESTED_TYPE, [ + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + ]) + ->add('entity_two', self::TESTED_TYPE, [ + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'choice_value' => function ($choice) { + return $choice ? $choice->name : ''; + }, + ]) + ->createView() + ; + + $this->assertSame('1', $view['entity_one']->vars['choices'][1]->value); + $this->assertSame('2', $view['entity_one']->vars['choices'][2]->value); + + $this->assertSame('Foo', $view['entity_two']->vars['choices']['Foo']->value); + $this->assertSame('Bar', $view['entity_two']->vars['choices']['Bar']->value); + } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php b/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php index 957ac0f60aeb0..f09c959bb7b36 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UlidGeneratorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\IdGenerator; +use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Entity; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator; @@ -21,7 +22,7 @@ class UlidGeneratorTest extends TestCase { public function testUlidCanBeGenerated() { - $em = new EntityManager(); + $em = (new \ReflectionClass(EntityManager::class))->newInstanceWithoutConstructor(); $generator = new UlidGenerator(); $ulid = $generator->generate($em, new Entity()); @@ -29,13 +30,10 @@ public function testUlidCanBeGenerated() $this->assertTrue(Ulid::isValid($ulid)); } - /** - * @requires function \Symfony\Component\Uid\Factory\UlidFactory::create - */ public function testUlidFactory() { $ulid = new Ulid('00000000000000000000000000'); - $em = new EntityManager(); + $em = (new \ReflectionClass(EntityManager::class))->newInstanceWithoutConstructor(); $factory = $this->createMock(UlidFactory::class); $factory->expects($this->any()) ->method('create') diff --git a/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UuidGeneratorTest.php b/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UuidGeneratorTest.php index 34367b0bd7213..74b2c20936529 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UuidGeneratorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/IdGenerator/UuidGeneratorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\IdGenerator; +use Doctrine\ORM\EntityManager; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Component\Uid\Factory\UuidFactory; @@ -18,14 +19,11 @@ use Symfony\Component\Uid\UuidV4; use Symfony\Component\Uid\UuidV6; -/** - * @requires function \Symfony\Component\Uid\Factory\UuidFactory::create - */ class UuidGeneratorTest extends TestCase { public function testUuidCanBeGenerated() { - $em = new EntityManager(); + $em = (new \ReflectionClass(EntityManager::class))->newInstanceWithoutConstructor(); $generator = new UuidGenerator(); $uuid = $generator->generate($em, new Entity()); @@ -35,7 +33,7 @@ public function testUuidCanBeGenerated() public function testCustomUuidfactory() { $uuid = new UuidV4(); - $em = new EntityManager(); + $em = (new \ReflectionClass(EntityManager::class))->newInstanceWithoutConstructor(); $factory = $this->createMock(UuidFactory::class); $factory->expects($this->any()) ->method('create') @@ -47,7 +45,7 @@ public function testCustomUuidfactory() public function testUuidfactory() { - $em = new EntityManager(); + $em = (new \ReflectionClass(EntityManager::class))->newInstanceWithoutConstructor(); $generator = new UuidGenerator(); $this->assertInstanceOf(UuidV6::class, $generator->generate($em, new Entity())); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php new file mode 100644 index 0000000000000..de9d537043788 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php @@ -0,0 +1,262 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Middleware\Debug; + +use Doctrine\DBAL\Configuration; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Middleware as MiddlewareInterface; +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\ParameterType; +use Doctrine\DBAL\Statement; +use Doctrine\DBAL\Types\Types; +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; +use Symfony\Bridge\Doctrine\Middleware\Debug\Middleware; +use Symfony\Bridge\PhpUnit\ClockMock; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @requires extension pdo_sqlite + */ +class MiddlewareTest extends TestCase +{ + private DebugDataHolder $debugDataHolder; + private Connection $conn; + private ?Stopwatch $stopwatch; + + protected function setUp(): void + { + parent::setUp(); + + if (!interface_exists(MiddlewareInterface::class)) { + $this->markTestSkipped(sprintf('%s needed to run this test', MiddlewareInterface::class)); + } + + ClockMock::withClockMock(false); + } + + private function init(bool $withStopwatch = true): void + { + $this->stopwatch = $withStopwatch ? new Stopwatch() : null; + + $configuration = new Configuration(); + $this->debugDataHolder = new DebugDataHolder(); + $configuration->setMiddlewares([new Middleware($this->debugDataHolder, $this->stopwatch)]); + + $this->conn = DriverManager::getConnection([ + 'driver' => 'pdo_sqlite', + 'memory' => true, + ], $configuration); + + $this->conn->executeQuery(<< [ + static fn (Statement|Connection $target, mixed ...$args) => $target->executeStatement(...$args), + ], + 'executeQuery' => [ + static fn (Statement|Connection $target, mixed ...$args) => $target->executeQuery(...$args), + ], + ]; + } + + /** + * @dataProvider provideExecuteMethod + */ + public function testWithoutBinding(callable $executeMethod) + { + $this->init(); + + $executeMethod($this->conn, 'INSERT INTO products(name, price, stock) VALUES ("product1", 12.5, 5)'); + + $debug = $this->debugDataHolder->getData()['default'] ?? []; + $this->assertCount(2, $debug); + $this->assertSame('INSERT INTO products(name, price, stock) VALUES ("product1", 12.5, 5)', $debug[1]['sql']); + $this->assertSame([], $debug[1]['params']); + $this->assertSame([], $debug[1]['types']); + $this->assertGreaterThan(0, $debug[1]['executionMS']); + } + + /** + * @dataProvider provideExecuteMethod + */ + public function testWithValueBound(callable $executeMethod) + { + $this->init(); + + $sql = <<conn->prepare($sql); + $stmt->bindValue(1, 'product1'); + $stmt->bindValue(2, 12.5); + $stmt->bindValue(3, 5, ParameterType::INTEGER); + $stmt->bindValue(4, $res = $this->getResourceFromString('mydata'), ParameterType::BINARY); + $stmt->bindValue(5, ['foo', 'bar'], Types::SIMPLE_ARRAY); + $stmt->bindValue(6, new \DateTime('2022-06-12 11:00:00'), Types::DATETIME_MUTABLE); + + $executeMethod($stmt); + + $debug = $this->debugDataHolder->getData()['default'] ?? []; + $this->assertCount(2, $debug); + $this->assertSame($sql, $debug[1]['sql']); + $this->assertSame(['product1', 12.5, 5, $res, 'foo,bar', '2022-06-12 11:00:00'], $debug[1]['params']); + $this->assertSame([ParameterType::STRING, ParameterType::STRING, ParameterType::INTEGER, ParameterType::BINARY, ParameterType::STRING, ParameterType::STRING], $debug[1]['types']); + $this->assertGreaterThan(0, $debug[1]['executionMS']); + } + + /** + * @dataProvider provideExecuteMethod + */ + public function testWithParamBound(callable $executeMethod) + { + $this->init(); + + $product = 'product1'; + $price = 12.5; + $stock = 5; + + $stmt = $this->conn->prepare('INSERT INTO products(name, price, stock) VALUES (?, ?, ?)'); + $stmt->bindParam(1, $product); + $stmt->bindParam(2, $price); + $stmt->bindParam(3, $stock, ParameterType::INTEGER); + + $executeMethod($stmt); + + // Debug data should not be affected by these changes + $product = 'product2'; + $price = 13.5; + $stock = 4; + + $debug = $this->debugDataHolder->getData()['default'] ?? []; + $this->assertCount(2, $debug); + $this->assertSame('INSERT INTO products(name, price, stock) VALUES (?, ?, ?)', $debug[1]['sql']); + $this->assertSame(['product1', '12.5', 5], $debug[1]['params']); + $this->assertSame([ParameterType::STRING, ParameterType::STRING, ParameterType::INTEGER], $debug[1]['types']); + $this->assertGreaterThan(0, $debug[1]['executionMS']); + } + + public function provideEndTransactionMethod(): array + { + return [ + 'commit' => [static fn (Connection $conn) => $conn->commit(), '"COMMIT"'], + 'rollback' => [static fn (Connection $conn) => $conn->rollBack(), '"ROLLBACK"'], + ]; + } + + /** + * @dataProvider provideEndTransactionMethod + */ + public function testTransaction(callable $endTransactionMethod, string $expectedEndTransactionDebug) + { + $this->init(); + + $this->conn->beginTransaction(); + $this->conn->beginTransaction(); + $this->conn->executeStatement('INSERT INTO products(name, price, stock) VALUES ("product1", 12.5, 5)'); + $endTransactionMethod($this->conn); + $endTransactionMethod($this->conn); + $this->conn->beginTransaction(); + $this->conn->executeStatement('INSERT INTO products(name, price, stock) VALUES ("product2", 15.5, 12)'); + $endTransactionMethod($this->conn); + + $debug = $this->debugDataHolder->getData()['default'] ?? []; + $this->assertCount(7, $debug); + $this->assertSame('"START TRANSACTION"', $debug[1]['sql']); + $this->assertGreaterThan(0, $debug[1]['executionMS']); + $this->assertSame('INSERT INTO products(name, price, stock) VALUES ("product1", 12.5, 5)', $debug[2]['sql']); + $this->assertGreaterThan(0, $debug[2]['executionMS']); + $this->assertSame($expectedEndTransactionDebug, $debug[3]['sql']); + $this->assertGreaterThan(0, $debug[3]['executionMS']); + $this->assertSame('"START TRANSACTION"', $debug[4]['sql']); + $this->assertGreaterThan(0, $debug[4]['executionMS']); + $this->assertSame('INSERT INTO products(name, price, stock) VALUES ("product2", 15.5, 12)', $debug[5]['sql']); + $this->assertGreaterThan(0, $debug[5]['executionMS']); + $this->assertSame($expectedEndTransactionDebug, $debug[6]['sql']); + $this->assertGreaterThan(0, $debug[6]['executionMS']); + } + + public function provideExecuteAndEndTransactionMethods(): array + { + return [ + 'commit and exec' => [ + static fn (Connection $conn, string $sql) => $conn->executeStatement($sql), + static fn (Connection $conn) => $conn->commit(), + ], + 'rollback and query' => [ + static fn (Connection $conn, string $sql) => $conn->executeQuery($sql), + static fn (Connection $conn) => $conn->rollBack(), + ], + ]; + } + + /** + * @dataProvider provideExecuteAndEndTransactionMethods + */ + public function testGlobalDoctrineDuration(callable $sqlMethod, callable $endTransactionMethod) + { + $this->init(); + + $periods = $this->stopwatch->getEvent('doctrine')->getPeriods(); + $this->assertCount(1, $periods); + + $this->conn->beginTransaction(); + + $this->assertFalse($this->stopwatch->getEvent('doctrine')->isStarted()); + $this->assertCount(2, $this->stopwatch->getEvent('doctrine')->getPeriods()); + + $sqlMethod($this->conn, 'SELECT * FROM products'); + + $this->assertFalse($this->stopwatch->getEvent('doctrine')->isStarted()); + $this->assertCount(3, $this->stopwatch->getEvent('doctrine')->getPeriods()); + + $endTransactionMethod($this->conn); + + $this->assertFalse($this->stopwatch->getEvent('doctrine')->isStarted()); + $this->assertCount(4, $this->stopwatch->getEvent('doctrine')->getPeriods()); + } + + /** + * @dataProvider provideExecuteAndEndTransactionMethods + */ + public function testWithoutStopwatch(callable $sqlMethod, callable $endTransactionMethod) + { + $this->init(false); + + $this->conn->beginTransaction(); + $sqlMethod($this->conn, 'SELECT * FROM products'); + $endTransactionMethod($this->conn); + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 5d0a09f5f906a..3771e772afc49 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -15,6 +15,7 @@ use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\ORMSetup; use Doctrine\ORM\Tools\Setup; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; @@ -33,7 +34,9 @@ class DoctrineExtractorTest extends TestCase { private function createExtractor() { - $config = Setup::createAnnotationMetadataConfiguration([__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'], true); + $config = class_exists(ORMSetup::class) + ? ORMSetup::createAnnotationMetadataConfiguration([__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'], true) + : Setup::createAnnotationMetadataConfiguration([__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'], true); $entityManager = EntityManager::create(['driver' => 'pdo_sqlite'], $config); if (!DBALType::hasType('foo')) { @@ -86,10 +89,6 @@ public function testGetProperties() public function testTestGetPropertiesWithEmbedded() { - if (!class_exists(\Doctrine\ORM\Mapping\Embedded::class)) { - $this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.'); - } - $this->assertEquals( [ 'id', @@ -109,10 +108,6 @@ public function testExtract($property, array $type = null) public function testExtractWithEmbedded() { - if (!class_exists(\Doctrine\ORM\Mapping\Embedded::class)) { - $this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.'); - } - $expectedTypes = [new Type( Type::BUILTIN_TYPE_OBJECT, false, @@ -128,9 +123,6 @@ public function testExtractWithEmbedded() $this->assertEquals($expectedTypes, $actualTypes); } - /** - * @requires PHP 8.1 - */ public function testExtractEnum() { if (!property_exists(Column::class, 'enumType')) { @@ -138,6 +130,9 @@ public function testExtractEnum() } $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, EnumString::class)], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumString', [])); $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, EnumInt::class)], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumInt', [])); + $this->assertNull($this->createExtractor()->getTypes(DoctrineEnum::class, 'enumStringArray', [])); + $this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, EnumInt::class))], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumIntArray', [])); + $this->assertNull($this->createExtractor()->getTypes(DoctrineEnum::class, 'enumCustom', [])); } public function typesProvider() diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php index 467522cbd3914..fd5271fc47730 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEnum.php @@ -35,4 +35,19 @@ class DoctrineEnum * @Column(type="integer", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt") */ protected $enumInt; + + /** + * @Column(type="array", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumString") + */ + protected $enumStringArray; + + /** + * @Column(type="simple_array", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt") + */ + protected $enumIntArray; + + /** + * @Column(type="custom_foo", enumType="Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt") + */ + protected $enumCustom; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php index 4e75f41cb688a..9d8b9256f4c9d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Security\RememberMe; use Doctrine\DBAL\DriverManager; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php index fde2341bc9ebe..8fd4b8b0a04b6 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php @@ -12,6 +12,9 @@ namespace Symfony\Bridge\Doctrine\Tests\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use PHPUnit\Framework\TestCase; @@ -19,13 +22,13 @@ use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Ulid; +// DBAL 2 compatibility +class_exists('Doctrine\DBAL\Platforms\PostgreSqlPlatform'); + final class UlidTypeTest extends TestCase { private const DUMMY_ULID = '01EEDQEK6ZAZE93J8KG5B4MBJC'; - /** @var AbstractPlatform */ - private $platform; - /** @var UlidType */ private $type; @@ -40,14 +43,6 @@ public static function setUpBeforeClass(): void protected function setUp(): void { - $this->platform = $this->createMock(AbstractPlatform::class); - $this->platform - ->method('hasNativeGuidType') - ->willReturn(true); - $this->platform - ->method('getGuidTypeDeclarationSQL') - ->willReturn('DUMMYVARCHAR()'); - $this->type = Type::getType('ulid'); } @@ -56,7 +51,7 @@ public function testUlidConvertsToDatabaseValue() $ulid = Ulid::fromString(self::DUMMY_ULID); $expected = $ulid->toRfc4122(); - $actual = $this->type->convertToDatabaseValue($ulid, $this->platform); + $actual = $this->type->convertToDatabaseValue($ulid, new PostgreSQLPlatform()); $this->assertEquals($expected, $actual); } @@ -70,14 +65,14 @@ public function testUlidInterfaceConvertsToDatabaseValue() ->method('toRfc4122') ->willReturn('foo'); - $actual = $this->type->convertToDatabaseValue($ulid, $this->platform); + $actual = $this->type->convertToDatabaseValue($ulid, new PostgreSQLPlatform()); $this->assertEquals('foo', $actual); } public function testUlidStringConvertsToDatabaseValue() { - $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, $this->platform); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_ULID, new PostgreSQLPlatform()); $ulid = Ulid::fromString(self::DUMMY_ULID); $expected = $ulid->toRfc4122(); @@ -89,25 +84,25 @@ public function testNotSupportedTypeConversionForDatabaseValue() { $this->expectException(ConversionException::class); - $this->type->convertToDatabaseValue(new \stdClass(), $this->platform); + $this->type->convertToDatabaseValue(new \stdClass(), new SqlitePlatform()); } public function testNullConversionForDatabaseValue() { - $this->assertNull($this->type->convertToDatabaseValue(null, $this->platform)); + $this->assertNull($this->type->convertToDatabaseValue(null, new SqlitePlatform())); } public function testUlidInterfaceConvertsToPHPValue() { $ulid = $this->createMock(AbstractUid::class); - $actual = $this->type->convertToPHPValue($ulid, $this->platform); + $actual = $this->type->convertToPHPValue($ulid, new SqlitePlatform()); $this->assertSame($ulid, $actual); } public function testUlidConvertsToPHPValue() { - $ulid = $this->type->convertToPHPValue(self::DUMMY_ULID, $this->platform); + $ulid = $this->type->convertToPHPValue(self::DUMMY_ULID, new SqlitePlatform()); $this->assertInstanceOf(Ulid::class, $ulid); $this->assertEquals(self::DUMMY_ULID, $ulid->__toString()); @@ -117,19 +112,19 @@ public function testInvalidUlidConversionForPHPValue() { $this->expectException(ConversionException::class); - $this->type->convertToPHPValue('abcdefg', $this->platform); + $this->type->convertToPHPValue('abcdefg', new SqlitePlatform()); } public function testNullConversionForPHPValue() { - $this->assertNull($this->type->convertToPHPValue(null, $this->platform)); + $this->assertNull($this->type->convertToPHPValue(null, new SqlitePlatform())); } public function testReturnValueIfUlidForPHPValue() { $ulid = new Ulid(); - $this->assertSame($ulid, $this->type->convertToPHPValue($ulid, $this->platform)); + $this->assertSame($ulid, $this->type->convertToPHPValue($ulid, new SqlitePlatform())); } public function testGetName() @@ -137,13 +132,25 @@ public function testGetName() $this->assertEquals('ulid', $this->type->getName()); } - public function testGetGuidTypeDeclarationSQL() + /** + * @dataProvider provideSqlDeclarations + */ + public function testGetGuidTypeDeclarationSQL(AbstractPlatform $platform, string $expectedDeclaration) + { + $this->assertEquals($expectedDeclaration, $this->type->getSqlDeclaration(['length' => 36], $platform)); + } + + public function provideSqlDeclarations(): array { - $this->assertEquals('DUMMYVARCHAR()', $this->type->getSqlDeclaration(['length' => 36], $this->platform)); + return [ + [new PostgreSQLPlatform(), 'UUID'], + [new SqlitePlatform(), 'BLOB'], + [new MySQLPlatform(), 'BINARY(16)'], + ]; } public function testRequiresSQLCommentHint() { - $this->assertTrue($this->type->requiresSQLCommentHint($this->platform)); + $this->assertTrue($this->type->requiresSQLCommentHint(new SqlitePlatform())); } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php index d6bf714627a1d..9b904b89d9d62 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php @@ -12,6 +12,9 @@ namespace Symfony\Bridge\Doctrine\Tests\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use PHPUnit\Framework\TestCase; @@ -19,13 +22,14 @@ use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Uuid; +// DBAL 2 compatibility +class_exists('Doctrine\DBAL\Platforms\MySqlPlatform'); +class_exists('Doctrine\DBAL\Platforms\PostgreSqlPlatform'); + final class UuidTypeTest extends TestCase { private const DUMMY_UUID = '9f755235-5a2d-4aba-9605-e9962b312e50'; - /** @var AbstractPlatform */ - private $platform; - /** @var UuidType */ private $type; @@ -40,14 +44,6 @@ public static function setUpBeforeClass(): void protected function setUp(): void { - $this->platform = $this->createMock(AbstractPlatform::class); - $this->platform - ->method('hasNativeGuidType') - ->willReturn(true); - $this->platform - ->method('getGuidTypeDeclarationSQL') - ->willReturn('DUMMYVARCHAR()'); - $this->type = Type::getType('uuid'); } @@ -56,12 +52,12 @@ public function testUuidConvertsToDatabaseValue() $uuid = Uuid::fromString(self::DUMMY_UUID); $expected = $uuid->__toString(); - $actual = $this->type->convertToDatabaseValue($uuid, $this->platform); + $actual = $this->type->convertToDatabaseValue($uuid, new PostgreSQLPlatform()); $this->assertEquals($expected, $actual); } - public function testUuidInterfaceConvertsToDatabaseValue() + public function testUuidInterfaceConvertsToNativeUidDatabaseValue() { $uuid = $this->createMock(AbstractUid::class); @@ -70,14 +66,28 @@ public function testUuidInterfaceConvertsToDatabaseValue() ->method('toRfc4122') ->willReturn('foo'); - $actual = $this->type->convertToDatabaseValue($uuid, $this->platform); + $actual = $this->type->convertToDatabaseValue($uuid, new PostgreSQLPlatform()); + + $this->assertEquals('foo', $actual); + } + + public function testUuidInterfaceConvertsToBinaryDatabaseValue() + { + $uuid = $this->createMock(AbstractUid::class); + + $uuid + ->expects($this->once()) + ->method('toBinary') + ->willReturn('foo'); + + $actual = $this->type->convertToDatabaseValue($uuid, new MySQLPlatform()); $this->assertEquals('foo', $actual); } public function testUuidStringConvertsToDatabaseValue() { - $actual = $this->type->convertToDatabaseValue(self::DUMMY_UUID, $this->platform); + $actual = $this->type->convertToDatabaseValue(self::DUMMY_UUID, new PostgreSQLPlatform()); $this->assertEquals(self::DUMMY_UUID, $actual); } @@ -86,25 +96,25 @@ public function testNotSupportedTypeConversionForDatabaseValue() { $this->expectException(ConversionException::class); - $this->type->convertToDatabaseValue(new \stdClass(), $this->platform); + $this->type->convertToDatabaseValue(new \stdClass(), new SqlitePlatform()); } public function testNullConversionForDatabaseValue() { - $this->assertNull($this->type->convertToDatabaseValue(null, $this->platform)); + $this->assertNull($this->type->convertToDatabaseValue(null, new SqlitePlatform())); } public function testUuidInterfaceConvertsToPHPValue() { $uuid = $this->createMock(AbstractUid::class); - $actual = $this->type->convertToPHPValue($uuid, $this->platform); + $actual = $this->type->convertToPHPValue($uuid, new SqlitePlatform()); $this->assertSame($uuid, $actual); } public function testUuidConvertsToPHPValue() { - $uuid = $this->type->convertToPHPValue(self::DUMMY_UUID, $this->platform); + $uuid = $this->type->convertToPHPValue(self::DUMMY_UUID, new SqlitePlatform()); $this->assertInstanceOf(Uuid::class, $uuid); $this->assertEquals(self::DUMMY_UUID, $uuid->__toString()); @@ -114,19 +124,19 @@ public function testInvalidUuidConversionForPHPValue() { $this->expectException(ConversionException::class); - $this->type->convertToPHPValue('abcdefg', $this->platform); + $this->type->convertToPHPValue('abcdefg', new SqlitePlatform()); } public function testNullConversionForPHPValue() { - $this->assertNull($this->type->convertToPHPValue(null, $this->platform)); + $this->assertNull($this->type->convertToPHPValue(null, new SqlitePlatform())); } public function testReturnValueIfUuidForPHPValue() { $uuid = Uuid::v4(); - $this->assertSame($uuid, $this->type->convertToPHPValue($uuid, $this->platform)); + $this->assertSame($uuid, $this->type->convertToPHPValue($uuid, new SqlitePlatform())); } public function testGetName() @@ -134,13 +144,25 @@ public function testGetName() $this->assertEquals('uuid', $this->type->getName()); } - public function testGetGuidTypeDeclarationSQL() + /** + * @dataProvider provideSqlDeclarations + */ + public function testGetGuidTypeDeclarationSQL(AbstractPlatform $platform, string $expectedDeclaration) + { + $this->assertEquals($expectedDeclaration, $this->type->getSqlDeclaration(['length' => 36], $platform)); + } + + public function provideSqlDeclarations(): array { - $this->assertEquals('DUMMYVARCHAR()', $this->type->getSqlDeclaration(['length' => 36], $this->platform)); + return [ + [new PostgreSQLPlatform(), 'UUID'], + [new SqlitePlatform(), 'BLOB'], + [new MySQLPlatform(), 'BINARY(16)'], + ]; } public function testRequiresSQLCommentHint() { - $this->assertTrue($this->type->requiresSQLCommentHint($this->platform)); + $this->assertTrue($this->type->requiresSQLCommentHint(new SqlitePlatform())); } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 37155c1fe4532..240e2eb976194 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -13,9 +13,9 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectRepository; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; @@ -111,7 +111,7 @@ protected function createEntityManagerMock($repositoryMock) ->willReturn($repositoryMock) ; - $classMetadata = $this->createMock(ClassMetadata::class); + $classMetadata = $this->createMock(ClassMetadataInfo::class); $classMetadata ->expects($this->any()) ->method('hasField') diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 0bb9591e185df..23c7e758505a5 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -27,7 +27,6 @@ use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Loader\AutoMappingTrait; use Symfony\Component\Validator\Mapping\PropertyMetadata; use Symfony\Component\Validator\Mapping\TraversalStrategy; use Symfony\Component\Validator\Tests\Fixtures\Entity; @@ -38,13 +37,6 @@ */ class DoctrineLoaderTest extends TestCase { - protected function setUp(): void - { - if (!trait_exists(AutoMappingTrait::class)) { - $this->markTestSkipped('Auto-mapping requires symfony/validation 4.4+'); - } - } - public function testLoadClassMetadata() { $validator = Validation::createValidatorBuilder() @@ -151,9 +143,6 @@ public function testLoadClassMetadata() $this->assertSame(AutoMappingStrategy::DISABLED, $noAutoMappingMetadata[0]->getAutoMappingStrategy()); } - /** - * @requires PHP 8.1 - */ public function testExtractEnum() { if (!property_exists(Column::class, 'enumType')) { @@ -162,7 +151,8 @@ public function testExtractEnum() $validator = Validation::createValidatorBuilder() ->addMethodMapping('loadValidatorMetadata') - ->enableAnnotationMapping() + ->enableAnnotationMapping(true) + ->addDefaultDoctrineAnnotationReader() ->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{^Symfony\\\\Bridge\\\\Doctrine\\\\Tests\\\\Fixtures\\\\DoctrineLoader}')) ->getValidator() ; diff --git a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php index 54f6d01ee4ea2..48f69eee850a6 100644 --- a/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php +++ b/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php @@ -18,6 +18,9 @@ abstract class AbstractUidType extends Type { + /** + * @return class-string + */ abstract protected function getUidClass(): string; /** @@ -25,7 +28,7 @@ abstract protected function getUidClass(): string; */ public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { - if ($platform->hasNativeGuidType()) { + if ($this->hasNativeGuidType($platform)) { return $platform->getGuidTypeDeclarationSQL($column); } @@ -64,7 +67,7 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Ab */ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string { - $toString = $platform->hasNativeGuidType() ? 'toRfc4122' : 'toBinary'; + $toString = $this->hasNativeGuidType($platform) ? 'toRfc4122' : 'toBinary'; if ($value instanceof AbstractUid) { return $value->$toString(); @@ -80,7 +83,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?str try { return $this->getUidClass()::fromString($value)->$toString(); - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { throw ConversionException::conversionFailed($value, $this->getName()); } } @@ -92,4 +95,14 @@ public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; } + + private function hasNativeGuidType(AbstractPlatform $platform): bool + { + // Compatibility with DBAL < 3.4 + $method = method_exists($platform, 'getStringTypeDeclarationSQL') + ? 'getStringTypeDeclarationSQL' + : 'getVarcharTypeDeclarationSQL'; + + return $platform->getGuidTypeDeclarationSQL([]) !== $platform->$method(['fixed' => true, 'length' => 36]); + } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php index 966d5c8af6dc7..45758d74b8685 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php +++ b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php @@ -50,7 +50,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool $className = $metadata->getClassName(); try { $doctrineMetadata = $this->entityManager->getClassMetadata($className); - } catch (MappingException|OrmMappingException $exception) { + } catch (MappingException|OrmMappingException) { return false; } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index d482efec66af8..3ded2fb48581c 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -16,9 +16,9 @@ } ], "require": { - "php": ">=8.0.2", - "doctrine/event-manager": "~1.0", - "doctrine/persistence": "^2", + "php": ">=8.1", + "doctrine/event-manager": "^1|^2", + "doctrine/persistence": "^2|^3", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", @@ -29,7 +29,7 @@ "symfony/cache": "^5.4|^6.0", "symfony/config": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", + "symfony/form": "^5.4.9|^6.0.9", "symfony/http-kernel": "^5.4|^6.0", "symfony/messenger": "^5.4|^6.0", "symfony/doctrine-messenger": "^5.4|^6.0", @@ -42,8 +42,8 @@ "symfony/validator": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0", - "doctrine/annotations": "^1.10.4", - "doctrine/collections": "~1.0", + "doctrine/annotations": "^1.10.4|^2", + "doctrine/collections": "^1.0|^2.0", "doctrine/data-fixtures": "^1.1", "doctrine/dbal": "^2.13.1|^3.0", "doctrine/orm": "^2.7.4", diff --git a/src/Symfony/Bridge/Doctrine/phpunit.xml.dist b/src/Symfony/Bridge/Doctrine/phpunit.xml.dist index 34c19c68c319d..f99086654ecab 100644 --- a/src/Symfony/Bridge/Doctrine/phpunit.xml.dist +++ b/src/Symfony/Bridge/Doctrine/phpunit.xml.dist @@ -28,4 +28,14 @@ ./vendor + + + + + + Symfony\Bridge\Doctrine\Middleware\Debug + + + + diff --git a/src/Symfony/Bridge/Monolog/CHANGELOG.md b/src/Symfony/Bridge/Monolog/CHANGELOG.md index 14c0e5882d015..0da84bd616c93 100644 --- a/src/Symfony/Bridge/Monolog/CHANGELOG.md +++ b/src/Symfony/Bridge/Monolog/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.1 +--- + + * Add support for Monolog 3 + 6.0 --- diff --git a/src/Symfony/Bridge/Monolog/Formatter/CompatibilityFormatter.php b/src/Symfony/Bridge/Monolog/Formatter/CompatibilityFormatter.php new file mode 100644 index 0000000000000..08cd70983b3ba --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Formatter/CompatibilityFormatter.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Formatter; + +use Monolog\Logger; +use Monolog\LogRecord; + +if (Logger::API >= 3) { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityFormatter + { + abstract private function doFormat(array|LogRecord $record): mixed; + + /** + * {@inheritdoc} + */ + public function format(LogRecord $record): mixed + { + return $this->doFormat($record); + } + } +} else { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityFormatter + { + abstract private function doFormat(array|LogRecord $record): mixed; + + /** + * {@inheritdoc} + */ + public function format(array $record): mixed + { + return $this->doFormat($record); + } + } +} diff --git a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php index 5778dbb3b37c0..b8ed640e9c4aa 100644 --- a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php +++ b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php @@ -13,6 +13,7 @@ use Monolog\Formatter\FormatterInterface; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; @@ -24,9 +25,13 @@ * * @author Tobias Schultze * @author Grégoire Pineau + * + * @final since Symfony 6.1 */ class ConsoleFormatter implements FormatterInterface { + use CompatibilityFormatter; + public const SIMPLE_FORMAT = "%datetime% %start_tag%%level_name%%end_tag% [%channel%] %message%%context%%extra%\n"; public const SIMPLE_DATE = 'H:i:s'; @@ -72,14 +77,14 @@ public function __construct(array $options = []) if (class_exists(VarCloner::class)) { $this->cloner = new VarCloner(); $this->cloner->addCasters([ - '*' => [$this, 'castObject'], + '*' => $this->castObject(...), ]); $this->outputBuffer = fopen('php://memory', 'r+'); if ($this->options['multiline']) { $output = $this->outputBuffer; } else { - $output = [$this, 'echoLine']; + $output = $this->echoLine(...); } $this->dumper = new CliDumper($output, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); @@ -98,11 +103,11 @@ public function formatBatch(array $records): mixed return $records; } - /** - * {@inheritdoc} - */ - public function format(array $record): mixed + private function doFormat(array|LogRecord $record): mixed { + if ($record instanceof LogRecord) { + $record = $record->toArray(); + } $record = $this->replacePlaceHolder($record); if (!$this->options['ignore_empty_context_and_extra'] || !empty($record['context'])) { diff --git a/src/Symfony/Bridge/Monolog/Formatter/VarDumperFormatter.php b/src/Symfony/Bridge/Monolog/Formatter/VarDumperFormatter.php index e745afec13650..92cf6c3e887b4 100644 --- a/src/Symfony/Bridge/Monolog/Formatter/VarDumperFormatter.php +++ b/src/Symfony/Bridge/Monolog/Formatter/VarDumperFormatter.php @@ -12,13 +12,18 @@ namespace Symfony\Bridge\Monolog\Formatter; use Monolog\Formatter\FormatterInterface; +use Monolog\LogRecord; use Symfony\Component\VarDumper\Cloner\VarCloner; /** * @author Grégoire Pineau + * + * @final since Symfony 6.1 */ class VarDumperFormatter implements FormatterInterface { + use CompatibilityFormatter; + private VarCloner $cloner; public function __construct(VarCloner $cloner = null) @@ -26,11 +31,12 @@ public function __construct(VarCloner $cloner = null) $this->cloner = $cloner ?? new VarCloner(); } - /** - * {@inheritdoc} - */ - public function format(array $record): mixed + private function doFormat(array|LogRecord $record): mixed { + if ($record instanceof LogRecord) { + $record = $record->toArray(); + } + $record['context'] = $this->cloner->cloneVar($record['context']); $record['extra'] = $this->cloner->cloneVar($record['extra']); diff --git a/src/Symfony/Bridge/Monolog/Handler/CompatibilityHandler.php b/src/Symfony/Bridge/Monolog/Handler/CompatibilityHandler.php new file mode 100644 index 0000000000000..dbeb59e4feb3b --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Handler/CompatibilityHandler.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Handler; + +use Monolog\Logger; +use Monolog\LogRecord; + +if (Logger::API >= 3) { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityHandler + { + abstract private function doHandle(array|LogRecord $record): bool; + + /** + * {@inheritdoc} + */ + public function handle(LogRecord $record): bool + { + return $this->doHandle($record); + } + } +} else { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityHandler + { + abstract private function doHandle(array|LogRecord $record): bool; + + /** + * {@inheritdoc} + */ + public function handle(array $record): bool + { + return $this->doHandle($record); + } + } +} diff --git a/src/Symfony/Bridge/Monolog/Handler/CompatibilityProcessingHandler.php b/src/Symfony/Bridge/Monolog/Handler/CompatibilityProcessingHandler.php new file mode 100644 index 0000000000000..c84c457859d52 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Handler/CompatibilityProcessingHandler.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Handler; + +use Monolog\Logger; +use Monolog\LogRecord; + +if (Logger::API >= 3) { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityProcessingHandler + { + abstract private function doWrite(array|LogRecord $record): void; + + /** + * {@inheritdoc} + */ + protected function write(LogRecord $record): void + { + $this->doWrite($record); + } + } +} else { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityProcessingHandler + { + abstract private function doWrite(array|LogRecord $record): void; + + /** + * {@inheritdoc} + */ + protected function write(array $record): void + { + $this->doWrite($record); + } + } +} diff --git a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php index 3c911f3cfa91d..88936ff2bfbd8 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php @@ -15,6 +15,7 @@ use Monolog\Formatter\LineFormatter; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleCommandEvent; @@ -24,6 +25,48 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\VarDumper\Dumper\CliDumper; +if (Logger::API >= 3) { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityIsHandlingHandler + { + abstract private function doIsHandling(array|LogRecord $record): bool; + + /** + * {@inheritdoc} + */ + public function isHandling(LogRecord $record): bool + { + return $this->doIsHandling($record); + } + } +} else { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityIsHandlingHandler + { + abstract private function doIsHandling(array|LogRecord $record): bool; + + /** + * {@inheritdoc} + */ + public function isHandling(array $record): bool + { + return $this->doIsHandling($record); + } + } +} + /** * Writes logs to the console output depending on its verbosity setting. * @@ -40,9 +83,15 @@ * This mapping can be customized with the $verbosityLevelMap constructor parameter. * * @author Tobias Schultze + * + * @final since Symfony 6.1 */ class ConsoleHandler extends AbstractProcessingHandler implements EventSubscriberInterface { + use CompatibilityHandler; + use CompatibilityIsHandlingHandler; + use CompatibilityProcessingHandler; + private ?OutputInterface $output; private array $verbosityLevelMap = [ OutputInterface::VERBOSITY_QUIET => Logger::ERROR, @@ -75,7 +124,7 @@ public function __construct(OutputInterface $output = null, bool $bubble = true, /** * {@inheritdoc} */ - public function isHandling(array $record): bool + private function doIsHandling(array|LogRecord $record): bool { return $this->updateLevel() && parent::isHandling($record); } @@ -83,7 +132,7 @@ public function isHandling(array $record): bool /** * {@inheritdoc} */ - public function handle(array $record): bool + private function doHandle(array|LogRecord $record): bool { // we have to update the logging level each time because the verbosity of the // console output might have changed in the meantime (it is not immutable) @@ -141,10 +190,7 @@ public static function getSubscribedEvents(): array ]; } - /** - * {@inheritdoc} - */ - protected function write(array $record): void + private function doWrite(array|LogRecord $record): void { // at this point we've determined for sure that we want to output the record, so use the output's own verbosity $this->output->write((string) $record['formatted'], false, $this->output->getVerbosity()); diff --git a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php index 65486f6b9d444..064a0fca43a21 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php @@ -16,7 +16,9 @@ use Monolog\Handler\AbstractHandler; use Monolog\Handler\FormattableHandlerTrait; use Monolog\Handler\ProcessableHandlerTrait; +use Monolog\Level; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Component\HttpClient\HttpClient; use Symfony\Contracts\HttpClient\Exception\ExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -39,22 +41,27 @@ * stack is recommended. * * @author Grégoire Pineau + * + * @final since Symfony 6.1 */ class ElasticsearchLogstashHandler extends AbstractHandler { + use CompatibilityHandler; + use FormattableHandlerTrait; use ProcessableHandlerTrait; private string $endpoint; private string $index; private HttpClientInterface $client; + private string $elasticsearchVersion; /** * @var \SplObjectStorage */ private \SplObjectStorage $responses; - public function __construct(string $endpoint = 'http://127.0.0.1:9200', string $index = 'monolog', HttpClientInterface $client = null, string|int $level = Logger::DEBUG, bool $bubble = true) + public function __construct(string $endpoint = 'http://127.0.0.1:9200', string $index = 'monolog', HttpClientInterface $client = null, string|int|Level $level = Logger::DEBUG, bool $bubble = true, string $elasticsearchVersion = '1.0.0') { if (!interface_exists(HttpClientInterface::class)) { throw new \LogicException(sprintf('The "%s" handler needs an HTTP client. Try running "composer require symfony/http-client".', __CLASS__)); @@ -65,9 +72,10 @@ public function __construct(string $endpoint = 'http://127.0.0.1:9200', string $ $this->index = $index; $this->client = $client ?: HttpClient::create(['timeout' => 1]); $this->responses = new \SplObjectStorage(); + $this->elasticsearchVersion = $elasticsearchVersion; } - public function handle(array $record): bool + private function doHandle(array|LogRecord $record): bool { if (!$this->isHandling($record)) { return false; @@ -80,7 +88,7 @@ public function handle(array $record): bool public function handleBatch(array $records): void { - $records = array_filter($records, [$this, 'isHandling']); + $records = array_filter($records, $this->isHandling(...)); if ($records) { $this->sendToElasticsearch($records); @@ -102,18 +110,28 @@ private function sendToElasticsearch(array $records) { $formatter = $this->getFormatter(); + if (version_compare($this->elasticsearchVersion, '7', '>=')) { + $headers = json_encode([ + 'index' => [ + '_index' => $this->index, + ], + ]); + } else { + $headers = json_encode([ + 'index' => [ + '_index' => $this->index, + '_type' => '_doc', + ], + ]); + } + $body = ''; foreach ($records as $record) { foreach ($this->processors as $processor) { $record = $processor($record); } - $body .= json_encode([ - 'index' => [ - '_index' => $this->index, - '_type' => '_doc', - ], - ]); + $body .= $headers; $body .= "\n"; $body .= $formatter->format($record); $body .= "\n"; diff --git a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php index fc78f2dc32c49..da48f08933289 100644 --- a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php +++ b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Monolog\Handler\FingersCrossed; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; +use Monolog\LogRecord; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -41,7 +42,7 @@ public function __construct( } } - public function isHandlerActivated(array $record): bool + public function isHandlerActivated(array|LogRecord $record): bool { $isActivated = $this->inner->isHandlerActivated($record); diff --git a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php index 808d863cec663..b825ef81164f9 100644 --- a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php +++ b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Monolog\Handler\FingersCrossed; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; +use Monolog\LogRecord; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -34,7 +35,7 @@ public function __construct( $this->exclude = '{('.implode('|', $excludedUrls).')}i'; } - public function isHandlerActivated(array $record): bool + public function isHandlerActivated(array|LogRecord $record): bool { $isActivated = $this->inner->isHandlerActivated($record); diff --git a/src/Symfony/Bridge/Monolog/Handler/FirePHPHandler.php b/src/Symfony/Bridge/Monolog/Handler/FirePHPHandler.php index b06f3244e73b8..d60b02a287558 100644 --- a/src/Symfony/Bridge/Monolog/Handler/FirePHPHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/FirePHPHandler.php @@ -25,7 +25,7 @@ class FirePHPHandler extends BaseFirePHPHandler { private array $headers = []; - private Response $response; + private ?Response $response = null; /** * Adds the headers to the response once it's created. @@ -61,7 +61,7 @@ protected function sendHeader($header, $content): void return; } - if ($this->response) { + if (null !== $this->response) { $this->response->headers->set($header, $content); } else { $this->headers[$header] = $content; diff --git a/src/Symfony/Bridge/Monolog/Handler/MailerHandler.php b/src/Symfony/Bridge/Monolog/Handler/MailerHandler.php index a7610f337be2a..b75accae76a84 100644 --- a/src/Symfony/Bridge/Monolog/Handler/MailerHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/MailerHandler.php @@ -15,24 +15,30 @@ use Monolog\Formatter\HtmlFormatter; use Monolog\Formatter\LineFormatter; use Monolog\Handler\AbstractProcessingHandler; +use Monolog\Level; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mime\Email; /** * @author Alexander Borisov + * + * @final since Symfony 6.1 */ class MailerHandler extends AbstractProcessingHandler { + use CompatibilityProcessingHandler; + private MailerInterface $mailer; private \Closure|Email $messageTemplate; - public function __construct(MailerInterface $mailer, callable|Email $messageTemplate, string|int $level = Logger::DEBUG, bool $bubble = true) + public function __construct(MailerInterface $mailer, callable|Email $messageTemplate, string|int|Level $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->mailer = $mailer; - $this->messageTemplate = !\is_callable($messageTemplate) || $messageTemplate instanceof \Closure ? $messageTemplate : \Closure::fromCallable($messageTemplate); + $this->messageTemplate = $messageTemplate instanceof Email ? $messageTemplate : $messageTemplate(...); } /** @@ -42,11 +48,21 @@ public function handleBatch(array $records): void { $messages = []; - foreach ($records as $record) { - if ($record['level'] < $this->level) { - continue; + if (Logger::API >= 3) { + /** @var LogRecord $record */ + foreach ($records as $record) { + if ($record->level->isLowerThan($this->level)) { + continue; + } + $messages[] = $this->processRecord($record); + } + } else { + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + $messages[] = $this->processRecord($record); } - $messages[] = $this->processRecord($record); } if (!empty($messages)) { @@ -57,7 +73,7 @@ public function handleBatch(array $records): void /** * {@inheritdoc} */ - protected function write(array $record): void + private function doWrite(array|LogRecord $record): void { $this->send((string) $record['formatted'], [$record]); } @@ -125,7 +141,7 @@ protected function buildMessage(string $content, array $records): Email return $message; } - protected function getHighestRecord(array $records): array + protected function getHighestRecord(array $records): array|LogRecord { $highestRecord = null; foreach ($records as $record) { diff --git a/src/Symfony/Bridge/Monolog/Handler/NotifierHandler.php b/src/Symfony/Bridge/Monolog/Handler/NotifierHandler.php index 9355ee23457f5..8576706080d44 100644 --- a/src/Symfony/Bridge/Monolog/Handler/NotifierHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/NotifierHandler.php @@ -12,7 +12,9 @@ namespace Symfony\Bridge\Monolog\Handler; use Monolog\Handler\AbstractHandler; +use Monolog\Level; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Component\Notifier\Notification\Notification; use Symfony\Component\Notifier\Notifier; use Symfony\Component\Notifier\NotifierInterface; @@ -21,19 +23,23 @@ * Uses Notifier as a log handler. * * @author Fabien Potencier + * + * @final since Symfony 6.1 */ class NotifierHandler extends AbstractHandler { + use CompatibilityHandler; + private NotifierInterface $notifier; - public function __construct(NotifierInterface $notifier, string|int $level = Logger::ERROR, bool $bubble = true) + public function __construct(NotifierInterface $notifier, string|int|Level $level = Logger::ERROR, bool $bubble = true) { $this->notifier = $notifier; parent::__construct(Logger::toMonologLevel($level) < Logger::ERROR ? Logger::ERROR : $level, $bubble); } - public function handle(array $record): bool + private function doHandle(array|LogRecord $record): bool { if (!$this->isHandling($record)) { return false; @@ -46,7 +52,7 @@ public function handle(array $record): bool public function handleBatch(array $records): void { - if ($records = array_filter($records, [$this, 'isHandling'])) { + if ($records = array_filter($records, $this->isHandling(...))) { $this->notify($records); } } diff --git a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php index b14d8e241cf13..3b2319fb5812a 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php @@ -14,12 +14,19 @@ use Monolog\Formatter\FormatterInterface; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Handler\FormattableHandlerTrait; +use Monolog\Level; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Bridge\Monolog\Formatter\VarDumperFormatter; if (trait_exists(FormattableHandlerTrait::class)) { + /** + * @final since Symfony 6.1 + */ class ServerLogHandler extends AbstractProcessingHandler { + use CompatibilityHandler; + use CompatibilityProcessingHandler; use ServerLogHandlerTrait; /** @@ -31,8 +38,13 @@ protected function getDefaultFormatter(): FormatterInterface } } } else { + /** + * @final since Symfony 6.1 + */ class ServerLogHandler extends AbstractProcessingHandler { + use CompatibilityHandler; + use CompatibilityProcessingHandler; use ServerLogHandlerTrait; /** @@ -47,6 +59,8 @@ protected function getDefaultFormatter() /** * @author Grégoire Pineau + * + * @internal since Symfony 6.1 */ trait ServerLogHandlerTrait { @@ -62,7 +76,7 @@ trait ServerLogHandlerTrait */ private $socket; - public function __construct(string $host, string|int $level = Logger::DEBUG, bool $bubble = true, array $context = []) + public function __construct(string $host, string|int|Level $level = Logger::DEBUG, bool $bubble = true, array $context = []) { parent::__construct($level, $bubble); @@ -74,10 +88,7 @@ public function __construct(string $host, string|int $level = Logger::DEBUG, boo $this->context = stream_context_create($context); } - /** - * {@inheritdoc} - */ - public function handle(array $record): bool + private function doHandle(array|LogRecord $record): bool { if (!$this->isHandling($record)) { return false; @@ -96,7 +107,7 @@ public function handle(array $record): bool return parent::handle($record); } - protected function write(array $record): void + private function doWrite(array|LogRecord $record): void { $recordFormatted = $this->formatRecord($record); @@ -139,7 +150,7 @@ private function createSocket() return $socket; } - private function formatRecord(array $record): string + private function formatRecord(array|LogRecord $record): string { $recordFormatted = $record['formatted']; diff --git a/src/Symfony/Bridge/Monolog/LICENSE b/src/Symfony/Bridge/Monolog/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bridge/Monolog/LICENSE +++ b/src/Symfony/Bridge/Monolog/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php index f98969700bcab..c455be29a33ec 100644 --- a/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/AbstractTokenProcessor.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Monolog\Processor; +use Monolog\LogRecord; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; @@ -19,9 +20,13 @@ * * @author Dany Maillard * @author Igor Timoshenko + * + * @internal since Symfony 6.1 */ abstract class AbstractTokenProcessor { + use CompatibilityProcessor; + /** * @var TokenStorageInterface */ @@ -36,7 +41,7 @@ abstract protected function getKey(): string; abstract protected function getToken(): ?TokenInterface; - public function __invoke(array $record): array + private function doInvoke(array|LogRecord $record): array|LogRecord { $record['extra'][$this->getKey()] = null; diff --git a/src/Symfony/Bridge/Monolog/Processor/CompatibilityProcessor.php b/src/Symfony/Bridge/Monolog/Processor/CompatibilityProcessor.php new file mode 100644 index 0000000000000..2f337b29febcf --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Processor/CompatibilityProcessor.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Processor; + +use Monolog\Logger; +use Monolog\LogRecord; + +if (Logger::API >= 3) { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityProcessor + { + abstract private function doInvoke(array|LogRecord $record): array|LogRecord; + + public function __invoke(LogRecord $record): LogRecord + { + return $this->doInvoke($record); + } + } +} else { + /** + * The base class for compatibility between Monolog 3 LogRecord and Monolog 1/2 array records. + * + * @author Jordi Boggiano + * + * @internal + */ + trait CompatibilityProcessor + { + abstract private function doInvoke(array|LogRecord $record): array|LogRecord; + + public function __invoke(array $record): array + { + return $this->doInvoke($record); + } + } +} diff --git a/src/Symfony/Bridge/Monolog/Processor/ConsoleCommandProcessor.php b/src/Symfony/Bridge/Monolog/Processor/ConsoleCommandProcessor.php index a1e1c144379ba..a5b26eacbae83 100644 --- a/src/Symfony/Bridge/Monolog/Processor/ConsoleCommandProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/ConsoleCommandProcessor.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Monolog\Processor; +use Monolog\LogRecord; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -20,9 +21,13 @@ * Adds the current console command information to the log entry. * * @author Piotr Stankowski + * + * @final since Symfony 6.1 */ class ConsoleCommandProcessor implements EventSubscriberInterface, ResetInterface { + use CompatibilityProcessor; + private array $commandData; private bool $includeArguments; private bool $includeOptions; @@ -33,13 +38,13 @@ public function __construct(bool $includeArguments = true, bool $includeOptions $this->includeOptions = $includeOptions; } - public function __invoke(array $records) + private function doInvoke(array|LogRecord $record): array|LogRecord { - if (isset($this->commandData) && !isset($records['extra']['command'])) { - $records['extra']['command'] = $this->commandData; + if (isset($this->commandData) && !isset($record['extra']['command'])) { + $record['extra']['command'] = $this->commandData; } - return $records; + return $record; } public function reset() diff --git a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php index bca5b948c6b9b..a033d73c3b187 100644 --- a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Monolog\Processor; use Monolog\Logger; +use Monolog\LogRecord; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; @@ -19,6 +20,8 @@ class DebugProcessor implements DebugLoggerInterface, ResetInterface { + use CompatibilityProcessor; + private array $records = []; private array $errorCount = []; private ?RequestStack $requestStack; @@ -28,7 +31,7 @@ public function __construct(RequestStack $requestStack = null) $this->requestStack = $requestStack; } - public function __invoke(array $record) + private function doInvoke(array|LogRecord $record): array|LogRecord { $hash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; diff --git a/src/Symfony/Bridge/Monolog/Processor/RouteProcessor.php b/src/Symfony/Bridge/Monolog/Processor/RouteProcessor.php index 0bb738f378532..c9f28af084068 100644 --- a/src/Symfony/Bridge/Monolog/Processor/RouteProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/RouteProcessor.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Monolog\Processor; +use Monolog\LogRecord; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; @@ -35,13 +36,13 @@ public function __construct(bool $includeParams = true) $this->reset(); } - public function __invoke(array $records): array + public function __invoke(array|LogRecord $record): array|LogRecord { - if ($this->routeData && !isset($records['extra']['requests'])) { - $records['extra']['requests'] = array_values($this->routeData); + if ($this->routeData && !isset($record['extra']['requests'])) { + $record['extra']['requests'] = array_values($this->routeData); } - return $records; + return $record; } public function reset() diff --git a/src/Symfony/Bridge/Monolog/Processor/SwitchUserTokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/SwitchUserTokenProcessor.php index 76aa7e479d0e5..bb3f6ff73d0cd 100644 --- a/src/Symfony/Bridge/Monolog/Processor/SwitchUserTokenProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/SwitchUserTokenProcessor.php @@ -18,6 +18,8 @@ * Adds the original security token to the log entry. * * @author Igor Timoshenko + * + * @final since Symfony 6.1 */ class SwitchUserTokenProcessor extends AbstractTokenProcessor { diff --git a/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php index 7ca212eb29770..c824ea1761efd 100644 --- a/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php @@ -18,6 +18,8 @@ * * @author Dany Maillard * @author Igor Timoshenko + * + * @final since Symfony 6.1 */ class TokenProcessor extends AbstractTokenProcessor { diff --git a/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php b/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php index 89d5bee454548..8e847c522642e 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php @@ -12,15 +12,17 @@ namespace Symfony\Bridge\Monolog\Tests\Formatter; use Monolog\Logger; +use Monolog\LogRecord; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; +use Symfony\Bridge\Monolog\Tests\RecordFactory; class ConsoleFormatterTest extends TestCase { /** * @dataProvider providerFormatTests */ - public function testFormat(array $record, $expectedMessage) + public function testFormat(array|LogRecord $record, $expectedMessage) { $formatter = new ConsoleFormatter(); self::assertSame($expectedMessage, $formatter->format($record)); @@ -28,25 +30,20 @@ public function testFormat(array $record, $expectedMessage) public function providerFormatTests(): array { - $currentDateTime = new \DateTime(); + $currentDateTime = new \DateTimeImmutable(); - return [ + $tests = [ 'record with DateTime object in datetime field' => [ - 'record' => [ - 'message' => 'test', - 'context' => [], - 'level' => Logger::WARNING, - 'level_name' => Logger::getLevelName(Logger::WARNING), - 'channel' => 'test', - 'datetime' => $currentDateTime, - 'extra' => [], - ], + 'record' => RecordFactory::create(datetime: $currentDateTime), 'expectedMessage' => sprintf( "%s WARNING [test] test\n", $currentDateTime->format(ConsoleFormatter::SIMPLE_DATE) ), ], - 'record with string in datetime field' => [ + ]; + + if (Logger::API < 3) { + $tests['record with string in datetime field'] = [ 'record' => [ 'message' => 'test', 'context' => [], @@ -57,7 +54,9 @@ public function providerFormatTests(): array 'extra' => [], ], 'expectedMessage' => "2019-01-01T00:42:00+00:00 WARNING [test] test\n", - ], - ]; + ]; + } + + return $tests; } } diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php index d61692ed76466..f7f09c389f8a4 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Bridge\Monolog\Handler\ConsoleHandler; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleCommandEvent; @@ -41,7 +42,7 @@ public function testConstructor() public function testIsHandling() { $handler = new ConsoleHandler(); - $this->assertFalse($handler->isHandling([]), '->isHandling returns false when no output is set'); + $this->assertFalse($handler->isHandling(RecordFactory::create()), '->isHandling returns false when no output is set'); } /** @@ -56,7 +57,7 @@ public function testVerbosityMapping($verbosity, $level, $isHandling, array $map ->willReturn($verbosity) ; $handler = new ConsoleHandler($output, true, $map); - $this->assertSame($isHandling, $handler->isHandling(['level' => $level]), + $this->assertSame($isHandling, $handler->isHandling(RecordFactory::create($level)), '->isHandling returns correct value depending on console verbosity and log level' ); @@ -77,15 +78,7 @@ public function testVerbosityMapping($verbosity, $level, $isHandling, array $map ->with($log, false); $handler = new ConsoleHandler($realOutput, true, $map); - $infoRecord = [ - 'message' => 'My info message', - 'context' => [], - 'level' => $level, - 'level_name' => Logger::getLevelName($level), - 'channel' => 'app', - 'datetime' => new \DateTime('2013-05-29 16:21:54'), - 'extra' => [], - ]; + $infoRecord = RecordFactory::create($level, 'My info message', 'app', datetime: new \DateTimeImmutable('2013-05-29 16:21:54')); $this->assertFalse($handler->handle($infoRecord), 'The handler finished handling the log.'); } @@ -123,10 +116,10 @@ public function testVerbosityChanged() ) ; $handler = new ConsoleHandler($output); - $this->assertFalse($handler->isHandling(['level' => Logger::NOTICE]), + $this->assertFalse($handler->isHandling(RecordFactory::create(Logger::NOTICE)), 'when verbosity is set to quiet, the handler does not handle the log' ); - $this->assertTrue($handler->isHandling(['level' => Logger::NOTICE]), + $this->assertTrue($handler->isHandling(RecordFactory::create(Logger::NOTICE)), 'since the verbosity of the output increased externally, the handler is now handling the log' ); } @@ -157,15 +150,7 @@ public function testWritingAndFormatting() $handler = new ConsoleHandler(null, false); $handler->setOutput($output); - $infoRecord = [ - 'message' => 'My info message', - 'context' => [], - 'level' => Logger::INFO, - 'level_name' => Logger::getLevelName(Logger::INFO), - 'channel' => 'app', - 'datetime' => new \DateTime('2013-05-29 16:21:54'), - 'extra' => [], - ]; + $infoRecord = RecordFactory::create(Logger::INFO, 'My info message', 'app', datetime: new \DateTimeImmutable('2013-05-29 16:21:54')); $this->assertTrue($handler->handle($infoRecord), 'The handler finished handling the log as bubble is false.'); } diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php index 2940f0440ff8f..3e8dde6d4bbda 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php @@ -16,6 +16,7 @@ use Monolog\Logger; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Handler\ElasticsearchLogstashHandler; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; @@ -47,24 +48,53 @@ public function testHandle() return new MockResponse(); }; - $handler = new ElasticsearchLogstashHandlerWithHardCodedHostname('http://es:9200', 'log', new MockHttpClient($responseFactory)); + $handler = new ElasticsearchLogstashHandler('http://es:9200', 'log', new MockHttpClient($responseFactory)); + $handler->setFormatter($this->getDefaultFormatter()); - $record = [ - 'message' => 'My info message', - 'context' => [], - 'level' => Logger::INFO, - 'level_name' => Logger::getLevelName(Logger::INFO), - 'channel' => 'app', - 'datetime' => new \DateTime('2020-01-01T00:00:00+01:00'), - 'extra' => [], - ]; + $record = RecordFactory::create(Logger::INFO, 'My info message', 'app', datetime: new \DateTimeImmutable('2020-01-01T00:00:00+01:00')); + + $handler->handle($record); + + $this->assertSame(1, $callCount); + } + + public function testHandleWithElasticsearch8() + { + $callCount = 0; + $responseFactory = function ($method, $url, $options) use (&$callCount) { + $body = <<assertSame('POST', $method); + $this->assertSame('http://es:9200/_bulk', $url); + $this->assertSame($body, $options['body']); + $this->assertSame('Content-Type: application/json', $options['normalized_headers']['content-type'][0]); + ++$callCount; + + return new MockResponse(); + }; + + $handler = new ElasticsearchLogstashHandler('http://es:9200', 'log', new MockHttpClient($responseFactory), Logger::DEBUG, true, '8.0.0'); + $handler->setFormatter($this->getDefaultFormatter()); + + $record = RecordFactory::create(Logger::INFO, 'My info message', 'app', datetime: new \DateTimeImmutable('2020-01-01T00:00:00+01:00')); $handler->handle($record); $this->assertSame(1, $callCount); } - public function testBandleBatch() + public function testHandleBatch() { $callCount = 0; $responseFactory = function ($method, $url, $options) use (&$callCount) { @@ -93,38 +123,20 @@ public function testBandleBatch() return new MockResponse(); }; - $handler = new ElasticsearchLogstashHandlerWithHardCodedHostname('http://es:9200', 'log', new MockHttpClient($responseFactory)); + $handler = new ElasticsearchLogstashHandler('http://es:9200', 'log', new MockHttpClient($responseFactory)); + $handler->setFormatter($this->getDefaultFormatter()); $records = [ - [ - 'message' => 'My info message', - 'context' => [], - 'level' => Logger::INFO, - 'level_name' => Logger::getLevelName(Logger::INFO), - 'channel' => 'app', - 'datetime' => new \DateTime('2020-01-01T00:00:00+01:00'), - 'extra' => [], - ], - [ - 'message' => 'My second message', - 'context' => [], - 'level' => Logger::WARNING, - 'level_name' => Logger::getLevelName(Logger::WARNING), - 'channel' => 'php', - 'datetime' => new \DateTime('2020-01-01T00:00:01+01:00'), - 'extra' => [], - ], + RecordFactory::create(Logger::INFO, 'My info message', 'app', datetime: new \DateTimeImmutable('2020-01-01T00:00:00+01:00')), + RecordFactory::create(Logger::WARNING, 'My second message', 'php', datetime: new \DateTimeImmutable('2020-01-01T00:00:01+01:00')), ]; $handler->handleBatch($records); $this->assertSame(1, $callCount); } -} -class ElasticsearchLogstashHandlerWithHardCodedHostname extends ElasticsearchLogstashHandler -{ - protected function getDefaultFormatter(): FormatterInterface + private function getDefaultFormatter(): FormatterInterface { // Monolog 1.X if (\defined(LogstashFormatter::class.'::V1')) { diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php index ea6931670d863..a5c877b296681 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php @@ -15,6 +15,7 @@ use Monolog\Logger; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -58,16 +59,16 @@ public function testIsActivated($url, $record, $expected) public function isActivatedProvider(): array { return [ - ['/test', ['level' => Logger::ERROR], true], - ['/400', ['level' => Logger::ERROR, 'context' => $this->getContextException(400)], true], - ['/400/a', ['level' => Logger::ERROR, 'context' => $this->getContextException(400)], false], - ['/400/b', ['level' => Logger::ERROR, 'context' => $this->getContextException(400)], false], - ['/400/c', ['level' => Logger::ERROR, 'context' => $this->getContextException(400)], true], - ['/401', ['level' => Logger::ERROR, 'context' => $this->getContextException(401)], true], - ['/403', ['level' => Logger::ERROR, 'context' => $this->getContextException(403)], false], - ['/404', ['level' => Logger::ERROR, 'context' => $this->getContextException(404)], false], - ['/405', ['level' => Logger::ERROR, 'context' => $this->getContextException(405)], false], - ['/500', ['level' => Logger::ERROR, 'context' => $this->getContextException(500)], true], + ['/test', RecordFactory::create(Logger::ERROR), true], + ['/400', RecordFactory::create(Logger::ERROR, context: self::getContextException(400)), true], + ['/400/a', RecordFactory::create(Logger::ERROR, context: self::getContextException(400)), false], + ['/400/b', RecordFactory::create(Logger::ERROR, context: self::getContextException(400)), false], + ['/400/c', RecordFactory::create(Logger::ERROR, context: self::getContextException(400)), true], + ['/401', RecordFactory::create(Logger::ERROR, context: self::getContextException(401)), true], + ['/403', RecordFactory::create(Logger::ERROR, context: self::getContextException(403)), false], + ['/404', RecordFactory::create(Logger::ERROR, context: self::getContextException(404)), false], + ['/405', RecordFactory::create(Logger::ERROR, context: self::getContextException(405)), false], + ['/500', RecordFactory::create(Logger::ERROR, context: self::getContextException(500)), true], ]; } diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php index 95590186d55f3..220cbe5a78bcd 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php @@ -13,8 +13,10 @@ use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Logger; +use Monolog\LogRecord; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -24,7 +26,7 @@ class NotFoundActivationStrategyTest extends TestCase /** * @dataProvider isActivatedProvider */ - public function testIsActivated(string $url, array $record, bool $expected) + public function testIsActivated(string $url, array|LogRecord $record, bool $expected) { $requestStack = new RequestStack(); $requestStack->push(Request::create($url)); @@ -37,19 +39,19 @@ public function testIsActivated(string $url, array $record, bool $expected) public function isActivatedProvider(): array { return [ - ['/test', ['level' => Logger::DEBUG], false], - ['/foo', ['level' => Logger::DEBUG, 'context' => $this->getContextException(404)], false], - ['/baz/bar', ['level' => Logger::ERROR, 'context' => $this->getContextException(404)], false], - ['/foo', ['level' => Logger::ERROR, 'context' => $this->getContextException(404)], false], - ['/foo', ['level' => Logger::ERROR, 'context' => $this->getContextException(500)], true], - - ['/test', ['level' => Logger::ERROR], true], - ['/baz', ['level' => Logger::ERROR, 'context' => $this->getContextException(404)], true], - ['/baz', ['level' => Logger::ERROR, 'context' => $this->getContextException(500)], true], + ['/test', RecordFactory::create(Logger::DEBUG), false], + ['/foo', RecordFactory::create(Logger::DEBUG, context: self::getContextException(404)), false], + ['/baz/bar', RecordFactory::create(Logger::ERROR, context: self::getContextException(404)), false], + ['/foo', RecordFactory::create(Logger::ERROR, context: self::getContextException(404)), false], + ['/foo', RecordFactory::create(Logger::ERROR, context: self::getContextException(500)), true], + + ['/test', RecordFactory::create(Logger::ERROR), true], + ['/baz', RecordFactory::create(Logger::ERROR, context: self::getContextException(404)), true], + ['/baz', RecordFactory::create(Logger::ERROR, context: self::getContextException(500)), true], ]; } - protected function getContextException(int $code): array + protected static function getContextException(int $code): array { return ['exception' => new HttpException($code)]; } diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FirePHPHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FirePHPHandlerTest.php new file mode 100644 index 0000000000000..70d1915b64f93 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FirePHPHandlerTest.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Tests\Handler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Handler\FirePHPHandler; +use Symfony\Bridge\Monolog\Logger; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; + +class FirePHPHandlerTest extends TestCase +{ + public function testLogHandling() + { + $handler = $this->createHandler(); + $logger = new Logger('my_logger', [$handler]); + + $logger->warning('This does not look right.'); + + $request = new Request(); + $request->headers->set('User-Agent', 'Mozilla/5.0 (FirePHP/1.0)'); + + $response = $this->dispatchResponseEvent($handler, $request); + + $logger->error('Something went wrong.'); + + self::assertSame( + [ + 'x-wf-1-1-1-1' => ['85|[{"Type":"WARN","File":"","Line":"","Label":"my_logger"},"This does not look right."]|'], + 'x-wf-1-1-1-2' => ['82|[{"Type":"ERROR","File":"","Line":"","Label":"my_logger"},"Something went wrong."]|'], + ], + array_filter( + $response->headers->all(), + static fn (string $key): bool => str_starts_with($key, 'x-wf-1-1-1'), + \ARRAY_FILTER_USE_KEY + ) + ); + } + + public function testEmptyLog() + { + $handler = $this->createHandler(); + + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::RESPONSE, $handler->onKernelResponse(...)); + + $request = new Request(); + $request->headers->set('User-Agent', 'Mozilla/5.0 (FirePHP/1.0)'); + + $response = $this->dispatchResponseEvent($handler, $request); + + self::assertSame( + [], + array_filter( + $response->headers->all(), + static fn (string $key): bool => str_starts_with($key, 'x-wf-1-1-1'), + \ARRAY_FILTER_USE_KEY + ) + ); + } + + public function testNoFirePhpClient() + { + $handler = $this->createHandler(); + $logger = new Logger('my_logger', [$handler]); + + $logger->warning('This does not look right.'); + + $request = new Request(); + $request->headers->set('User-Agent', 'Mozilla/5.0'); + + $response = $this->dispatchResponseEvent($handler, $request); + + $logger->error('Something went wrong.'); + + self::assertSame( + [], + array_filter( + $response->headers->all(), + static fn (string $key): bool => str_starts_with($key, 'x-wf-1-1-1'), + \ARRAY_FILTER_USE_KEY + ) + ); + } + + private function createHandler(): FirePHPHandler + { + // Monolog 1 + if (!method_exists(FirePHPHandler::class, 'isWebRequest')) { + return new FirePHPHandler(); + } + + $handler = $this->getMockBuilder(FirePHPHandler::class) + ->onlyMethods(['isWebRequest']) + ->getMock(); + // Disable web request detection + $handler->method('isWebRequest')->willReturn(true); + + return $handler; + } + + private function dispatchResponseEvent(FirePHPHandler $handler, Request $request): Response + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::RESPONSE, $handler->onKernelResponse(...)); + + return $dispatcher + ->dispatch( + new ResponseEvent( + $this->createStub(HttpKernelInterface::class), + $request, + HttpKernelInterface::MAIN_REQUEST, + new Response() + ), + KernelEvents::RESPONSE + ) + ->getResponse(); + } +} diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/MailerHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/MailerHandlerTest.php index daec7676c9e99..43d5ef3cfab72 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/MailerHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/MailerHandlerTest.php @@ -13,10 +13,12 @@ use Monolog\Formatter\HtmlFormatter; use Monolog\Formatter\LineFormatter; +use Monolog\LogRecord; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Handler\MailerHandler; use Symfony\Bridge\Monolog\Logger; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mime\Email; @@ -91,17 +93,9 @@ public function testHtmlContent() $handler->handle($this->getRecord(Logger::WARNING, 'message')); } - protected function getRecord($level = Logger::WARNING, $message = 'test', $context = []): array + protected function getRecord($level = Logger::WARNING, $message = 'test', $context = []): array|LogRecord { - return [ - 'message' => $message, - 'context' => $context, - 'level' => $level, - 'level_name' => Logger::getLevelName($level), - 'channel' => 'test', - 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))), - 'extra' => [], - ]; + return RecordFactory::create($level, $message, context: $context); } protected function getMultipleRecords(): array diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ServerLogHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ServerLogHandlerTest.php index f5a4405f645f1..cade0b80ec9fd 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ServerLogHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ServerLogHandlerTest.php @@ -17,6 +17,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Formatter\VarDumperFormatter; use Symfony\Bridge\Monolog\Handler\ServerLogHandler; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\VarDumper\Cloner\Data; /** @@ -37,7 +38,7 @@ public function testFormatter() public function testIsHandling() { $handler = new ServerLogHandler('tcp://127.0.0.1:9999', Logger::INFO); - $this->assertFalse($handler->isHandling(['level' => Logger::DEBUG]), '->isHandling returns false when no output is set'); + $this->assertFalse($handler->isHandling(RecordFactory::create(Logger::DEBUG)), '->isHandling returns false when no output is set'); } public function testGetFormatter() @@ -54,15 +55,7 @@ public function testWritingAndFormatting() $handler = new ServerLogHandler($host, Logger::INFO, false); $handler->pushProcessor(new ProcessIdProcessor()); - $infoRecord = [ - 'message' => 'My info message', - 'context' => [], - 'level' => Logger::INFO, - 'level_name' => Logger::getLevelName(Logger::INFO), - 'channel' => 'app', - 'datetime' => new \DateTime('2013-05-29 16:21:54'), - 'extra' => [], - ]; + $infoRecord = RecordFactory::create(Logger::INFO, 'My info message', 'app', datetime: new \DateTimeImmutable('2013-05-29 16:21:54')); $socket = stream_socket_server($host, $errno, $errstr); $this->assertIsResource($socket, sprintf('Server start failed on "%s": %s %s.', $host, $errstr, $errno)); diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php index 424f9ce10d597..c824721217ca5 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Processor\ConsoleCommandProcessor; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Input\InputInterface; @@ -29,7 +30,7 @@ public function testProcessor() $processor = new ConsoleCommandProcessor(); $processor->addCommandData($this->getConsoleEvent()); - $record = $processor(['extra' => []]); + $record = $processor(RecordFactory::create()); $this->assertArrayHasKey('command', $record['extra']); $this->assertEquals( @@ -43,7 +44,7 @@ public function testProcessorWithOptions() $processor = new ConsoleCommandProcessor(true, true); $processor->addCommandData($this->getConsoleEvent()); - $record = $processor(['extra' => []]); + $record = $processor(RecordFactory::create()); $this->assertArrayHasKey('command', $record['extra']); $this->assertEquals( @@ -56,8 +57,8 @@ public function testProcessorDoesNothingWhenNotInConsole() { $processor = new ConsoleCommandProcessor(true, true); - $record = $processor(['extra' => []]); - $this->assertEquals(['extra' => []], $record); + $record = $processor(RecordFactory::create()); + $this->assertEquals([], $record['extra']); } private function getConsoleEvent(): ConsoleEvent diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/DebugProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/DebugProcessorTest.php index c576462d0abfe..6e4b67e265d1d 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/DebugProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/DebugProcessorTest.php @@ -12,66 +12,42 @@ namespace Symfony\Bridge\Monolog\Tests\Processor; use Monolog\Logger; +use Monolog\LogRecord; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Processor\DebugProcessor; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; class DebugProcessorTest extends TestCase { - /** - * @dataProvider providerDatetimeFormatTests - */ - public function testDatetimeFormat(array $record, $expectedTimestamp) + public function testDatetimeFormat() { + $record = RecordFactory::create(datetime: new \DateTimeImmutable('2019-01-01T00:01:00+00:00')); $processor = new DebugProcessor(); $processor($record); $records = $processor->getLogs(); self::assertCount(1, $records); - self::assertSame($expectedTimestamp, $records[0]['timestamp']); + self::assertSame(1546300860, $records[0]['timestamp']); } - public function providerDatetimeFormatTests(): array - { - $record = $this->getRecord(); - - return [ - [array_merge($record, ['datetime' => new \DateTime('2019-01-01T00:01:00+00:00')]), 1546300860], - [array_merge($record, ['datetime' => '2019-01-01T00:01:00+00:00']), 1546300860], - [array_merge($record, ['datetime' => 'foo']), false], - ]; - } - - /** - * @dataProvider providerDatetimeRfc3339FormatTests - */ - public function testDatetimeRfc3339Format(array $record, $expectedTimestamp) + public function testDatetimeRfc3339Format() { + $record = RecordFactory::create(datetime: new \DateTimeImmutable('2019-01-01T00:01:00+00:00')); $processor = new DebugProcessor(); $processor($record); $records = $processor->getLogs(); self::assertCount(1, $records); - self::assertSame($expectedTimestamp, $records[0]['timestamp_rfc3339']); - } - - public function providerDatetimeRfc3339FormatTests(): array - { - $record = $this->getRecord(); - - return [ - [array_merge($record, ['datetime' => new \DateTime('2019-01-01T00:01:00+00:00')]), '2019-01-01T00:01:00.000+00:00'], - [array_merge($record, ['datetime' => '2019-01-01T00:01:00+00:00']), '2019-01-01T00:01:00.000+00:00'], - [array_merge($record, ['datetime' => 'foo']), false], - ]; + self::assertSame('2019-01-01T00:01:00.000+00:00', $records[0]['timestamp_rfc3339']); } public function testDebugProcessor() { $processor = new DebugProcessor(); - $processor($this->getRecord()); - $processor($this->getRecord(Logger::ERROR)); + $processor(self::getRecord()); + $processor(self::getRecord(Logger::ERROR)); $this->assertCount(2, $processor->getLogs()); $this->assertSame(1, $processor->countErrors()); @@ -89,8 +65,8 @@ public function testWithRequestStack() { $stack = new RequestStack(); $processor = new DebugProcessor($stack); - $processor($this->getRecord()); - $processor($this->getRecord(Logger::ERROR)); + $processor(self::getRecord()); + $processor(self::getRecord(Logger::ERROR)); $this->assertCount(2, $processor->getLogs()); $this->assertSame(1, $processor->countErrors()); @@ -98,8 +74,8 @@ public function testWithRequestStack() $request = new Request(); $stack->push($request); - $processor($this->getRecord()); - $processor($this->getRecord(Logger::ERROR)); + $processor(self::getRecord()); + $processor(self::getRecord(Logger::ERROR)); $this->assertCount(4, $processor->getLogs()); $this->assertSame(2, $processor->countErrors()); @@ -123,16 +99,8 @@ public function testInheritedClassCallCountErrorsWithoutArgument() $this->assertEquals(0, $debugProcessorChild->countErrors()); } - private function getRecord($level = Logger::WARNING, $message = 'test'): array + private static function getRecord($level = Logger::WARNING, $message = 'test'): array|LogRecord { - return [ - 'message' => $message, - 'context' => [], - 'level' => $level, - 'level_name' => Logger::getLevelName($level), - 'channel' => 'test', - 'datetime' => new \DateTime(), - 'extra' => [], - ]; + return RecordFactory::create($level, $message); } } diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/SwitchUserTokenProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/SwitchUserTokenProcessorTest.php index 602e9db61a82d..03706d7680e11 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/SwitchUserTokenProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/SwitchUserTokenProcessorTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; @@ -33,7 +34,7 @@ public function testProcessor() $tokenStorage->method('getToken')->willReturn($switchUserToken); $processor = new SwitchUserTokenProcessor($tokenStorage); - $record = ['extra' => []]; + $record = RecordFactory::create(); $record = $processor($record); $expected = [ diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php index c9e37cfdb2c45..603b6f2ce131e 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Processor\TokenProcessor; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\User\InMemoryUser; @@ -26,16 +27,12 @@ class TokenProcessorTest extends TestCase { public function testProcessor() { - if (!method_exists(UsernamePasswordToken::class, 'getUserIdentifier')) { - $this->markTestSkipped('This test requires symfony/security-core 5.3+'); - } - $token = new UsernamePasswordToken(new InMemoryUser('user', 'password', ['ROLE_USER']), 'provider', ['ROLE_USER']); $tokenStorage = $this->createMock(TokenStorageInterface::class); $tokenStorage->method('getToken')->willReturn($token); $processor = new TokenProcessor($tokenStorage); - $record = ['extra' => []]; + $record = RecordFactory::create(); $record = $processor($record); $this->assertArrayHasKey('token', $record['extra']); diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php index 9b70b4bbfbc25..3ae74658097de 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/WebProcessorTest.php @@ -12,8 +12,10 @@ namespace Symfony\Bridge\Monolog\Tests\Processor; use Monolog\Logger; +use Monolog\LogRecord; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Processor\WebProcessor; +use Symfony\Bridge\Monolog\Tests\RecordFactory; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -94,17 +96,9 @@ private function createRequestEvent(array $additionalServerParameters = []): arr return [$event, $server]; } - private function getRecord(int $level = Logger::WARNING, string $message = 'test'): array + private function getRecord(int $level = Logger::WARNING, string $message = 'test'): array|LogRecord { - return [ - 'message' => $message, - 'context' => [], - 'level' => $level, - 'level_name' => Logger::getLevelName($level), - 'channel' => 'test', - 'datetime' => new \DateTime(), - 'extra' => [], - ]; + return RecordFactory::create($level, $message); } private function isExtraFieldsSupported() diff --git a/src/Symfony/Bridge/Monolog/Tests/RecordFactory.php b/src/Symfony/Bridge/Monolog/Tests/RecordFactory.php new file mode 100644 index 0000000000000..8f7b5a1f78357 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Tests/RecordFactory.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Tests; + +use Monolog\Logger; +use Monolog\LogRecord; + +class RecordFactory +{ + public static function create(int|string $level = 'warning', string|\Stringable $message = 'test', string $channel = 'test', array $context = [], \DateTimeImmutable $datetime = new \DateTimeImmutable(), array $extra = []): LogRecord|array + { + $level = Logger::toMonologLevel($level); + + if (Logger::API >= 3) { + return new LogRecord( + message: (string) $message, + context: $context, + level: $level, + channel: $channel, + datetime: $datetime, + extra: $extra, + ); + } + + return [ + 'message' => $message, + 'context' => $context, + 'level' => $level, + 'level_name' => Logger::getLevelName($level), + 'channel' => $channel, + // Monolog 1 had no support for DateTimeImmutable + 'datetime' => Logger::API >= 2 ? $datetime : \DateTime::createFromImmutable($datetime), + 'extra' => $extra, + ]; + } +} diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index 1fd9424f683a9..025d54a48398d 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -16,8 +16,8 @@ } ], "require": { - "php": ">=8.0.2", - "monolog/monolog": "^1.25.1|^2", + "php": ">=8.1", + "monolog/monolog": "^1.25.1|^2|^3", "symfony/service-contracts": "^1.1|^2|^3", "symfony/http-kernel": "^5.4|^6.0" }, diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index bdcd3ea0d7819..9b8a974ecc5e6 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.1 +--- + + * Add option `ignoreFile` to configure a file that lists deprecation messages to ignore + 6.0 --- diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 2aeae49d58fa9..36c0960868dad 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -132,10 +132,13 @@ public function handleError($type, $msg, $file, $line, $context = []) $msg = $trace[1]['args'][0]; } - $deprecation = new Deprecation($msg, $trace, $file); + $deprecation = new Deprecation($msg, $trace, $file, \E_DEPRECATED === $type); if ($deprecation->isMuted()) { return null; } + if ($this->getConfiguration()->isIgnoredDeprecation($deprecation)) { + return null; + } if ($this->getConfiguration()->isBaselineDeprecation($deprecation)) { return null; } @@ -188,7 +191,7 @@ public function shutdown() if (class_exists(DebugClassLoader::class, false)) { DebugClassLoader::checkClasses(); } - $currErrorHandler = set_error_handler('var_dump'); + $currErrorHandler = set_error_handler('is_int'); restore_error_handler(); if ($currErrorHandler !== [$this, 'handleError']) { @@ -200,7 +203,7 @@ public function shutdown() // store failing status $isFailing = !$configuration->tolerates($this->deprecationGroups); - $this->displayDeprecations($groups, $configuration, $isFailing); + $this->displayDeprecations($groups, $configuration); $this->resetDeprecationGroups(); @@ -213,7 +216,7 @@ public function shutdown() } $isFailingAtShutdown = !$configuration->tolerates($this->deprecationGroups); - $this->displayDeprecations($groups, $configuration, $isFailingAtShutdown); + $this->displayDeprecations($groups, $configuration); if ($configuration->isGeneratingBaseline()) { $configuration->writeBaseline(); @@ -289,11 +292,10 @@ private static function colorize($str, $red) /** * @param string[] $groups * @param Configuration $configuration - * @param bool $isFailing * * @throws \InvalidArgumentException */ - private function displayDeprecations($groups, $configuration, $isFailing) + private function displayDeprecations($groups, $configuration) { $cmp = function ($a, $b) { return $b->count() - $a->count(); @@ -320,7 +322,8 @@ private function displayDeprecations($groups, $configuration, $isFailing) fwrite($handle, "\n".self::colorize($deprecationGroupMessage, 'legacy' !== $group && 'indirect' !== $group)."\n"); } - if ('legacy' !== $group && !$configuration->verboseOutput($group) && !$isFailing) { + // Skip the verbose output if the group is quiet and not failing according to its threshold: + if ('legacy' !== $group && !$configuration->verboseOutput($group) && $configuration->toleratesForGroup($group, $this->deprecationGroups)) { continue; } $notices = $this->deprecationGroups[$group]->notices(); @@ -331,9 +334,14 @@ private function displayDeprecations($groups, $configuration, $isFailing) $countsByCaller = $notice->getCountsByCaller(); arsort($countsByCaller); + $limit = 5; foreach ($countsByCaller as $method => $count) { if ('count' !== $method) { + if (!$limit--) { + fwrite($handle, " ...\n"); + break; + } fwrite($handle, sprintf(" %dx in %s\n", $count, preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method))); } } diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php index 4420ef3d0e46c..45d1ed7ce9940 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php @@ -36,6 +36,11 @@ class Configuration */ private $verboseOutput; + /** + * @var string[] + */ + private $ignoreDeprecationPatterns = []; + /** * @var bool */ @@ -60,11 +65,12 @@ class Configuration * @param int[] $thresholds A hash associating groups to thresholds * @param string $regex Will be matched against messages, to decide whether to display a stack trace * @param bool[] $verboseOutput Keyed by groups + * @param string $ignoreFile The path to the ignore deprecation patterns file * @param bool $generateBaseline Whether to generate or update the baseline file * @param string $baselineFile The path to the baseline file * @param string|null $logFile The path to the log file */ - private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $generateBaseline = false, $baselineFile = '', $logFile = null) + private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $ignoreFile = '', $generateBaseline = false, $baselineFile = '', $logFile = null) { $groups = ['total', 'indirect', 'direct', 'self']; @@ -110,6 +116,25 @@ private function __construct(array $thresholds = [], $regex = '', $verboseOutput $this->verboseOutput[$group] = $status; } + if ($ignoreFile) { + if (!is_file($ignoreFile)) { + throw new \InvalidArgumentException(sprintf('The ignoreFile "%s" does not exist.', $ignoreFile)); + } + set_error_handler(static function ($t, $m) use ($ignoreFile, &$line) { + throw new \RuntimeException(sprintf('Invalid pattern found in "%s" on line "%d"', $ignoreFile, 1 + $line).substr($m, 12)); + }); + try { + foreach (file($ignoreFile) as $line => $pattern) { + if ('#' !== (trim($pattern)[0] ?? '#')) { + preg_match($pattern, ''); + $this->ignoreDeprecationPatterns[] = $pattern; + } + } + } finally { + restore_error_handler(); + } + } + if ($generateBaseline && !$baselineFile) { throw new \InvalidArgumentException('You cannot use the "generateBaseline" configuration option without providing a "baselineFile" configuration option.'); } @@ -165,11 +190,54 @@ public function tolerates(array $deprecationGroups) return true; } + public function isIgnoredDeprecation(Deprecation $deprecation): bool + { + if (!$this->ignoreDeprecationPatterns) { + return false; + } + $result = @preg_filter($this->ignoreDeprecationPatterns, '$0', $deprecation->getMessage()); + if (\PREG_NO_ERROR !== preg_last_error()) { + throw new \RuntimeException(preg_last_error_msg()); + } + + return (bool) $result; + } + + /** + * @param array $deprecationGroups + * + * @return bool true if the threshold is not reached for the deprecation type nor for the total + */ + public function toleratesForGroup(string $groupName, array $deprecationGroups): bool + { + $grandTotal = 0; + + foreach ($deprecationGroups as $type => $group) { + if ('legacy' !== $type) { + $grandTotal += $group->count(); + } + } + + if ($grandTotal > $this->thresholds['total']) { + return false; + } + + if (\in_array($groupName, ['self', 'direct', 'indirect'], true) && $deprecationGroups[$groupName]->count() > $this->thresholds[$groupName]) { + return false; + } + + return true; + } + /** * @return bool */ public function isBaselineDeprecation(Deprecation $deprecation) { + if ($deprecation->isLegacy()) { + return false; + } + if ($deprecation->originatesFromAnObject()) { $location = $deprecation->originatingClass().'::'.$deprecation->originatingMethod(); } else { @@ -266,16 +334,17 @@ public static function fromUrlEncodedString($serializedConfiguration) { parse_str($serializedConfiguration, $normalizedConfiguration); foreach (array_keys($normalizedConfiguration) as $key) { - if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'generateBaseline', 'baselineFile', 'logFile'], true)) { + if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'ignoreFile', 'generateBaseline', 'baselineFile', 'logFile'], true)) { throw new \InvalidArgumentException(sprintf('Unknown configuration option "%s".', $key)); } } $normalizedConfiguration += [ - 'max' => [], + 'max' => ['total' => 0], 'disabled' => false, 'verbose' => true, 'quiet' => [], + 'ignoreFile' => '', 'generateBaseline' => false, 'baselineFile' => '', 'logFile' => null, @@ -297,9 +366,10 @@ public static function fromUrlEncodedString($serializedConfiguration) } return new self( - $normalizedConfiguration['max'] ?? [], + $normalizedConfiguration['max'], '', $verboseOutput, + $normalizedConfiguration['ignoreFile'], filter_var($normalizedConfiguration['generateBaseline'], \FILTER_VALIDATE_BOOLEAN), $normalizedConfiguration['baselineFile'], $normalizedConfiguration['logFile'] diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php index 5eda2bafdfb10..5a5a0f61c4e64 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php @@ -37,6 +37,7 @@ class Deprecation private $trace = []; private $message; + private $languageDeprecation; private $originClass; private $originMethod; private $triggeringFile; @@ -56,8 +57,9 @@ class Deprecation /** * @param string $message * @param string $file + * @param bool $languageDeprecation */ - public function __construct($message, array $trace, $file) + public function __construct($message, array $trace, $file, $languageDeprecation = false) { if (isset($trace[2]['function']) && 'trigger_deprecation' === $trace[2]['function']) { $file = $trace[2]['file']; @@ -66,6 +68,7 @@ public function __construct($message, array $trace, $file) $this->trace = $trace; $this->message = $message; + $this->languageDeprecation = $languageDeprecation; $i = \count($trace); while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) { @@ -239,7 +242,12 @@ public function isMuted() */ public function getType() { - if (self::PATH_TYPE_SELF === $pathType = $this->getPathType($this->triggeringFile)) { + $pathType = $this->getPathType($this->triggeringFile); + if ($this->languageDeprecation && self::PATH_TYPE_VENDOR === $pathType) { + // the triggering file must be used for language deprecations + return self::TYPE_INDIRECT; + } + if (self::PATH_TYPE_SELF === $pathType) { return self::TYPE_SELF; } if (self::PATH_TYPE_UNDETERMINED === $pathType) { diff --git a/src/Symfony/Bridge/PhpUnit/LICENSE b/src/Symfony/Bridge/PhpUnit/LICENSE index a843ec124ea70..72412a62b2029 100644 --- a/src/Symfony/Bridge/PhpUnit/LICENSE +++ b/src/Symfony/Bridge/PhpUnit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2022 Fabien Potencier +Copyright (c) 2014-2023 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 diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index c84ec1b66ddbd..a623edbbf15de 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -138,7 +138,7 @@ public function startTestSuite($suite) if (!class_exists(AnnotationRegistry::class, false) && class_exists(AnnotationRegistry::class)) { if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { AnnotationRegistry::registerUniqueLoader('class_exists'); - } else { + } elseif (method_exists(AnnotationRegistry::class, 'registerLoader')) { AnnotationRegistry::registerLoader('class_exists'); } } @@ -271,7 +271,7 @@ public function endTest($test, $time) $assertions = \count(self::$expectedDeprecations) + $test->getNumAssertions(); if ($test->doesNotPerformAssertions() && $assertions > 0) { $test->getTestResultObject()->addFailure($test, new RiskyTestError(sprintf('This test is annotated with "@doesNotPerformAssertions", but performed %s assertions', $assertions)), $time); - } elseif ($assertions === 0 && $test->getTestResultObject()->noneSkipped()) { + } elseif ($assertions === 0 && !$test->doesNotPerformAssertions() && $test->getTestResultObject()->noneSkipped()) { $test->getTestResultObject()->addFailure($test, new RiskyTestError('This test did not perform any assertions'), $time); } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php index b309606d5bd4e..19408df6d2dfe 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PhpUnit\Tests; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php index 5d36a43bff54f..496a1b5fa8170 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php @@ -234,6 +234,103 @@ public function testOutputIsNotVerboseInWeakMode() $this->assertFalse($configuration->verboseOutput('other')); } + /** + * @dataProvider provideDataForToleratesForGroup + */ + public function testToleratesForIndividualGroups(string $deprecationsHelper, array $deprecationsPerType, array $expected) + { + $configuration = Configuration::fromUrlEncodedString($deprecationsHelper); + + $groups = $this->buildGroups($deprecationsPerType); + + foreach ($expected as $groupName => $tolerates) { + $this->assertSame($tolerates, $configuration->toleratesForGroup($groupName, $groups), sprintf('Deprecation type "%s" is %s', $groupName, $tolerates ? 'tolerated' : 'not tolerated')); + } + } + + public function provideDataForToleratesForGroup() { + + yield 'total threshold not reached' => ['max[total]=1', [ + 'unsilenced' => 0, + 'self' => 0, + 'legacy' => 1, // Legacy group is ignored in total threshold + 'other' => 0, + 'direct' => 1, + 'indirect' => 0, + ], [ + 'unsilenced' => true, + 'self' => true, + 'legacy' => true, + 'other' => true, + 'direct' => true, + 'indirect' => true, + ]]; + + yield 'total threshold reached' => ['max[total]=1', [ + 'unsilenced' => 0, + 'self' => 0, + 'legacy' => 1, + 'other' => 0, + 'direct' => 1, + 'indirect' => 1, + ], [ + 'unsilenced' => false, + 'self' => false, + 'legacy' => false, + 'other' => false, + 'direct' => false, + 'indirect' => false, + ]]; + + yield 'direct threshold reached' => ['max[total]=99&max[direct]=0', [ + 'unsilenced' => 0, + 'self' => 0, + 'legacy' => 1, + 'other' => 0, + 'direct' => 1, + 'indirect' => 1, + ], [ + 'unsilenced' => true, + 'self' => true, + 'legacy' => true, + 'other' => true, + 'direct' => false, + 'indirect' => true, + ]]; + + yield 'indirect & self threshold reached' => ['max[total]=99&max[direct]=0&max[self]=0', [ + 'unsilenced' => 0, + 'self' => 1, + 'legacy' => 1, + 'other' => 1, + 'direct' => 1, + 'indirect' => 1, + ], [ + 'unsilenced' => true, + 'self' => false, + 'legacy' => true, + 'other' => true, + 'direct' => false, + 'indirect' => true, + ]]; + + yield 'indirect & self threshold not reached' => ['max[total]=99&max[direct]=2&max[self]=2', [ + 'unsilenced' => 0, + 'self' => 1, + 'legacy' => 1, + 'other' => 1, + 'direct' => 1, + 'indirect' => 1, + ], [ + 'unsilenced' => true, + 'self' => true, + 'legacy' => true, + 'other' => true, + 'direct' => true, + 'indirect' => true, + ]]; + } + private function buildGroups($counts) { $groups = []; @@ -391,6 +488,62 @@ public function testBaselineFileWriteError() $configuration->writeBaseline(); } + public function testExistingIgnoreFile() + { + $filename = $this->createFile(); + $ignorePatterns = [ + '/Test message .*/', + '/^\d* occurrences/', + ]; + file_put_contents($filename, implode("\n", $ignorePatterns)); + + $configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename)); + $trace = debug_backtrace(); + $this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('Test message 1', $trace, ''))); + $this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('Test message 2', $trace, ''))); + $this->assertFalse($configuration->isIgnoredDeprecation(new Deprecation('Test mexxage 3', $trace, ''))); + $this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('1 occurrences', $trace, ''))); + $this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('1200 occurrences and more', $trace, ''))); + $this->assertFalse($configuration->isIgnoredDeprecation(new Deprecation('Many occurrences', $trace, ''))); + } + + public function testIgnoreFilePatternInvalid() + { + $filename = $this->createFile(); + $ignorePatterns = [ + '/Test message (.*/', + ]; + file_put_contents($filename, implode("\n", $ignorePatterns)); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('missing closing parenthesis'); + $configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename)); + } + + public function testIgnoreFilePatternException() + { + $filename = $this->createFile(); + $ignorePatterns = [ + '/(?:\D+|<\d+>)*[!?]/', + ]; + file_put_contents($filename, implode("\n", $ignorePatterns)); + + $configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename)); + $trace = debug_backtrace(); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessageMatches('/[Bb]acktrack limit exhausted/'); + $configuration->isIgnoredDeprecation(new Deprecation('foobar foobar foobar', $trace, '')); + } + + public function testIgnoreFileException() + { + $filename = $this->createFile(); + unlink($filename); + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('The ignoreFile "%s" does not exist.', $filename)); + Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename)); + } + protected function setUp(): void { $this->files = []; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline.phpt index 533912c106cbd..83d448ea8ca7b 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline.phpt @@ -78,3 +78,4 @@ print "Cannot test baselineFile contents because it is generated in a shutdown f ?> --EXPECT-- Cannot test baselineFile contents because it is generated in a shutdown function registered by another shutdown function. +Legacy deprecation notices (1) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline2.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline2.phpt index f520912694a1e..925d5c2384901 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline2.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline2.phpt @@ -66,6 +66,8 @@ $foo->testLegacyFoo(); $foo->testNonLegacyBar(); ?> --EXPECTF-- +Legacy deprecation notices (1) + Other deprecation notices (2) 1x: root deprecation diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline3.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline3.phpt index 28d1a74ffd427..d814c02b555b3 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline3.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/baseline3.phpt @@ -69,7 +69,7 @@ $foo->testLegacyFoo(); $foo->testNonLegacyBar(); ?> --EXPECTF-- -Legacy deprecation notices (1) +Legacy deprecation notices (2) Other deprecation notices (2) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php new file mode 100644 index 0000000000000..26a3237e77941 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php @@ -0,0 +1,15 @@ + --EXPECT-- Cannot test baselineFile contents because it is generated in a shutdown function registered by another shutdown function. +Legacy deprecation notices (1) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ignore.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ignore.phpt new file mode 100644 index 0000000000000..44d86203f4777 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ignore.phpt @@ -0,0 +1,80 @@ +--TEST-- +Test DeprecationErrorHandler with an ignoreFile +--FILE-- +testLegacyFoo(); +$foo->testNonLegacyBar(); +?> +--EXPECTF-- +Legacy deprecation notices (1) + +Other deprecation notices (2) + + 1x: root deprecation + + 1x: not ignored bar deprecation + 1x in FooTestCase::testNonLegacyBar diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/partially_quiet2.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/partially_quiet2.phpt new file mode 100644 index 0000000000000..4d0d6c3d55794 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/partially_quiet2.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test DeprecationErrorHandler quiet on everything but self/direct deprecations +--FILE-- + +--EXPECTF-- +Unsilenced deprecation notices (3) + +Remaining direct deprecation notices (2) + + 1x: root deprecation + + 1x: silenced bar deprecation + 1x in FooTestCase::testNonLegacyBar + +Remaining indirect deprecation notices (1) + +Legacy deprecation notices (2) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt new file mode 100644 index 0000000000000..1ead2ef4a4013 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt @@ -0,0 +1,43 @@ +--TEST-- +Test that a PHP deprecation from a vendor class autoload is considered indirect. +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Remaining indirect deprecation notices (1) + + 1x: acme\lib\PhpDeprecation implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) + 1x in DebugClassLoader::loadClass from Symfony\Component\ErrorHandler diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/quiet.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/quiet.phpt index 91cee8e17fa95..5b6e325106f03 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/quiet.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/quiet.phpt @@ -4,7 +4,7 @@ Test DeprecationErrorHandler with quiet output + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Tests\FailTests; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; + +/** + * This class is deliberately suffixed with *TestRisky.php so that it is ignored + * by PHPUnit. This test is designed to fail. See ../expectnotrisky.phpt. + */ +final class NoAssertionsTestNotRisky extends TestCase +{ + use ExpectDeprecationTrait; + + /** + * Do not remove this test in the next major version. + */ + public function testOne() + { + $this->expectNotToPerformAssertions(); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php index e9634480b770d..04bf6ec80776a 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PhpUnit\Tests; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/expectdeprecationfail.phpt b/src/Symfony/Bridge/PhpUnit/Tests/expectdeprecationfail.phpt index 9f9bf8c17508e..f968cd188a0a7 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/expectdeprecationfail.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/expectdeprecationfail.phpt @@ -6,7 +6,7 @@ $test = realpath(__DIR__.'/FailTests/ExpectDeprecationTraitTestFail.php'); passthru('php '.getenv('SYMFONY_SIMPLE_PHPUNIT_BIN_DIR').'/simple-phpunit.php --colors=never '.$test); ?> --EXPECTF-- -PHPUnit %s by Sebastian Bergmann and contributors. +PHPUnit %s %ATesting Symfony\Bridge\PhpUnit\Tests\FailTests\ExpectDeprecationTraitTestFail FF 2 / 2 (100%) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/expectnotrisky.phpt b/src/Symfony/Bridge/PhpUnit/Tests/expectnotrisky.phpt new file mode 100644 index 0000000000000..2005adf2ec363 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/expectnotrisky.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test NoAssertionsTestNotRisky not risky test +--SKIPIF-- + +--EXPECTF-- +PHPUnit %s + +%ATesting Symfony\Bridge\PhpUnit\Tests\FailTests\NoAssertionsTestNotRisky +. 1 / 1 (100%) + +Time: %s, Memory: %s + +OK (1 test, 0 assertions) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/expectrisky.phpt b/src/Symfony/Bridge/PhpUnit/Tests/expectrisky.phpt index 608c56488979f..91e0830553950 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/expectrisky.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/expectrisky.phpt @@ -8,7 +8,7 @@ $test = realpath(__DIR__.'/FailTests/NoAssertionsTestRisky.php'); passthru('php '.getenv('SYMFONY_SIMPLE_PHPUNIT_BIN_DIR').'/simple-phpunit.php --fail-on-risky --colors=never '.$test); ?> --EXPECTF-- -PHPUnit %s by Sebastian Bergmann and contributors. +PHPUnit %s %ATesting Symfony\Bridge\PhpUnit\Tests\FailTests\NoAssertionsTestRisky R. 2 / 2 (100%) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index ea88872ae9b86..f28933cf97357 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -12,6 +12,10 @@ // Please update when phpunit needs to be reinstalled with fresh deps: // Cache-Id: 2021-02-04 11:00 UTC +if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + error_reporting(-1); global $argv, $argc; @@ -66,14 +70,14 @@ $phpunitConfigFilename = $phpunitConfigFilename ?: $getPhpUnitConfig('phpunit.xml'); if ($phpunitConfigFilename) { - $phpunitConfig = new DomDocument(); + $phpunitConfig = new DOMDocument(); $phpunitConfig->load($phpunitConfigFilename); } else { $phpunitConfig = false; } } if (false !== $phpunitConfig) { - $var = new DOMXpath($phpunitConfig); + $var = new DOMXPath($phpunitConfig); foreach ($var->query('//php/server[@name="'.$name.'"]') as $var) { return $var->getAttribute('value'); } @@ -149,9 +153,9 @@ $COMPOSER = ($COMPOSER = getenv('COMPOSER_BINARY')) || file_exists($COMPOSER = $oldPwd.'/composer.phar') - || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar 2> NUL`) : `which composer.phar 2> /dev/null`))) - || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer 2> NUL`) : `which composer 2> /dev/null`))) - || file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`)).\DIRECTORY_SEPARATOR.'composer.phar') + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', shell_exec('where.exe composer.phar 2> NUL')) : shell_exec('which composer.phar 2> /dev/null')))) + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', shell_exec('where.exe composer 2> NUL')) : shell_exec('which composer 2> /dev/null')))) + || file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? shell_exec('git rev-parse --show-toplevel 2> NUL') : shell_exec('git rev-parse --show-toplevel 2> /dev/null'))).\DIRECTORY_SEPARATOR.'composer.phar') ? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang : 'composer'; diff --git a/src/Symfony/Bridge/PhpUnit/bootstrap.php b/src/Symfony/Bridge/PhpUnit/bootstrap.php index e07c8d6cf5de8..f2064368f41a3 100644 --- a/src/Symfony/Bridge/PhpUnit/bootstrap.php +++ b/src/Symfony/Bridge/PhpUnit/bootstrap.php @@ -30,7 +30,7 @@ if (!class_exists(AnnotationRegistry::class, false) && class_exists(AnnotationRegistry::class)) { if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { AnnotationRegistry::registerUniqueLoader('class_exists'); - } else { + } elseif (method_exists(AnnotationRegistry::class, 'registerLoader')) { AnnotationRegistry::registerLoader('class_exists'); } } diff --git a/src/Symfony/Bridge/ProxyManager/LICENSE b/src/Symfony/Bridge/ProxyManager/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bridge/ProxyManager/LICENSE +++ b/src/Symfony/Bridge/ProxyManager/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index a63cbb4667549..e787da909bbb3 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -185,6 +185,7 @@ function ($definition) { } } +#[\AllowDynamicProperties] final class DummyClass implements DummyInterface, SunnyInterface { private $ref; diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 430c4edd1e608..d141f99ba6ee5 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "friendsofphp/proxy-manager-lts": "^1.0.2", "symfony/dependency-injection": "^5.4|^6.0" }, diff --git a/src/Symfony/Bridge/Twig/AppVariable.php b/src/Symfony/Bridge/Twig/AppVariable.php index b46646b5461ae..43d6e3ffc9056 100644 --- a/src/Symfony/Bridge/Twig/AppVariable.php +++ b/src/Symfony/Bridge/Twig/AppVariable.php @@ -139,7 +139,7 @@ public function getFlashes(string|array $types = null): array if (null === $session = $this->getSession()) { return []; } - } catch (\RuntimeException $e) { + } catch (\RuntimeException) { return []; } diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index 535df0c0897b4..819251bf0d874 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.1 +--- + + * Wrap help messages on form elements in `div` instead of `p` + 5.4 --- diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 542ec78218d4d..d5e64859a6c20 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -294,7 +294,7 @@ private function getLoaderPaths(string $name = null): array } foreach ($namespaces as $namespace) { - $paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace)); + $paths = array_map($this->getRelativePath(...), $loader->getPaths($namespace)); if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { $namespace = '(None)'; diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index dfe66054bc496..54f4e233b884d 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -39,14 +39,13 @@ #[AsCommand(name: 'lint:twig', description: 'Lint a Twig template and outputs encountered errors')] class LintCommand extends Command { - private Environment $twig; private string $format; - public function __construct(Environment $twig) - { + public function __construct( + private Environment $twig, + private array $namePatterns = ['*.twig'], + ) { parent::__construct(); - - $this->twig = $twig; } protected function configure() @@ -146,7 +145,7 @@ protected function findFiles(string $filename) if (is_file($filename)) { return [$filename]; } elseif (is_dir($filename)) { - return Finder::create()->files()->in($filename)->name('*.twig'); + return Finder::create()->files()->in($filename)->name($this->namePatterns); } throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); @@ -172,16 +171,12 @@ private function validate(string $template, string $file): array private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, array $files) { - switch ($this->format) { - case 'txt': - return $this->displayTxt($output, $io, $files); - case 'json': - return $this->displayJson($output, $files); - case 'github': - return $this->displayTxt($output, $io, $files, true); - default: - throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); - } + return match ($this->format) { + 'txt' => $this->displayTxt($output, $io, $files), + 'json' => $this->displayJson($output, $files), + 'github' => $this->displayTxt($output, $io, $files, true), + default => throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))), + }; } private function displayTxt(OutputInterface $output, SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false) diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index f41aa479cb794..a26a620cfddb0 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -71,7 +71,7 @@ public function lateCollect() if ($profile->isTemplate()) { try { $template = $this->twig->load($name = $profile->getName()); - } catch (LoaderError $e) { + } catch (LoaderError) { $template = null; } @@ -140,7 +140,7 @@ public function getHtmlCallGraph() public function getProfile() { - return $this->profile ??= unserialize($this->data['profile'], ['allowed_classes' => ['Twig_Profiler_Profile', 'Twig\Profiler\Profile']]); + return $this->profile ??= unserialize($this->data['profile'], ['allowed_classes' => ['Twig_Profiler_Profile', Profile::class]]); } private function getComputedData(string $index) diff --git a/src/Symfony/Bridge/Twig/ErrorRenderer/TwigErrorRenderer.php b/src/Symfony/Bridge/Twig/ErrorRenderer/TwigErrorRenderer.php index ef3d433b94ce9..4dde73f62c902 100644 --- a/src/Symfony/Bridge/Twig/ErrorRenderer/TwigErrorRenderer.php +++ b/src/Symfony/Bridge/Twig/ErrorRenderer/TwigErrorRenderer.php @@ -36,7 +36,7 @@ public function __construct(Environment $twig, HtmlErrorRenderer $fallbackErrorR { $this->twig = $twig; $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); - $this->debug = !\is_callable($debug) || $debug instanceof \Closure ? $debug : \Closure::fromCallable($debug); + $this->debug = \is_bool($debug) ? $debug : $debug(...); } /** diff --git a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php index 35c69b6988910..3e12371ba99c3 100644 --- a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php @@ -35,8 +35,8 @@ public function __construct(Packages $packages) public function getFunctions(): array { return [ - new TwigFunction('asset', [$this, 'getAssetUrl']), - new TwigFunction('asset_version', [$this, 'getAssetVersion']), + new TwigFunction('asset', $this->getAssetUrl(...)), + new TwigFunction('asset_version', $this->getAssetVersion(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 62573d9f961e6..af6ea706b280c 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -28,7 +28,7 @@ final class CodeExtension extends AbstractExtension public function __construct(string|FileLinkFormatter $fileLinkFormat, string $projectDir, string $charset) { - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); $this->projectDir = str_replace('\\', '/', $projectDir).'/'; $this->charset = $charset; } @@ -39,16 +39,16 @@ public function __construct(string|FileLinkFormatter $fileLinkFormat, string $pr public function getFilters(): array { return [ - new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]), - new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]), - new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]), - new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']), - new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]), - new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]), - new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]), - new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]), - new TwigFilter('file_link', [$this, 'getFileLink']), - new TwigFilter('file_relative', [$this, 'getFileRelative']), + new TwigFilter('abbr_class', $this->abbrClass(...), ['is_safe' => ['html']]), + new TwigFilter('abbr_method', $this->abbrMethod(...), ['is_safe' => ['html']]), + new TwigFilter('format_args', $this->formatArgs(...), ['is_safe' => ['html']]), + new TwigFilter('format_args_as_text', $this->formatArgsAsText(...)), + new TwigFilter('file_excerpt', $this->fileExcerpt(...), ['is_safe' => ['html']]), + new TwigFilter('format_file', $this->formatFile(...), ['is_safe' => ['html']]), + new TwigFilter('format_file_from_text', $this->formatFileFromText(...), ['is_safe' => ['html']]), + new TwigFilter('format_log_message', $this->formatLogMessage(...), ['is_safe' => ['html']]), + new TwigFilter('file_link', $this->getFileLink(...)), + new TwigFilter('file_relative', $this->getFileRelative(...)), ]; } @@ -204,7 +204,7 @@ public function formatLogMessage(string $message, array $context): string if ($context && str_contains($message, '{')) { $replacements = []; foreach ($context as $key => $val) { - if (is_scalar($val)) { + if (\is_scalar($val)) { $replacements['{'.$key.'}'] = $val; } } diff --git a/src/Symfony/Bridge/Twig/Extension/DumpExtension.php b/src/Symfony/Bridge/Twig/Extension/DumpExtension.php index 1ce6593a13ec0..910fece83b9bb 100644 --- a/src/Symfony/Bridge/Twig/Extension/DumpExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/DumpExtension.php @@ -41,7 +41,7 @@ public function __construct(ClonerInterface $cloner, HtmlDumper $dumper = null) public function getFunctions(): array { return [ - new TwigFunction('dump', [$this, 'dump'], ['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]), + new TwigFunction('dump', $this->dump(...), ['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php b/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php index 8d2a35c99f682..a30499620ea0f 100644 --- a/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php @@ -28,7 +28,7 @@ final class ExpressionExtension extends AbstractExtension public function getFunctions(): array { return [ - new TwigFunction('expression', [$this, 'createExpression']), + new TwigFunction('expression', $this->createExpression(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 6e42928a71c82..c041a51f9c300 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -11,10 +11,13 @@ namespace Symfony\Bridge\Twig\Extension; +use Symfony\Bridge\Twig\Node\RenderBlockNode; +use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode; use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Extension\AbstractExtension; @@ -54,23 +57,23 @@ public function getTokenParsers(): array public function getFunctions(): array { return [ - new TwigFunction('form_widget', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_errors', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_label', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_help', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_row', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_rest', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_start', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_end', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('csrf_token', ['Symfony\Component\Form\FormRenderer', 'renderCsrfToken']), + new TwigFunction('form_widget', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_errors', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_label', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_help', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_row', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_rest', null, ['node_class' => SearchAndRenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form', null, ['node_class' => RenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_start', null, ['node_class' => RenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('form_end', null, ['node_class' => RenderBlockNode::class, 'is_safe' => ['html']]), + new TwigFunction('csrf_token', [FormRenderer::class, 'renderCsrfToken']), new TwigFunction('form_parent', 'Symfony\Bridge\Twig\Extension\twig_get_form_parent'), - new TwigFunction('field_name', [$this, 'getFieldName']), - new TwigFunction('field_value', [$this, 'getFieldValue']), - new TwigFunction('field_label', [$this, 'getFieldLabel']), - new TwigFunction('field_help', [$this, 'getFieldHelp']), - new TwigFunction('field_errors', [$this, 'getFieldErrors']), - new TwigFunction('field_choices', [$this, 'getFieldChoices']), + new TwigFunction('field_name', $this->getFieldName(...)), + new TwigFunction('field_value', $this->getFieldValue(...)), + new TwigFunction('field_label', $this->getFieldLabel(...)), + new TwigFunction('field_help', $this->getFieldHelp(...)), + new TwigFunction('field_errors', $this->getFieldErrors(...)), + new TwigFunction('field_choices', $this->getFieldChoices(...)), ]; } @@ -80,8 +83,8 @@ public function getFunctions(): array public function getFilters(): array { return [ - new TwigFilter('humanize', ['Symfony\Component\Form\FormRenderer', 'humanize']), - new TwigFilter('form_encode_currency', ['Symfony\Component\Form\FormRenderer', 'encodeCurrency'], ['is_safe' => ['html'], 'needs_environment' => true]), + new TwigFilter('humanize', [FormRenderer::class, 'humanize']), + new TwigFilter('form_encode_currency', [FormRenderer::class, 'encodeCurrency'], ['is_safe' => ['html'], 'needs_environment' => true]), ]; } @@ -188,7 +191,7 @@ private function createFieldTranslation(?string $value, array $parameters, strin * * @see ChoiceView::isSelected() */ -function twig_is_selected_choice(ChoiceView $choice, string|array $selectedValue): bool +function twig_is_selected_choice(ChoiceView $choice, string|array|null $selectedValue): bool { if (\is_array($selectedValue)) { return \in_array($choice->value, $selectedValue, true); diff --git a/src/Symfony/Bridge/Twig/Extension/HtmlSanitizerExtension.php b/src/Symfony/Bridge/Twig/Extension/HtmlSanitizerExtension.php new file mode 100644 index 0000000000000..bec5ceb94e34e --- /dev/null +++ b/src/Symfony/Bridge/Twig/Extension/HtmlSanitizerExtension.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Extension; + +use Psr\Container\ContainerInterface; +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; + +/** + * @author Titouan Galopin + */ +final class HtmlSanitizerExtension extends AbstractExtension +{ + public function __construct( + private ContainerInterface $sanitizers, + private string $defaultSanitizer = 'default', + ) { + } + + public function getFilters(): array + { + return [ + new TwigFilter('sanitize_html', $this->sanitize(...), ['is_safe' => ['html']]), + ]; + } + + public function sanitize(string $html, string $sanitizer = null): string + { + return $this->sanitizers->get($sanitizer ?? $this->defaultSanitizer)->sanitize($html); + } +} diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php index 365e11733c92b..104bd3231f773 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php @@ -36,8 +36,8 @@ public function __construct(UrlHelper $urlHelper) public function getFunctions(): array { return [ - new TwigFunction('absolute_url', [$this, 'generateAbsoluteUrl']), - new TwigFunction('relative_path', [$this, 'generateRelativePath']), + new TwigFunction('absolute_url', $this->generateAbsoluteUrl(...)), + new TwigFunction('relative_path', $this->generateRelativePath(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php b/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php index 5b29b4896906e..3ac7582b8fbeb 100644 --- a/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php @@ -35,8 +35,8 @@ public function __construct(LogoutUrlGenerator $generator) public function getFunctions(): array { return [ - new TwigFunction('logout_url', [$this, 'getLogoutUrl']), - new TwigFunction('logout_path', [$this, 'getLogoutPath']), + new TwigFunction('logout_url', $this->getLogoutUrl(...)), + new TwigFunction('logout_path', $this->getLogoutPath(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 26591fd5533b5..3b3a2ac58e27b 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -38,8 +38,8 @@ public function __construct(UrlGeneratorInterface $generator) public function getFunctions(): array { return [ - new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), - new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), + new TwigFunction('url', $this->getUrl(...), ['is_safe_callback' => $this->isUrlGenerationSafe(...)]), + new TwigFunction('path', $this->getPath(...), ['is_safe_callback' => $this->isUrlGenerationSafe(...)]), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php index 3f24b82de5a17..dd1c57fb3b36e 100644 --- a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php @@ -46,7 +46,7 @@ public function isGranted(mixed $role, mixed $object = null, string $field = nul try { return $this->securityChecker->isGranted($role, $object); - } catch (AuthenticationCredentialsNotFoundException $e) { + } catch (AuthenticationCredentialsNotFoundException) { return false; } } @@ -75,9 +75,9 @@ public function getImpersonateExitPath(string $exitTo = null): string public function getFunctions(): array { return [ - new TwigFunction('is_granted', [$this, 'isGranted']), - new TwigFunction('impersonation_exit_url', [$this, 'getImpersonateExitUrl']), - new TwigFunction('impersonation_exit_path', [$this, 'getImpersonateExitPath']), + new TwigFunction('is_granted', $this->isGranted(...)), + new TwigFunction('impersonation_exit_url', $this->getImpersonateExitUrl(...)), + new TwigFunction('impersonation_exit_path', $this->getImpersonateExitPath(...)), ]; } } diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index 8371291d04f85..cbb7394e7d848 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -64,7 +64,7 @@ public function getTranslator(): TranslatorInterface public function getFunctions(): array { return [ - new TwigFunction('t', [$this, 'createTranslatable']), + new TwigFunction('t', $this->createTranslatable(...)), ]; } @@ -74,7 +74,7 @@ public function getFunctions(): array public function getFilters(): array { return [ - new TwigFilter('trans', [$this, 'trans']), + new TwigFilter('trans', $this->trans(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php index de2884a71b987..fcc34ecb5aad6 100644 --- a/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php @@ -37,12 +37,12 @@ public function __construct(RequestStack $requestStack) public function getFunctions(): array { return [ - new TwigFunction('link', [$this, 'link']), - new TwigFunction('preload', [$this, 'preload']), - new TwigFunction('dns_prefetch', [$this, 'dnsPrefetch']), - new TwigFunction('preconnect', [$this, 'preconnect']), - new TwigFunction('prefetch', [$this, 'prefetch']), - new TwigFunction('prerender', [$this, 'prerender']), + new TwigFunction('link', $this->link(...)), + new TwigFunction('preload', $this->preload(...)), + new TwigFunction('dns_prefetch', $this->dnsPrefetch(...)), + new TwigFunction('preconnect', $this->preconnect(...)), + new TwigFunction('prefetch', $this->prefetch(...)), + new TwigFunction('prerender', $this->prerender(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php index 2b13d29195afe..895faf457f648 100644 --- a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php @@ -38,13 +38,13 @@ public function __construct(Registry $workflowRegistry) public function getFunctions(): array { return [ - new TwigFunction('workflow_can', [$this, 'canTransition']), - new TwigFunction('workflow_transitions', [$this, 'getEnabledTransitions']), - new TwigFunction('workflow_transition', [$this, 'getEnabledTransition']), - new TwigFunction('workflow_has_marked_place', [$this, 'hasMarkedPlace']), - new TwigFunction('workflow_marked_places', [$this, 'getMarkedPlaces']), - new TwigFunction('workflow_metadata', [$this, 'getMetadata']), - new TwigFunction('workflow_transition_blockers', [$this, 'buildTransitionBlockerList']), + new TwigFunction('workflow_can', $this->canTransition(...)), + new TwigFunction('workflow_transitions', $this->getEnabledTransitions(...)), + new TwigFunction('workflow_transition', $this->getEnabledTransition(...)), + new TwigFunction('workflow_has_marked_place', $this->hasMarkedPlace(...)), + new TwigFunction('workflow_marked_places', $this->getMarkedPlaces(...)), + new TwigFunction('workflow_metadata', $this->getMetadata(...)), + new TwigFunction('workflow_transition_blockers', $this->buildTransitionBlockerList(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index 919834e24a5d6..2d0595b7e9bca 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -28,8 +28,8 @@ final class YamlExtension extends AbstractExtension public function getFilters(): array { return [ - new TwigFilter('yaml_encode', [$this, 'encode']), - new TwigFilter('yaml_dump', [$this, 'dump']), + new TwigFilter('yaml_encode', $this->encode(...)), + new TwigFilter('yaml_dump', $this->dump(...)), ]; } diff --git a/src/Symfony/Bridge/Twig/LICENSE b/src/Symfony/Bridge/Twig/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bridge/Twig/LICENSE +++ b/src/Symfony/Bridge/Twig/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php index e1b27046805a7..85e0ba93d42c9 100644 --- a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php +++ b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php @@ -85,7 +85,7 @@ private function getFingerPrint(TemplatedEmail $message): string $payload = [$messageContext, $message->getTextTemplate(), $message->getHtmlTemplate()]; try { $serialized = serialize($payload); - } catch (\Exception $e) { + } catch (\Exception) { // Serialization of 'Closure' is not allowed // Happens when context contain a closure, in that case, we assume that context always change. $serialized = random_bytes(8); diff --git a/src/Symfony/Bridge/Twig/Mime/NotificationEmail.php b/src/Symfony/Bridge/Twig/Mime/NotificationEmail.php index 084dc3489f270..49236d8feb12a 100644 --- a/src/Symfony/Bridge/Twig/Mime/NotificationEmail.php +++ b/src/Symfony/Bridge/Twig/Mime/NotificationEmail.php @@ -44,7 +44,7 @@ public function __construct(Headers $headers = null, AbstractPart $body = null) { $missingPackages = []; if (!class_exists(CssInlinerExtension::class)) { - $missingPackages['twig/cssinliner-extra'] = ' CSS Inliner'; + $missingPackages['twig/cssinliner-extra'] = 'CSS Inliner'; } if (!class_exists(InkyExtension::class)) { @@ -192,17 +192,12 @@ public function getPreparedHeaders(): Headers private function determinePriority(string $importance): int { - switch ($importance) { - case self::IMPORTANCE_URGENT: - return self::PRIORITY_HIGHEST; - case self::IMPORTANCE_HIGH: - return self::PRIORITY_HIGH; - case self::IMPORTANCE_MEDIUM: - return self::PRIORITY_NORMAL; - case self::IMPORTANCE_LOW: - default: - return self::PRIORITY_LOW; - } + return match ($importance) { + self::IMPORTANCE_URGENT => self::PRIORITY_HIGHEST, + self::IMPORTANCE_HIGH => self::PRIORITY_HIGH, + self::IMPORTANCE_MEDIUM => self::PRIORITY_NORMAL, + default => self::PRIORITY_LOW, + }; } private function getExceptionAsString(\Throwable|FlattenException $exception): string @@ -229,7 +224,7 @@ private function getExceptionAsString(\Throwable|FlattenException $exception): s */ public function __serialize(): array { - return [$this->context, parent::__serialize()]; + return [$this->context, $this->theme, parent::__serialize()]; } /** @@ -237,7 +232,12 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - [$this->context, $parentData] = $data; + if (3 === \count($data)) { + [$this->context, $this->theme, $parentData] = $data; + } else { + // Backwards compatibility for deserializing data structures that were serialized without the theme + [$this->context, $parentData] = $data; + } parent::__unserialize($parentData); } diff --git a/src/Symfony/Bridge/Twig/Mime/WrappedTemplatedEmail.php b/src/Symfony/Bridge/Twig/Mime/WrappedTemplatedEmail.php index e0b3bef29308f..956c5fdd71871 100644 --- a/src/Symfony/Bridge/Twig/Mime/WrappedTemplatedEmail.php +++ b/src/Symfony/Bridge/Twig/Mime/WrappedTemplatedEmail.php @@ -35,6 +35,12 @@ public function toName(): string return $this->message->getTo()[0]->getName(); } + /** + * @param string $image A Twig path to the image file. It's recommended to define + * some Twig namespace for email images (e.g. '@email/images/logo.png'). + * @param string|null $contentType The media type (i.e. MIME type) of the image file (e.g. 'image/png'). + * Some email clients require this to display embedded images. + */ public function image(string $image, string $contentType = null): string { $file = $this->twig->getLoader()->getSourceContext($image); @@ -47,6 +53,13 @@ public function image(string $image, string $contentType = null): string return 'cid:'.$image; } + /** + * @param string $file A Twig path to the file. It's recommended to define + * some Twig namespace for email files (e.g. '@email/files/contract.pdf'). + * @param string|null $name A custom file name that overrides the original name of the attached file. + * @param string|null $contentType The media type (i.e. MIME type) of the file (e.g. 'application/pdf'). + * Some email clients require this to display attached files. + */ public function attach(string $file, string $name = null, string $contentType = null): void { $file = $this->twig->getLoader()->getSourceContext($file); diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index 34cbc76074acd..865f9078a9658 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -101,7 +101,22 @@ {%- endif -%} {%- endif -%} - {{- widget|raw }} {{ label is not same as(false) ? (translation_domain is same as(false) ? (label_html is same as(false) ? label : label|raw) : (label_html is same as(false) ? label|trans(label_translation_parameters, translation_domain) : label|trans(label_translation_parameters, translation_domain)|raw)) -}} + {#- if statement must be kept on the same line, to force the space between widget and label -#} + {{- widget|raw }} {% if label is not same as(false) -%} + {%- if translation_domain is same as(false) -%} + {%- if label_html is same as(false) -%} + {{ label -}} + {%- else -%} + {{ label|raw -}} + {%- endif -%} + {%- else -%} + {%- if label_html is same as(false) -%} + {{ label|trans(label_translation_parameters, translation_domain) -}} + {%- else -%} + {{ label|trans(label_translation_parameters, translation_domain)|raw -}} + {%- endif -%} + {%- endif -%} + {%- endif -%} {%- endif -%} {%- endblock checkbox_radio_label %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index a75e364187743..990b324cb0d17 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -49,6 +49,7 @@ col-sm-2
{{- form_widget(form, widget_attr) -}} {{- form_help(form) -}} + {{- form_errors(form) -}}
{##} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index 0e80840541fa1..9aa6081e7e323 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -6,7 +6,7 @@ {%- set prepend = not (money_pattern starts with '{{') -%} {%- set append = not (money_pattern ends with '}}') -%} {%- if prepend or append -%} -
+
{%- if prepend -%}
{{ money_pattern|form_encode_currency }} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig index eef6f606edc14..22555ed88f4a8 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig @@ -6,7 +6,7 @@ {%- set prepend = not (money_pattern starts with '{{') -%} {%- set append = not (money_pattern ends with '}}') -%} {%- if prepend or append -%} -
+
{%- if prepend -%} {{ money_pattern|form_encode_currency }} {%- endif -%} @@ -213,10 +213,10 @@ {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} {%- set row_class = 'form-check' -%} {%- if 'checkbox-inline' in parent_label_class %} - {% set row_class = row_class ~ ' form-check-inline' %} + {%- set row_class = row_class ~ ' form-check-inline' -%} {% endif -%} {%- if 'checkbox-switch' in parent_label_class %} - {% set row_class = row_class ~ ' form-switch' %} + {%- set row_class = row_class ~ ' form-switch' -%} {% endif -%}
{{- form_label(form, null, { widget: parent() }) -}} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig index b8cb8c44aa832..e8b9318b3a8bf 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig @@ -11,7 +11,7 @@ {% set prepend = not (money_pattern starts with '{{') %} {% set append = not (money_pattern ends with '}}') %} {% if prepend or append %} -
+
{% if prepend %} {{ money_pattern|form_encode_currency }} {% endif %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 94f87dc165ec6..4769585c22772 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -325,7 +325,7 @@ {% block form_help -%} {%- if help is not empty -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-text')|trim}) -%} -

+

{%- if translation_domain is same as(false) -%} {%- if help_html is same as(false) -%} {{- help -}} @@ -339,7 +339,7 @@ {{- help|trans(help_translation_parameters, translation_domain)|raw -}} {%- endif -%} {%- endif -%} -

+
{%- endif -%} {%- endblock form_help %} diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index 462f9f7874879..6ba4ca77e51c4 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Twig\Tests; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php index 2488a27677af9..f0d7d661b1ff2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php @@ -299,10 +299,6 @@ public function testWithFilter() */ public function testComplete(array $input, array $expectedSuggestions) { - if (!class_exists(CommandCompletionTester::class)) { - $this->markTestSkipped('Test command completion requires symfony/console 5.4+.'); - } - $projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'; $loader = new FilesystemLoader([], $projectDir); $environment = new Environment($loader); diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index 6a3d640b2d5b2..6428f4860ba78 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -141,10 +141,6 @@ public function testLintAutodetectsGithubActionEnvironment() */ public function testComplete(array $input, array $expectedSuggestions) { - if (!class_exists(CommandCompletionTester::class)) { - $this->markTestSkipped('Test command completion requires symfony/console 5.4+.'); - } - $tester = new CommandCompletionTester($this->createCommand()); $this->assertSame($expectedSuggestions, $tester->complete($input)); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php index 3929877438132..c4874c3407092 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php @@ -21,7 +21,7 @@ public function testLabelOnForm() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/label + '/label [@class="col-sm-2 control-label required"] [.="[trans]Name[/trans]"] ' @@ -38,7 +38,7 @@ public function testLabelDoesNotRenderFieldAttributes() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="col-sm-2 control-label required"] ' @@ -55,7 +55,7 @@ public function testLabelWithCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-sm-2 control-label required"] ' @@ -72,7 +72,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-sm-2 control-label required"] [.="[trans]Custom label[/trans]"] @@ -92,7 +92,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-sm-2 control-label required"] [.="[trans]Custom label[/trans]"] @@ -203,7 +203,7 @@ public function testCheckboxRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group"] [ ./div[@class="col-sm-2" or @class="col-sm-10"] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php index 6e08f650bb963..808352300adf4 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap3LayoutTest.php @@ -25,7 +25,7 @@ public function testLabelOnForm() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/label + '/label [@class="control-label required"] [.="[trans]Name[/trans]"] ' @@ -42,7 +42,7 @@ public function testLabelDoesNotRenderFieldAttributes() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="control-label required"] ' @@ -59,7 +59,7 @@ public function testLabelWithCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class control-label required"] ' @@ -76,7 +76,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class control-label required"] [.="[trans]Custom label[/trans]"] @@ -96,7 +96,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class control-label required"] [.="[trans]Custom label[/trans]"] @@ -146,7 +146,7 @@ public function testHelp() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, -'/span + '/span [@id="name_help"] [@class="help-block"] [.="[trans]Help text test![/trans]"] @@ -266,7 +266,7 @@ public function testErrors() $html = $this->renderErrors($view); $this->assertMatchesXpath($html, -'/div + '/div [@class="alert alert-danger"] [ ./ul @@ -296,7 +296,7 @@ public function testOverrideWidgetBlock() $html = $this->renderWidget($form->createView()); $this->assertMatchesXpath($html, -'/div + '/div [ ./input [@type="text"] @@ -313,7 +313,7 @@ public function testCheckedCheckbox() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', true); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="checkbox"] [ ./label @@ -331,7 +331,7 @@ public function testUncheckedCheckbox() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="checkbox"] [ ./label @@ -351,7 +351,7 @@ public function testCheckboxWithValue() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="checkbox"] [ ./label @@ -370,7 +370,7 @@ public function testCheckboxRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group"] [ ./span[text() = "[trans]really helpful text[/trans]"] @@ -388,7 +388,7 @@ public function testSingleChoice() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -411,7 +411,7 @@ public function testSingleChoiceAttributesWithMainAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], -'/select + '/select [@name="name"] [@class="bar&baz form-control"] [not(@required)] @@ -434,7 +434,7 @@ public function testSingleExpandedChoiceAttributesWithMainAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], -'/div + '/div [@class="bar&baz"] [ ./div @@ -471,7 +471,7 @@ public function testSelectWithSizeBiggerThanOneCanBeRequired() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => '']], -'/select + '/select [@name="name"] [@required="required"] [@size="2"] @@ -490,7 +490,7 @@ public function testSingleChoiceWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -515,7 +515,7 @@ public function testSingleChoiceWithPlaceholderWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -539,7 +539,7 @@ public function testSingleChoiceAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -562,7 +562,7 @@ public function testSingleChoiceWithPreferred() ]); $this->assertWidgetMatchesXpath($form->createView(), ['separator' => '-- sep --', 'attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -587,7 +587,7 @@ public function testSingleChoiceWithSelectedPreferred() ]); $this->assertWidgetMatchesXpath($form->createView(), ['separator' => '-- sep --', 'attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -612,7 +612,7 @@ public function testSingleChoiceWithPreferredAndNoSeparator() ]); $this->assertWidgetMatchesXpath($form->createView(), ['separator' => null, 'attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -636,7 +636,7 @@ public function testSingleChoiceWithPreferredAndBlankSeparator() ]); $this->assertWidgetMatchesXpath($form->createView(), ['separator' => '', 'attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -661,7 +661,7 @@ public function testChoiceWithOnlyPreferred() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@class="my&class form-control"] [count(./option)=5] ' @@ -678,7 +678,7 @@ public function testSingleChoiceNonRequired() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -702,7 +702,7 @@ public function testSingleChoiceNonRequiredNoneSelected() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -727,7 +727,7 @@ public function testSingleChoiceNonRequiredWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -752,7 +752,7 @@ public function testSingleChoiceRequiredWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [@required="required"] @@ -776,7 +776,7 @@ public function testSingleChoiceRequiredWithPlaceholderViaView() ]); $this->assertWidgetMatchesXpath($form->createView(), ['placeholder' => '', 'attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [@required="required"] @@ -802,7 +802,7 @@ public function testSingleChoiceGrouped() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [./optgroup[@label="[trans]Group&1[/trans]"] @@ -831,7 +831,7 @@ public function testMultipleChoice() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name[]"] [@class="my&class form-control"] [@required="required"] @@ -856,7 +856,7 @@ public function testMultipleChoiceAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name[]"] [@class="my&class form-control"] [@required="required"] @@ -880,7 +880,7 @@ public function testMultipleChoiceSkipsPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name[]"] [@class="my&class form-control"] [@multiple="multiple"] @@ -903,7 +903,7 @@ public function testMultipleChoiceNonRequired() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name[]"] [@class="my&class form-control"] [@multiple="multiple"] @@ -925,7 +925,7 @@ public function testSingleChoiceExpanded() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -961,7 +961,7 @@ public function testSingleChoiceExpandedWithLabelsAsFalse() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1001,7 +1001,7 @@ public function testSingleChoiceExpandedWithLabelsSetByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1047,7 +1047,7 @@ public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1081,7 +1081,7 @@ public function testSingleChoiceExpandedWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1117,7 +1117,7 @@ public function testSingleChoiceExpandedAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1154,7 +1154,7 @@ public function testSingleChoiceExpandedWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1201,7 +1201,7 @@ public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1245,7 +1245,7 @@ public function testSingleChoiceExpandedWithBooleanValue() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="radio"] @@ -1281,7 +1281,7 @@ public function testMultipleChoiceExpanded() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="checkbox"] @@ -1326,7 +1326,7 @@ public function testMultipleChoiceExpandedWithLabelsAsFalse() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="checkbox"] @@ -1412,7 +1412,7 @@ public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="checkbox"] @@ -1447,7 +1447,7 @@ public function testMultipleChoiceExpandedWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="checkbox"] @@ -1493,7 +1493,7 @@ public function testMultipleChoiceExpandedAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="checkbox"] @@ -1533,7 +1533,7 @@ public function testCountry() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CountryType', 'AT'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [./option[@value="AT"][@selected="selected"][.="Austria"]] @@ -1550,7 +1550,7 @@ public function testCountryWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] @@ -1568,7 +1568,7 @@ public function testDateTime() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [ ./select [@id="name_date_month"] @@ -1605,7 +1605,7 @@ public function testDateTimeWithPlaceholderGlobal() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1644,7 +1644,7 @@ public function testDateTimeWithHourAndMinute() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1681,7 +1681,7 @@ public function testDateTimeWithSeconds() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1723,7 +1723,7 @@ public function testDateTimeSingleText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./input @@ -1753,7 +1753,7 @@ public function testDateTimeWithWidgetSingleText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="datetime-local"] [@name="name"] [@class="my&class form-control"] @@ -1775,7 +1775,7 @@ public function testDateChoice() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1806,7 +1806,7 @@ public function testDateChoiceWithPlaceholderGlobal() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1837,7 +1837,7 @@ public function testDateChoiceWithPlaceholderOnYear() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1866,7 +1866,7 @@ public function testDateText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./input @@ -1898,7 +1898,7 @@ public function testDateSingleText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="date"] [@name="name"] [@class="my&class form-control"] @@ -1914,7 +1914,7 @@ public function testBirthDay() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1944,7 +1944,7 @@ public function testBirthDayWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -1973,7 +1973,7 @@ public function testEmail() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="email"] [@name="name"] [@class="my&class form-control"] @@ -1990,7 +1990,7 @@ public function testEmailWithMaxLength() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="email"] [@name="name"] [@class="my&class form-control"] @@ -2005,7 +2005,7 @@ public function testHidden() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\HiddenType', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="hidden"] [@name="name"] [@class="my&class"] @@ -2021,7 +2021,7 @@ public function testDisabled() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] @@ -2035,7 +2035,7 @@ public function testInteger() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="number"] [@name="name"] [@class="my&class form-control"] @@ -2051,7 +2051,7 @@ public function testIntegerTypeWithGroupingRendersAsTextInput() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] @@ -2065,7 +2065,7 @@ public function testLanguage() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LanguageType', 'de'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [./option[@value="de"][@selected="selected"][.="German"]] @@ -2079,7 +2079,7 @@ public function testLocale() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LocaleType', 'de_AT'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [./option[@value="de_AT"][@selected="selected"][.="German (Austria)"]] @@ -2095,7 +2095,7 @@ public function testMoney() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="input-group"] [ ./span @@ -2119,7 +2119,7 @@ public function testMoneyWithoutCurrency() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/input + '/input [@id="my&id"] [@type="text"] [@name="name"] @@ -2136,7 +2136,7 @@ public function testNumber() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\NumberType', 1234.56); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] @@ -2166,7 +2166,7 @@ public function testPassword() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="password"] [@name="name"] [@class="my&class form-control"] @@ -2182,7 +2182,7 @@ public function testPasswordSubmittedWithNotAlwaysEmpty() $form->submit('foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="password"] [@name="name"] [@class="my&class form-control"] @@ -2198,7 +2198,7 @@ public function testPasswordWithMaxLength() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="password"] [@name="name"] [@class="my&class form-control"] @@ -2212,7 +2212,7 @@ public function testPercent() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PercentType', 0.1, ['rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="input-group"] [ ./input @@ -2233,7 +2233,7 @@ public function testPercentNoSymbol() { $form = $this->factory->createNamed('name', PercentType::class, 0.1, ['symbol' => false, 'rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/input + '/input [@id="my&id"] [@type="text"] [@name="name"] @@ -2247,7 +2247,7 @@ public function testPercentCustomSymbol() { $form = $this->factory->createNamed('name', PercentType::class, 0.1, ['symbol' => '‱', 'rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="input-group"] [ ./input @@ -2269,7 +2269,7 @@ public function testCheckedRadio() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', true); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="radio"] [ ./label @@ -2293,7 +2293,7 @@ public function testUncheckedRadio() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="radio"] [ ./label @@ -2318,7 +2318,7 @@ public function testRadioWithValue() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="radio"] [ ./label @@ -2342,7 +2342,7 @@ public function testRadioRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group"] [ ./span[text() = "[trans]really helpful text[/trans]"] @@ -2356,7 +2356,7 @@ public function testRange() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5]]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="range"] [@name="name"] [@value="42"] @@ -2371,7 +2371,7 @@ public function testRangeWithMinMaxValues() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5, 'max' => 57]]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="range"] [@name="name"] [@value="42"] @@ -2389,7 +2389,7 @@ public function testTextarea() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/textarea + '/textarea [@name="name"] [not(@pattern)] [@class="my&class form-control"] @@ -2403,7 +2403,7 @@ public function testText() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] @@ -2420,7 +2420,7 @@ public function testTextWithMaxLength() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] @@ -2435,7 +2435,7 @@ public function testSearch() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\SearchType', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="search"] [@name="name"] [@class="my&class form-control"] @@ -2453,7 +2453,7 @@ public function testTime() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -2480,7 +2480,7 @@ public function testTimeWithSeconds() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -2515,7 +2515,7 @@ public function testTimeText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./input @@ -2548,7 +2548,7 @@ public function testTimeSingleText() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="time"] [@name="name"] [@class="my&class form-control"] @@ -2567,7 +2567,7 @@ public function testTimeWithPlaceholderGlobal() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -2594,7 +2594,7 @@ public function testTimeWithPlaceholderOnYear() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/div + '/div [@class="my&class form-inline"] [ ./select @@ -2617,7 +2617,7 @@ public function testTimezone() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimezoneType', 'Europe/Vienna'); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@name="name"] [@class="my&class form-control"] [not(@required)] @@ -2635,7 +2635,7 @@ public function testTimezoneWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/select + '/select [@class="my&class form-control"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] [count(.//option)>201] @@ -2649,7 +2649,7 @@ public function testUrlWithDefaultProtocol() $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => 'http']); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="text"] [@name="name"] [@class="my&class form-control"] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php index 39d49d97a0bd6..1ef14ecf4dc0f 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php @@ -53,7 +53,7 @@ public function testLabelOnForm() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/legend + '/legend [@class="col-form-label col-sm-2 col-form-label required"] [.="[trans]Name[/trans]"] ' @@ -70,7 +70,7 @@ public function testLabelDoesNotRenderFieldAttributes() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="col-form-label col-sm-2 required"] ' @@ -87,7 +87,7 @@ public function testLabelWithCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] ' @@ -104,7 +104,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] [.="[trans]Custom label[/trans]"] @@ -124,7 +124,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] [.="[trans]Custom label[/trans]"] @@ -177,7 +177,7 @@ public function testLegendOnExpandedType() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/legend + '/legend [@class="col-sm-2 col-form-label required"] [.="[trans]Custom label[/trans]"] ' @@ -255,7 +255,7 @@ public function testCheckboxRowWithHelp() $html = $this->renderRow($view, ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group row"] [ ./div[@class="col-sm-2" or @class="col-sm-10"] @@ -274,7 +274,7 @@ public function testRadioRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group row"] [ ./div[@class="col-sm-2" or @class="col-sm-10"] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4LayoutTest.php index 61006607c33e0..8689df830b290 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap4LayoutTest.php @@ -63,7 +63,7 @@ public function testLabelOnForm() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/legend + '/legend [@class="col-form-label required"] [.="[trans]Name[/trans]"] ' @@ -80,7 +80,7 @@ public function testLabelDoesNotRenderFieldAttributes() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="required"] ' @@ -97,7 +97,7 @@ public function testLabelWithCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class required"] ' @@ -114,7 +114,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] @@ -134,7 +134,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] @@ -187,7 +187,7 @@ public function testLegendOnExpandedType() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/legend + '/legend [@class="col-form-label required"] [.="[trans]Custom label[/trans]"] ' @@ -203,7 +203,7 @@ public function testHelp() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, -'/small + '/small [@id="name_help"] [@class="form-text text-muted"] [.="[trans]Help text test![/trans]"] @@ -323,7 +323,7 @@ public function testErrors() $html = $this->renderErrors($view); $this->assertMatchesXpath($html, -'/span + '/span [@class="alert alert-danger d-block"] [ ./span[@class="d-block"] @@ -354,7 +354,7 @@ public function testCheckedCheckbox() $form = $this->factory->createNamed('name', CheckboxType::class, true); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@checked="checked"][@value="1"] @@ -376,7 +376,7 @@ public function testSingleChoiceAttributesWithMainAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], -'/select + '/select [@name="name"] [@class="bar&baz form-control"] [not(@required)] @@ -399,7 +399,7 @@ public function testSingleExpandedChoiceAttributesWithMainAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], -'/div + '/div [@class="bar&baz"] [ ./div @@ -427,7 +427,7 @@ public function testUncheckedCheckbox() $form = $this->factory->createNamed('name', CheckboxType::class, false); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][not(@checked)] @@ -445,7 +445,7 @@ public function testCheckboxWithValue() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@value="foo&bar"] @@ -480,7 +480,7 @@ public function testSingleChoiceExpanded() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -512,7 +512,7 @@ public function testSingleChoiceExpandedWithLabelsAsFalse() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -548,7 +548,7 @@ public function testSingleChoiceExpandedWithLabelsSetByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -588,7 +588,7 @@ public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -618,7 +618,7 @@ public function testSingleChoiceExpandedWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -650,7 +650,7 @@ public function testSingleChoiceExpandedAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -683,7 +683,7 @@ public function testSingleChoiceExpandedWithPlaceholder() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -724,7 +724,7 @@ public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -762,7 +762,7 @@ public function testSingleChoiceExpandedWithBooleanValue() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -794,7 +794,7 @@ public function testMultipleChoiceExpanded() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -833,7 +833,7 @@ public function testMultipleChoiceExpandedWithLabelsAsFalse() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -909,7 +909,7 @@ public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -940,7 +940,7 @@ public function testMultipleChoiceExpandedWithoutTranslation() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -980,7 +980,7 @@ public function testMultipleChoiceExpandedAttributes() ]); $this->assertWidgetMatchesXpath($form->createView(), [], -'/div + '/div [ ./div [@class="form-check"] @@ -1014,7 +1014,7 @@ public function testCheckedRadio() $form = $this->factory->createNamed('name', RadioType::class, true); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input @@ -1036,7 +1036,7 @@ public function testUncheckedRadio() $form = $this->factory->createNamed('name', RadioType::class, false); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input @@ -1059,7 +1059,7 @@ public function testRadioWithValue() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="form-check"] [ ./input @@ -1082,7 +1082,7 @@ public function testRadioRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="form-group"] [ ./small[text() = "[trans]really helpful text[/trans]"] @@ -1108,7 +1108,7 @@ public function testFile() $form = $this->factory->createNamed('name', FileType::class); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'n/a', 'attr' => ['class' => 'my&class form-control-file']], -'/div + '/div [@class="custom-file"] [ ./input @@ -1126,7 +1126,7 @@ public function testFileLabelIdNotDuplicated() $form = $this->factory->createNamed('name', FileType::class); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'n/a', 'attr' => ['class' => 'my&class form-control-file'], 'label_attr' => ['id' => 'label-id']], -'/div + '/div [@class="custom-file"] [ ./input @@ -1144,7 +1144,7 @@ public function testFileWithPlaceholder() $form = $this->factory->createNamed('name', FileType::class); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'n/a', 'attr' => ['class' => 'my&class form-control-file', 'placeholder' => 'Custom Placeholder']], -'/div + '/div [@class="custom-file"] [ ./input @@ -1164,8 +1164,8 @@ public function testMoney() ]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div - [@class="input-group"] + '/div + [@class="input-group "] [ ./div [@class="input-group-prepend"] @@ -1190,7 +1190,7 @@ public function testPercent() $form = $this->factory->createNamed('name', PercentType::class, 0.1, ['rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="input-group"] [ ./input @@ -1215,7 +1215,7 @@ public function testPercentNoSymbol() { $form = $this->factory->createNamed('name', PercentType::class, 0.1, ['symbol' => false, 'rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/input + '/input [@id="my&id"] [@type="text"] [@name="name"] @@ -1229,7 +1229,7 @@ public function testPercentCustomSymbol() { $form = $this->factory->createNamed('name', PercentType::class, 0.1, ['symbol' => '‱', 'rounding_mode' => \NumberFormatter::ROUND_CEILING]); $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], -'/div + '/div [@class="input-group"] [ ./input @@ -1257,7 +1257,7 @@ public function testRange() $this->assertWidgetMatchesXpath( $form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="range"] [@name="name"] [@value="42"] @@ -1274,7 +1274,7 @@ public function testRangeWithMinMaxValues() $this->assertWidgetMatchesXpath( $form->createView(), ['attr' => ['class' => 'my&class']], -'/input + '/input [@type="range"] [@name="name"] [@value="42"] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5HorizontalLayoutTest.php index 9fe231bfa1198..e6a8846c4b127 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5HorizontalLayoutTest.php @@ -109,7 +109,7 @@ public function testLabelDoesNotRenderFieldAttributes() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="col-form-label col-sm-2 required"] ' @@ -126,7 +126,7 @@ public function testLabelWithCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] ' @@ -143,7 +143,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] [.="[trans]Custom label[/trans]"] @@ -163,7 +163,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ]); $this->assertMatchesXpath($html, -'/label + '/label [@for="name"] [@class="my&class col-form-label col-sm-2 required"] [.="[trans]Custom label[/trans]"] @@ -216,7 +216,7 @@ public function testLegendOnExpandedType() $html = $this->renderLabel($view); $this->assertMatchesXpath($html, -'/legend + '/legend [@class="col-sm-2 col-form-label required"] [.="[trans]Custom label[/trans]"] ' @@ -239,13 +239,13 @@ public function testCheckboxRowWithHelp() $html = $this->renderRow($view, ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="mb-3 row"] [ ./div[@class="col-sm-2" or @class="col-sm-10"] /following-sibling::div[@class="col-sm-2" or @class="col-sm-10"] [ - ./p + ./div [@class="form-text mb-0 help-text"] [.="[trans]really helpful text[/trans]"] ] @@ -260,13 +260,13 @@ public function testRadioRowWithHelp() $html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']); $this->assertMatchesXpath($html, -'/div + '/div [@class="mb-3 row"] [ ./div[@class="col-sm-2" or @class="col-sm-10"] /following-sibling::div[@class="col-sm-2" or @class="col-sm-10"] [ - ./p + ./div [@class="form-text mb-0 help-text"] [.="[trans]really helpful text[/trans]"] ] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5LayoutTest.php index ff35789a564cd..d9bb0c17bde97 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractBootstrap5LayoutTest.php @@ -198,7 +198,7 @@ public function testHelp() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] [.="[trans]Help text test![/trans]"] @@ -218,7 +218,7 @@ public function testHelpAttr() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="class-test form-text mb-0 help-text"] [.="[trans]Help text test![/trans]"] @@ -236,7 +236,7 @@ public function testHelpHtmlDefaultIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] [.="[trans]Help text test![/trans]"] @@ -244,7 +244,7 @@ public function testHelpHtmlDefaultIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] /b @@ -264,7 +264,7 @@ public function testHelpHtmlIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] [.="[trans]Help text test![/trans]"] @@ -272,7 +272,7 @@ public function testHelpHtmlIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] /b @@ -290,7 +290,7 @@ public function testHelpHtmlIsTrue() $html = $this->renderHelp($form->createView()); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] [.="[trans]Help text test![/trans]"] @@ -298,7 +298,7 @@ public function testHelpHtmlIsTrue() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="form-text mb-0 help-text"] /b @@ -377,7 +377,7 @@ public function testCheckboxRowWithHelp() [@for="name"] [.="[trans]foo[/trans]"] ] - /following-sibling::p + /following-sibling::div [@class="form-text mb-0 help-text"] [.="[trans]really helpful text[/trans]"] ] @@ -871,7 +871,7 @@ public function testRadioRowWithHelp() '/div [@class="mb-3"] [ - ./p + ./div [@class="form-text mb-0 help-text"] [.="[trans]really helpful text[/trans]"] ] @@ -1450,7 +1450,7 @@ public function testMoney() $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], '/div - [@class="input-group"] + [@class="input-group "] [ ./span [@class="input-group-text"] diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index b02d859f74856..a3a6c751a0718 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -102,7 +102,7 @@ public function testMoneyWidgetInIso()
HTML - , trim($this->renderWidget($view))); + , trim($this->renderWidget($view))); } protected function renderForm(FormView $view, array $vars = []) diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index 41985a8ce2d85..00fee10edb2fc 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -102,11 +102,11 @@ public function testMoneyWidgetInIso() ; $this->assertSame(<<<'HTML' -
+
HTML - , trim($this->renderWidget($view))); + , trim($this->renderWidget($view))); } protected function renderForm(FormView $view, array $vars = []) diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php index 8c0e54744f964..ed69ca81c3375 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php @@ -104,7 +104,7 @@ public function testMoneyWidgetInIso() ->createView(); self::assertSame(<<<'HTML' -
+
HTML , trim($this->renderWidget($view))); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index e7991240f03f5..cae1a1c6e6b4d 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -203,7 +203,7 @@ public function testHelpAttr() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="class-test help-text"] [.="[trans]Help text test![/trans]"] @@ -221,7 +221,7 @@ public function testHelpHtmlDefaultIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -229,7 +229,7 @@ public function testHelpHtmlDefaultIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b @@ -249,7 +249,7 @@ public function testHelpHtmlIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -257,7 +257,7 @@ public function testHelpHtmlIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b @@ -277,7 +277,7 @@ public function testHelpHtmlIsTrue() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -285,7 +285,7 @@ public function testHelpHtmlIsTrue() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 20b465418daea..7b75be234da3a 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -89,7 +89,7 @@ public function testHelpAttr() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="class-test help-text"] [.="[trans]Help text test![/trans]"] @@ -107,7 +107,7 @@ public function testHelpHtmlDefaultIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -115,7 +115,7 @@ public function testHelpHtmlDefaultIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b @@ -135,7 +135,7 @@ public function testHelpHtmlIsFalse() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -143,7 +143,7 @@ public function testHelpHtmlIsFalse() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b @@ -163,7 +163,7 @@ public function testHelpHtmlIsTrue() $html = $this->renderHelp($view); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] [.="[trans]Help text test![/trans]"] @@ -171,7 +171,7 @@ public function testHelpHtmlIsTrue() ); $this->assertMatchesXpath($html, - '/p + '/div [@id="name_help"] [@class="help-text"] /b diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HtmlSanitizerExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HtmlSanitizerExtensionTest.php new file mode 100644 index 0000000000000..23755d0317be2 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HtmlSanitizerExtensionTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Twig\Extension\HtmlSanitizerExtension; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; +use Twig\Environment; +use Twig\Loader\ArrayLoader; + +class HtmlSanitizerExtensionTest extends TestCase +{ + public function testSanitizeHtml() + { + $loader = new ArrayLoader([ + 'foo' => '{{ "foobar"|sanitize_html }}', + 'bar' => '{{ "foobar"|sanitize_html("bar") }}', + ]); + + $twig = new Environment($loader, ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); + + $fooSanitizer = $this->createMock(HtmlSanitizerInterface::class); + $fooSanitizer->expects($this->once()) + ->method('sanitize') + ->with('foobar') + ->willReturn('foo'); + + $barSanitizer = $this->createMock(HtmlSanitizerInterface::class); + $barSanitizer->expects($this->once()) + ->method('sanitize') + ->with('foobar') + ->willReturn('bar'); + + $twig->addExtension(new HtmlSanitizerExtension(new ServiceLocator([ + 'foo' => fn () => $fooSanitizer, + 'bar' => fn () => $barSanitizer, + ]), 'foo')); + + $this->assertSame('foo', $twig->render('foo')); + $this->assertSame('bar', $twig->render('bar')); + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php index ea3bb17bb3038..131cb3d040a4b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php @@ -60,10 +60,6 @@ public function getGenerateAbsoluteUrlData() */ public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected) { - if (!class_exists(RequestContext::class)) { - $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.'); - } - $requestContext = new RequestContext($baseUrl, 'GET', $host, $scheme, $httpPort, $httpsPort, $path); $extension = new HttpFoundationExtension(new UrlHelper(new RequestStack(), $requestContext)); @@ -75,10 +71,6 @@ public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host */ public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path) { - if (!class_exists(RequestContext::class)) { - $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.'); - } - $extension = new HttpFoundationExtension(new UrlHelper(new RequestStack())); $this->assertEquals($path, $extension->generateAbsoluteUrl($path)); @@ -118,10 +110,6 @@ public function testGenerateAbsoluteUrlWithScriptFileName() */ public function testGenerateRelativePath($expected, $path, $pathinfo) { - if (!method_exists(Request::class, 'getRelativeUriForPath')) { - $this->markTestSkipped('Your version of Symfony HttpFoundation is too old.'); - } - $stack = new RequestStack(); $stack->push(Request::create($pathinfo)); $extension = new HttpFoundationExtension(new UrlHelper($stack)); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php index a3294db0d2ae6..a53e64a425390 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php @@ -58,10 +58,6 @@ public function testUnknownFragmentRenderer() public function testGenerateFragmentUri() { - if (!class_exists(FragmentUriGenerator::class)) { - $this->markTestSkipped('HttpKernel 5.3+ is required'); - } - $requestStack = new RequestStack(); $requestStack->push(Request::create('/')); @@ -74,7 +70,7 @@ public function testGenerateFragmentUri() 'index' => sprintf(<< true, 'cache' => false]); $twig->addExtension(new HttpKernelExtension()); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php index 23dcc64b3d418..1252efb8d6ee0 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php @@ -30,10 +30,6 @@ class WorkflowExtensionTest extends TestCase protected function setUp(): void { - if (!class_exists(Workflow::class)) { - $this->markTestSkipped('The Workflow component is needed to run tests for this extension.'); - } - $places = ['ordered', 'waiting_for_payment', 'processed']; $transitions = [ $this->t1 = new Transition('t1', 'ordered', 'waiting_for_payment'), @@ -110,9 +106,6 @@ public function testGetMarkedPlaces() public function testGetMetadata() { - if (!class_exists(InMemoryMetadataStore::class)) { - $this->markTestSkipped('This test requires symfony/workflow:4.1.'); - } $subject = new Subject(); $this->assertSame('workflow title', $this->extension->getMetadata($subject, 'title')); @@ -124,9 +117,6 @@ public function testGetMetadata() public function testbuildTransitionBlockerList() { - if (!class_exists(TransitionBlockerList::class)) { - $this->markTestSkipped('This test requires symfony/workflow:4.1.'); - } $subject = new Subject(); $list = $this->extension->buildTransitionBlockerList($subject, 't1'); diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/NotificationEmailTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/NotificationEmailTest.php index 6eed243690387..ceafea1bb6b72 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/NotificationEmailTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/NotificationEmailTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Twig\Tests\Mime; use PHPUnit\Framework\TestCase; @@ -38,6 +47,7 @@ public function testSerialize() ->importance(NotificationEmail::IMPORTANCE_HIGH) ->action('Bar', 'http://example.com/') ->context(['a' => 'b']) + ->theme('example') )); $this->assertEquals([ 'importance' => NotificationEmail::IMPORTANCE_HIGH, @@ -50,6 +60,8 @@ public function testSerialize() 'a' => 'b', 'footer_text' => 'Notification e-mail sent by Symfony', ], $email->getContext()); + + $this->assertSame('@email/example/notification/body.html.twig', $email->getHtmlTemplate()); } public function testTheme() diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php index 2da04921446eb..b21017193251d 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Twig\Tests\Mime; use PHPUnit\Framework\TestCase; @@ -64,11 +73,9 @@ public function testSymfonySerialize() "html": null, "htmlCharset": null, "attachments": [ - { - "body": "Some Text file", - "name": "test.txt", - "content-type": null, - "inline": false + {%A + "body": "Some Text file",%A + "name": "test.txt",%A } ], "headers": { @@ -101,12 +108,12 @@ public function testSymfonySerialize() $propertyNormalizer, ], [new JsonEncoder()]); - $serialized = $serializer->serialize($e, 'json'); - $this->assertSame($expectedJson, json_encode(json_decode($serialized), \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); + $serialized = $serializer->serialize($e, 'json', [ObjectNormalizer::IGNORED_ATTRIBUTES => ['cachedBody']]); + $this->assertStringMatchesFormat($expectedJson, json_encode(json_decode($serialized), \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); $n = $serializer->deserialize($serialized, TemplatedEmail::class, 'json'); - $serialized = $serializer->serialize($e, 'json'); - $this->assertSame($expectedJson, json_encode(json_decode($serialized), \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); + $serialized = $serializer->serialize($e, 'json', [ObjectNormalizer::IGNORED_ATTRIBUTES => ['cachedBody']]); + $this->assertStringMatchesFormat($expectedJson, json_encode(json_decode($serialized), \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); $n->from('fabien@symfony.com'); $expected->from('fabien@symfony.com'); diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 89d4460fa98cb..ab45b83fecd72 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -64,7 +64,7 @@ public function testCompile() sprintf( '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, [0 => "tpl1", 1 => "tpl2"], true);', $this->getVariableGetter('form') - ), + ), trim($compiler->compile($node)->getSource()) ); @@ -74,7 +74,7 @@ public function testCompile() sprintf( '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, [0 => "tpl1", 1 => "tpl2"], false);', $this->getVariableGetter('form') - ), + ), trim($compiler->compile($node)->getSource()) ); @@ -86,7 +86,7 @@ public function testCompile() sprintf( '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1", true);', $this->getVariableGetter('form') - ), + ), trim($compiler->compile($node)->getSource()) ); @@ -96,7 +96,7 @@ public function testCompile() sprintf( '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1", false);', $this->getVariableGetter('form') - ), + ), trim($compiler->compile($node)->getSource()) ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index 59a8b10a9d065..42cb1762b050d 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -38,7 +38,7 @@ public function testCompileWidget() sprintf( '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'widget\')', $this->getVariableGetter('form') - ), + ), trim($compiler->compile($node)->getSource()) ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 72997273aced1..c6d3064676937 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -38,8 +38,8 @@ public function testCompileStrict() 'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans("trans %%var%%", array_merge(["%%var%%" => %s], %s), "messages");', $this->getVariableGetterWithoutStrictCheck('var'), $this->getVariableGetterWithStrictCheck('foo') - ), - trim($compiler->compile($node)->getSource()) + ), + trim($compiler->compile($node)->getSource()) ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php index 4a8b4d19c066e..c93bd718bc903 100644 --- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php @@ -41,7 +41,6 @@ public function testExtract($template, $messages) $catalogue = new MessageCatalogue('en'); $m = new \ReflectionMethod($extractor, 'extractTemplate'); - $m->setAccessible(true); $m->invoke($extractor, $template, $catalogue); if (0 === \count($messages)) { diff --git a/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php index f0b3ac2e9240e..b332485d02577 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php @@ -42,7 +42,7 @@ public function parse(Token $token): Node $stream->expect(Token::BLOCK_END_TYPE); // {% endstopwatch %} - $body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true); + $body = $this->parser->subparse($this->decideStopwatchEnd(...), true); $stream->expect(Token::BLOCK_END_TYPE); if ($this->stopwatchIsAvailable) { diff --git a/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php index ffe8828590852..b440931bba794 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php @@ -69,7 +69,7 @@ public function parse(Token $token): Node // {% trans %}message{% endtrans %} $stream->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse([$this, 'decideTransFork'], true); + $body = $this->parser->subparse($this->decideTransFork(...), true); if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()); diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php index b53ab80df2747..86ef269328530 100644 --- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php +++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Translation; +use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Component\Finder\Finder; use Symfony\Component\Translation\Extractor\AbstractFileExtractor; use Symfony\Component\Translation\Extractor\ExtractorInterface; @@ -52,7 +53,7 @@ public function extract($resource, MessageCatalogue $catalogue) foreach ($this->extractFiles($resource) as $file) { try { $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); - } catch (Error $e) { + } catch (Error) { // ignore errors, these should be fixed by using the linter } } @@ -68,7 +69,7 @@ public function setPrefix(string $prefix) protected function extractTemplate(string $template, MessageCatalogue $catalogue) { - $visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor(); + $visitor = $this->twig->getExtension(TranslationExtension::class)->getTranslationNodeVisitor(); $visitor->enable(); $this->twig->parse($this->twig->tokenize(new Source($template, ''))); diff --git a/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php index 30dd92ff2ff3b..c4d3971edcaff 100644 --- a/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php +++ b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig; +use Composer\InstalledVersions; use Symfony\Bundle\FullStack; use Twig\Error\SyntaxError; use Twig\TwigFilter; @@ -24,6 +25,7 @@ class UndefinedCallableHandler private const FILTER_COMPONENTS = [ 'humanize' => 'form', 'trans' => 'translation', + 'sanitize_html' => 'html-sanitizer', 'yaml_encode' => 'yaml', 'yaml_dump' => 'yaml', ]; @@ -61,6 +63,7 @@ class UndefinedCallableHandler ]; private const FULL_STACK_ENABLE = [ + 'html-sanitizer' => 'enable "framework.html_sanitizer"', 'form' => 'enable "framework.form"', 'security-core' => 'add the "SecurityBundle"', 'security-http' => 'add the "SecurityBundle"', @@ -96,6 +99,12 @@ private static function onUndefined(string $name, string $type, string $componen return sprintf('Did you forget to %s? Unknown %s "%s".', self::FULL_STACK_ENABLE[$component], $type, $name); } - return sprintf('Did you forget to run "composer require symfony/%s"? Unknown %s "%s".', $component, $type, $name); + $missingPackage = 'symfony/'.$component; + + if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled($missingPackage)) { + $missingPackage = 'symfony/twig-bundle'; + } + + return sprintf('Did you forget to run "composer require %s"? Unknown %s "%s".', $missingPackage, $type, $name); } } diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 0765818346b6d..974e2f3cd891a 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -16,18 +16,19 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/translation-contracts": "^1.1|^2|^3", "twig/twig": "^2.13|^3.0.4" }, "require-dev": { - "doctrine/annotations": "^1.12", - "egulias/email-validator": "^2.1.10|^3", + "doctrine/annotations": "^1.12|^2", + "egulias/email-validator": "^2.1.10|^3|^4", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/asset": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", + "symfony/form": "^6.1", + "symfony/html-sanitizer": "^6.1", "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", @@ -55,7 +56,7 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/console": "<5.4", - "symfony/form": "<5.4", + "symfony/form": "<6.1", "symfony/http-foundation": "<5.4", "symfony/http-kernel": "<5.4", "symfony/translation": "<5.4", @@ -65,6 +66,7 @@ "symfony/finder": "", "symfony/asset": "For using the AssetExtension", "symfony/form": "For using the FormExtension", + "symfony/html-sanitizer": "For using the HtmlSanitizerExtension", "symfony/http-kernel": "For using the HttpKernelExtension", "symfony/routing": "For using the RoutingExtension", "symfony/translation": "For using the TranslationExtension", diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php index 9843893088074..f645a48f8a3b1 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php @@ -56,7 +56,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->values(['dark', 'light']) ->defaultValue('dark') ->end() - ; + ; return $treeBuilder; } diff --git a/src/Symfony/Bundle/DebugBundle/LICENSE b/src/Symfony/Bundle/DebugBundle/LICENSE index a843ec124ea70..72412a62b2029 100644 --- a/src/Symfony/Bundle/DebugBundle/LICENSE +++ b/src/Symfony/Bundle/DebugBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2022 Fabien Potencier +Copyright (c) 2014-2023 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 diff --git a/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig index 7f078b93ac34c..ee009cc6fa508 100644 --- a/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig +++ b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig @@ -3,7 +3,7 @@ {% block toolbar %} {% if collector.dumpsCount %} {% set icon %} - {{ include('@Debug/Profiler/icon.svg') }} + {{ source('@Debug/Profiler/icon.svg') }} {{ collector.dumpsCount }} {% endset %} @@ -35,7 +35,7 @@ {% block menu %} - {{ include('@Debug/Profiler/icon.svg') }} + {{ source('@Debug/Profiler/icon.svg') }} Debug {% endblock %} diff --git a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php index 31afae4d93acb..f026d4d188232 100644 --- a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php +++ b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php @@ -43,10 +43,6 @@ public function testLoadWithoutConfiguration() public function testUnsetClosureFileInfoShouldBeRegisteredInVarCloner() { - if (!method_exists(ReflectionCaster::class, 'unsetClosureFileInfo')) { - $this->markTestSkipped('Method not available'); - } - $container = $this->createContainer(); $container->registerExtension(new DebugExtension()); $container->loadFromExtension('debug', []); diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 6dc3f8c126b0a..619db7d66feed 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -16,15 +16,15 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "ext-xml": "*", + "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/twig-bridge": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, "require-dev": { "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", "symfony/web-profiler-bundle": "^5.4|^6.0" }, "conflict": { diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 7c5a2c90398cd..40698a59a6023 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,9 +4,18 @@ CHANGELOG 6.1 --- - * Environment variable `SYMFONY_IDE` is read by default when `framework.ide` config is not set. + * Add support for configuring semaphores + * Environment variable `SYMFONY_IDE` is read by default when `framework.ide` config is not set * Load PHP configuration files by default in the `MicroKernelTrait` * Add `cache:pool:invalidate-tags` command + * Add `xliff` support in addition to `xlf` for `XliffFileDumper` + * Deprecate the `reset_on_message` config option. It can be set to `true` only and does nothing now + * Add `trust_x_sendfile_type_header` option + * Add support for first-class callable route controller in `MicroKernelTrait` + * Add tag `routing.condition_service` to autoconfigure routing condition services + * Automatically register kernel methods marked with the `Symfony\Component\Routing\Annotation\Route` attribute or annotation as controllers in `MicroKernelTrait` + * Deprecate not setting the `http_method_override` config option. The default value will change to `false` in 7.0. + * Add `framework.profiler.collect_serializer_data` config option, set it to `true` to enable the serializer data collector and profiler panel 6.0 --- diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php index 097a356008a5b..f72df9e6542bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -78,7 +78,7 @@ final protected function ignoreAutoloadException(string $class, \Exception $exce { try { ClassExistenceResource::throwOnRequiredClass($class, $exception); - } catch (\ReflectionException $e) { + } catch (\ReflectionException) { } } diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php index 6bc39acc27923..2fd5f661d2dee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php @@ -85,7 +85,7 @@ private function readAllComponents(Reader $reader, string $class) try { $reader->getClassAnnotations($reflectionClass); - } catch (AnnotationException $e) { + } catch (AnnotationException) { /* * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly * configured or could not be found / read / etc. @@ -99,14 +99,14 @@ private function readAllComponents(Reader $reader, string $class) foreach ($reflectionClass->getMethods() as $reflectionMethod) { try { $reader->getMethodAnnotations($reflectionMethod); - } catch (AnnotationException $e) { + } catch (AnnotationException) { } } foreach ($reflectionClass->getProperties() as $reflectionProperty) { try { $reader->getPropertyAnnotations($reflectionProperty); - } catch (AnnotationException $e) { + } catch (AnnotationException) { } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php index 4aae3ba96eaf5..ccc1402e2ddfe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php @@ -54,7 +54,7 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool foreach ($loader->getMappedClasses() as $mappedClass) { try { $metadataFactory->getMetadataFor($mappedClass); - } catch (AnnotationException $e) { + } catch (AnnotationException) { // ignore failing annotations } catch (\Exception $e) { $this->ignoreAutoloadException($mappedClass, $e); diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php index e28e21eb98324..04025a49bba66 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php @@ -57,7 +57,7 @@ protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter): bool if ($metadataFactory->hasMetadataFor($mappedClass)) { $metadataFactory->getMetadataFor($mappedClass); } - } catch (AnnotationException $e) { + } catch (AnnotationException) { // ignore failing annotations } catch (\Exception $e) { $this->ignoreAutoloadException($mappedClass, $e); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 8057460738f00..ed5a47f12a0f7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -87,8 +87,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int ['Architecture', (\PHP_INT_SIZE * 8).' bits'], ['Intl locale', class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], ['Timezone', date_default_timezone_get().' ('.(new \DateTime())->format(\DateTime::W3C).')'], - ['OPcache', \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], - ['APCu', \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], + ['OPcache', \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], + ['APCu', \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false'], ]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php index 41d3eddd9964e..5f79d95bf036d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php @@ -90,20 +90,20 @@ protected function findExtension(string $name): ExtensionInterface $guess = $bundle->getName(); $minScore = $distance; } + } - $extension = $bundle->getContainerExtension(); + $container = $this->getContainerBuilder($kernel); - if ($extension) { - if ($name === $extension->getAlias()) { - return $extension; - } + if ($container->hasExtension($name)) { + return $container->getExtension($name); + } - $distance = levenshtein($name, $extension->getAlias()); + foreach ($container->getExtensions() as $extension) { + $distance = levenshtein($name, $extension->getAlias()); - if ($distance < $minScore) { - $guess = $extension->getAlias(); - $minScore = $distance; - } + if ($distance < $minScore) { + $guess = $extension->getAlias(); + $minScore = $distance; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 4bdf3bed59485..aaad074daf246 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -202,7 +202,7 @@ private function relativeSymlinkWithFallback(string $originDir, string $targetDi try { $this->symlink($originDir, $targetDir, true); $method = self::METHOD_RELATIVE_SYMLINK; - } catch (IOException $e) { + } catch (IOException) { $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); } @@ -219,7 +219,7 @@ private function absoluteSymlinkWithFallback(string $originDir, string $targetDi try { $this->symlink($originDir, $targetDir); $method = self::METHOD_ABSOLUTE_SYMLINK; - } catch (IOException $e) { + } catch (IOException) { // fall back to copy $method = $this->hardCopy($originDir, $targetDir); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php index 440c4762a95e9..785027dbc8d4e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php @@ -53,6 +53,10 @@ protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilde (new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); $locatorPass = new ServiceLocatorTagPass(); $locatorPass->process($container); + + $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); + $container->getCompilerPassConfig()->setOptimizationPasses([]); + $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); } return $this->containerBuilder = $container; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index 36c2f76e7e3cf..5e7dc36f206d8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -53,11 +53,6 @@ protected function configure() Before running this command, the cache must be empty. -This command does not generate the classes cache (as when executing this -command, too many classes that should be part of the cache are already loaded -in memory). Use curl or any other similar tool to warm up -the classes cache if you want. - EOF ) ; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index fd01616394763..8e603648f9750 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -98,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (null === $path = $input->getArgument('path')) { $io->title( - sprintf('Current configuration for %s', ($name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name))) + sprintf('Current configuration for %s', $name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name)) ); $io->writeln(Yaml::dump([$extensionAlias => $config], 10)); @@ -127,7 +127,6 @@ private function compileContainer(): ContainerBuilder $kernel->boot(); $method = new \ReflectionMethod($kernel, 'buildContainer'); - $method->setAccessible(true); $container = $method->invoke($kernel); $container->getCompiler()->compile($container); @@ -196,7 +195,7 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti $config = $this->getConfig($this->findExtension($name), $this->compileContainer()); $paths = array_keys(self::buildPathsCompletion($config)); $suggestions->suggestValues($paths); - } catch (LogicException $e) { + } catch (LogicException) { } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index 271ba9bf6429b..d4563dbee2d3d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -67,7 +67,7 @@ protected function configure() For dumping a specific option, add its path as second argument (only available for the yaml format): - php %command.full_name% framework profiler.matcher + php %command.full_name% framework http_client.default_options EOF ) @@ -97,7 +97,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $errorIo->comment([ 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle)', - 'For dumping a specific option, add its path as the second argument of this command. (e.g. config:dump-reference FrameworkBundle profiler.matcher to dump the framework.profiler.matcher configuration)', + 'For dumping a specific option, add its path as the second argument of this command. (e.g. config:dump-reference FrameworkBundle http_client.default_options to dump the framework.http_client.default_options configuration)', ]); return 0; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index b579998231215..c5c2da4a4407c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -132,7 +132,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $options = ['env-vars' => true, 'name' => $envVar]; } elseif ($input->getOption('types')) { $options = []; - $options['filter'] = [$this, 'filterToServiceTypes']; + $options['filter'] = $this->filterToServiceTypes(...); } elseif ($input->getOption('parameters')) { $parameters = []; foreach ($object->getParameterBag()->all() as $k => $v) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php index bb595e305f591..5e3e891ee845f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php @@ -104,7 +104,6 @@ private function getContainerBuilder(): ContainerBuilder (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); $refl = new \ReflectionProperty($parameterBag, 'resolved'); - $refl->setAccessible(true); $refl->setValue($parameterBag, true); $skippedIds = []; @@ -113,6 +112,10 @@ private function getContainerBuilder(): ContainerBuilder $skippedIds[$serviceId] = true; } } + + $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); + $container->getCompilerPassConfig()->setOptimizationPasses([]); + $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); } $container->setParameter('container.build_hash', 'lint_container'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php index 58e7ae1b437c1..ecd507127c00c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php @@ -78,7 +78,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $builder = $this->getContainerBuilder($this->getApplication()->getKernel()); $serviceIds = $builder->getServiceIds(); - $serviceIds = array_filter($serviceIds, [$this, 'filterToServiceTypes']); + $serviceIds = array_filter($serviceIds, $this->filterToServiceTypes(...)); if ($search = $input->getArgument('search')) { $searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff $]++/', '', $search); @@ -169,7 +169,7 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti if ($input->mustSuggestArgumentValuesFor('search')) { $builder = $this->getContainerBuilder($this->getApplication()->getKernel()); - $suggestions->suggestValues(array_filter($builder->getServiceIds(), [$this, 'filterToServiceTypes'])); + $suggestions->suggestValues(array_filter($builder->getServiceIds(), $this->filterToServiceTypes(...))); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index ed61ddd8ff7b3..7d2d6e9340304 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -91,7 +91,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($name) { - if (!($route = $routes->get($name)) && $matchingRoutes = $this->findRouteNameContaining($name, $routes)) { + $route = $routes->get($name); + $matchingRoutes = $this->findRouteNameContaining($name, $routes); + + if (!$input->isInteractive() && !$route && \count($matchingRoutes) > 1) { + $helper->describe($io, $this->findRouteContaining($name, $routes), [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'show_controllers' => $input->getOption('show-controllers'), + 'output' => $io, + ]); + + return 0; + } + + if (!$route && $matchingRoutes) { $default = 1 === \count($matchingRoutes) ? $matchingRoutes[0] : null; $name = $io->choice('Select one of the matching routes', $matchingRoutes, $default); $route = $routes->get($name); @@ -146,4 +160,16 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti $suggestions->suggestValues($helper->getFormats()); } } + + private function findRouteContaining(string $name, RouteCollection $routes): RouteCollection + { + $foundRoutes = new RouteCollection(); + foreach ($routes as $routeName => $route) { + if (false !== stripos($routeName, $name)) { + $foundRoutes->add($routeName, $route); + } + } + + return $foundRoutes; + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index 906f160b4f11f..c2cfae702863b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -131,7 +131,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $locale = $input->getArgument('locale'); $domain = $input->getOption('domain'); - $exitCode = 0; + $exitCode = self::SUCCESS; /** @var KernelInterface $kernel */ $kernel = $this->getApplication()->getKernel(); @@ -153,7 +153,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($this->defaultViewsPath) { $codePaths[] = $this->defaultViewsPath; } - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { // such a bundle does not exist, so treat the argument as path $path = $input->getArgument('bundle'); @@ -217,16 +217,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (!$currentCatalogue->defines($messageId, $domain)) { $states[] = self::MESSAGE_MISSING; - $exitCode = $exitCode | self::EXIT_CODE_MISSING; + if (!$input->getOption('only-unused')) { + $exitCode = $exitCode | self::EXIT_CODE_MISSING; + } } } elseif ($currentCatalogue->defines($messageId, $domain)) { $states[] = self::MESSAGE_UNUSED; - $exitCode = $exitCode | self::EXIT_CODE_UNUSED; + if (!$input->getOption('only-missing')) { + $exitCode = $exitCode | self::EXIT_CODE_UNUSED; + } } - if (!\in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') - || !\in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) { + if (!\in_array(self::MESSAGE_UNUSED, $states) && $input->getOption('only-unused') + || !\in_array(self::MESSAGE_MISSING, $states) && $input->getOption('only-missing') + ) { continue; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 002a80e049b7c..e63be384b8620 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -186,7 +186,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $codePaths[] = $this->defaultViewsPath; } $currentName = $foundBundle->getName(); - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { // such a bundle does not exist, so treat the argument as path $path = $input->getArgument('bundle'); @@ -395,6 +395,7 @@ private function extractMessages(string $locale, array $transPaths, string $pref { $extractedCatalogue = new MessageCatalogue($locale); $this->extractor->setPrefix($prefix); + $transPaths = $this->filterDuplicateTransPaths($transPaths); foreach ($transPaths as $path) { if (is_dir($path) || is_file($path)) { $this->extractor->extract($path, $extractedCatalogue); @@ -404,6 +405,27 @@ private function extractMessages(string $locale, array $transPaths, string $pref return $extractedCatalogue; } + private function filterDuplicateTransPaths(array $transPaths): array + { + $transPaths = array_filter(array_map('realpath', $transPaths)); + + sort($transPaths); + + $filteredPaths = []; + + foreach ($transPaths as $path) { + foreach ($filteredPaths as $filteredPath) { + if (str_starts_with($path, $filteredPath.\DIRECTORY_SEPARATOR)) { + continue 2; + } + } + + $filteredPaths[] = $path; + } + + return $filteredPaths; + } + private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue { $currentCatalogue = new MessageCatalogue($locale); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index b6b3a0222f9a6..e6d21f40b3dc1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -57,6 +57,6 @@ protected function configure() php %command.full_name% @AcmeDemoBundle EOF - ); + ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 5f7cb53420d6f..8927eb1e07b1d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -145,7 +145,7 @@ public function all(string $namespace = null): array */ public function getLongVersion(): string { - return parent::getLongVersion().sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); + return parent::getLongVersion().sprintf(' (env: %s, debug: %s) #StandWithUkraine https://sf.to/ukraine', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); } public function add(Command $command): ?Command diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index c6545f70abaa2..62a60f4d1a9b2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -145,6 +145,10 @@ abstract protected function describeCallable(mixed $callable, array $options = [ protected function formatValue(mixed $value): string { + if ($value instanceof \UnitEnum) { + return ltrim(var_export($value, true), '\\'); + } + if (\is_object($value)) { return sprintf('object(%s)', \get_class($value)); } @@ -159,7 +163,7 @@ protected function formatValue(mixed $value): string protected function formatParameter(mixed $value): string { if ($value instanceof \UnitEnum) { - return var_export($value, true); + return ltrim(var_export($value, true), '\\'); } // Recursively search for enum values, so we can replace it @@ -167,7 +171,7 @@ protected function formatParameter(mixed $value): string if (\is_array($value)) { array_walk_recursive($value, static function (&$value) { if ($value instanceof \UnitEnum) { - $value = var_export($value, true); + $value = ltrim(var_export($value, true), '\\'); } }); } @@ -299,7 +303,7 @@ public static function getClassDescription(string $class, string &$resolvedClass return trim(preg_replace('#\s*\n\s*\*\s*#', ' ', $docComment)); } - } catch (\ReflectionException $e) { + } catch (\ReflectionException) { } return ''; @@ -326,7 +330,6 @@ private function getContainerEnvVars(ContainerBuilder $container): array $getDefaultParameter = $getDefaultParameter->bindTo($bag, \get_class($bag)); $getEnvReflection = new \ReflectionMethod($container, 'getEnv'); - $getEnvReflection->setAccessible(true); $envs = []; diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index c87f96393f600..df71b38b2faa7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -188,7 +188,7 @@ private function writeData(array $data, array $options) // before json_encode (which will not display anything for \UnitEnum otherwise) array_walk_recursive($data, static function (&$value) { if ($value instanceof \UnitEnum) { - $value = var_export($value, true); + $value = ltrim(var_export($value, true), '\\'); } }); @@ -245,7 +245,7 @@ private function getContainerDefinitionData(Definition $definition, bool $omitTa if ($factory[0] instanceof Reference) { $data['factory_service'] = (string) $factory[0]; } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); + $data['factory_service'] = sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured'); } else { $data['factory_class'] = $factory[0]; } @@ -361,7 +361,7 @@ private function getCallableData(mixed $callable): array } $data['name'] = $r->name; - if ($class = $r->getClosureScopeClass()) { + if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { $data['class'] = $class->name; if (!$r->getClosureThis()) { $data['static'] = true; diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index b70bfce81260e..22cfe9259292f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -224,7 +224,7 @@ protected function describeContainerDefinition(Definition $definition, array $op if ($factory[0] instanceof Reference) { $output .= "\n".'- Factory Service: `'.$factory[0].'`'; } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); + $output .= "\n".sprintf('- Factory Service: inline factory service (%s)', $factory[0]->getClass() ? sprintf('`%s`', $factory[0]->getClass()) : 'not configured'); } else { $output .= "\n".'- Factory Class: `'.$factory[0].'`'; } @@ -377,7 +377,7 @@ protected function describeCallable(mixed $callable, array $options = []) } $string .= "\n".sprintf('- Name: `%s`', $r->name); - if ($class = $r->getClosureScopeClass()) { + if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { $string .= "\n".sprintf('- Class: `%s`', $class->name); if (!$r->getClosureThis()) { $string .= "\n- Static: yes"; diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 89f407765b10c..df1b141cfa3f1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -93,11 +93,11 @@ protected function describeRoute(Route $route, array $options = []) ['Route Name', $options['name'] ?? ''], ['Path', $route->getPath()], ['Path Regex', $route->compile()->getRegex()], - ['Host', ('' !== $route->getHost() ? $route->getHost() : 'ANY')], - ['Host Regex', ('' !== $route->getHost() ? $route->compile()->getHostRegex() : '')], - ['Scheme', ($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY')], - ['Method', ($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY')], - ['Requirements', ($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM')], + ['Host', '' !== $route->getHost() ? $route->getHost() : 'ANY'], + ['Host Regex', '' !== $route->getHost() ? $route->compile()->getHostRegex() : ''], + ['Scheme', $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'], + ['Method', $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'], + ['Requirements', $route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM'], ['Class', \get_class($route)], ['Defaults', $this->formatRouterConfig($defaults)], ['Options', $this->formatRouterConfig($route->getOptions())], @@ -315,7 +315,7 @@ protected function describeContainerDefinition(Definition $definition, array $op if ($factory[0] instanceof Reference) { $tableRows[] = ['Factory Service', $factory[0]]; } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); + $tableRows[] = ['Factory Service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured')]; } else { $tableRows[] = ['Factory Class', $factory[0]]; } @@ -349,7 +349,7 @@ protected function describeContainerDefinition(Definition $definition, array $op } elseif ($argument instanceof Definition) { $argumentsInformation[] = 'Inlined Service'; } elseif ($argument instanceof \UnitEnum) { - $argumentsInformation[] = var_export($argument, true); + $argumentsInformation[] = ltrim(var_export($argument, true), '\\'); } elseif ($argument instanceof AbstractArgument) { $argumentsInformation[] = sprintf('Abstract argument (%s)', $argument->getText()); } else { @@ -563,7 +563,7 @@ private function formatControllerLink(mixed $controller, string $anchorText, cal } else { $r = new \ReflectionFunction($controller); } - } catch (\ReflectionException $e) { + } catch (\ReflectionException) { if (\is_array($controller)) { $controller = implode('::', $controller); } @@ -582,7 +582,7 @@ private function formatControllerLink(mixed $controller, string $anchorText, cal try { $r = new \ReflectionMethod($container->findDefinition($id)->getClass(), $method); - } catch (\ReflectionException $e) { + } catch (\ReflectionException) { return $anchorText; } } @@ -614,7 +614,7 @@ private function formatCallable(mixed $callable): string if (str_contains($r->name, '{closure}')) { return 'Closure()'; } - if ($class = $r->getClosureScopeClass()) { + if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { return sprintf('%s::%s()', $class->name, $r->name); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index 91984fb621784..bdc52c45e134a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -324,7 +324,7 @@ private function getContainerDefinitionDocument(Definition $definition, string $ if ($factory[0] instanceof Reference) { $factoryXML->setAttribute('service', (string) $factory[0]); } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); + $factoryXML->setAttribute('service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'not configured')); } else { $factoryXML->setAttribute('class', $factory[0]); } @@ -421,7 +421,7 @@ private function getArgumentNodes(array $arguments, \DOMDocument $dom): array } } elseif ($argument instanceof \UnitEnum) { $argumentXML->setAttribute('type', 'constant'); - $argumentXML->appendChild(new \DOMText(var_export($argument, true))); + $argumentXML->appendChild(new \DOMText(ltrim(var_export($argument, true), '\\'))); } else { $argumentXML->appendChild(new \DOMText($argument)); } @@ -548,7 +548,7 @@ private function getCallableDocument(mixed $callable): \DOMDocument } $callableXML->setAttribute('name', $r->name); - if ($class = $r->getClosureScopeClass()) { + if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { $callableXML->setAttribute('class', $class->name); if (!$r->getClosureThis()) { $callableXML->setAttribute('static', 'true'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index 9e0836101b38e..3be4b0f517411 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -42,6 +42,7 @@ use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Contracts\Service\Attribute\Required; use Symfony\Contracts\Service\ServiceSubscriberInterface; use Twig\Environment; @@ -60,6 +61,7 @@ abstract class AbstractController implements ServiceSubscriberInterface /** * @required */ + #[Required] public function setContainer(ContainerInterface $container): ?ContainerInterface { $previous = $this->container; diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php index 4f09e52bdcbd1..d7db6ebf050a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -34,8 +35,11 @@ public function process(ContainerBuilder $container) $provider = $properties['cacheProviderBackup']->getValues()[0]; unset($properties['cacheProviderBackup']); $reader->setProperties($properties); - $container->set($id, null); - $container->setDefinition($id, $reader->replaceArgument(1, $provider)); + $reader->replaceArgument(1, $provider); + } elseif (4 <= \count($arguments = $reader->getArguments()) && $arguments[3] instanceof ServiceClosureArgument) { + $arguments[1] = $arguments[3]->getValues()[0]; + unset($arguments[3]); + $reader->setArguments($arguments); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php index ee2bbb6521b17..898f961d0a1f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Translation\TranslatorBagInterface; /** * @author Christian Flothmann @@ -27,7 +28,7 @@ public function process(ContainerBuilder $container) $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); - if (!is_subclass_of($translatorClass, 'Symfony\Component\Translation\TranslatorBagInterface')) { + if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) { $container->removeDefinition('translator.data_collector'); $container->removeDefinition('data_collector.translation'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php index 222b5c7b75af0..942eb635b26f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -38,6 +39,16 @@ public function process(ContainerBuilder $container) } } + foreach ($container->getAliases() as $id => $target) { + while ($container->hasAlias($target = (string) $target)) { + $target = $container->getAlias($target); + } + + if ($definitions[$target]->hasTag('container.private')) { + $privateServices[$id] = new ServiceClosureArgument(new Reference($target)); + } + } + $privateContainer->replaceArgument(0, $privateServices); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index 67bbc740f816b..32b578ee7b64a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -31,6 +31,7 @@ class UnusedTagsPass implements CompilerPassInterface 'chatter.transport_factory', 'config_cache.resource_checker', 'console.command', + 'container.do_not_inline', 'container.env_var_loader', 'container.env_var_processor', 'container.hot_path', @@ -49,6 +50,7 @@ class UnusedTagsPass implements CompilerPassInterface 'form.type', 'form.type_extension', 'form.type_guesser', + 'html_sanitizer', 'http_client.client', 'kernel.cache_clearer', 'kernel.cache_warmer', @@ -71,6 +73,7 @@ class UnusedTagsPass implements CompilerPassInterface 'property_info.list_extractor', 'property_info.type_extractor', 'proxy', + 'routing.condition_service', 'routing.expression_language_function', 'routing.expression_language_provider', 'routing.loader', diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 5f2eb5daa173e..28f3b07adbf78 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -16,6 +16,7 @@ use Psr\Log\LogLevel; use Symfony\Bundle\FullStack; use Symfony\Component\Asset\Package; +use Symfony\Component\Cache\Adapter\DoctrineAdapter; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; @@ -24,6 +25,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\Form\Form; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\Lock\Lock; @@ -34,6 +36,7 @@ use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter; +use Symfony\Component\Semaphore\Semaphore; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\Translator; use Symfony\Component\Uid\Factory\UuidFactory; @@ -73,12 +76,27 @@ 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() - ->scalarNode('http_method_override') + ->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") - ->defaultTrue() + ->treatNullLike(false) + ->end() + ->scalarNode('trust_x_sendfile_type_header') + ->info('Set true to enable support for xsendfile in binary file responses.') + ->defaultFalse() ->end() ->scalarNode('ide')->defaultValue('%env(default::SYMFONY_IDE)%')->end() ->booleanNode('test')->end() @@ -142,9 +160,9 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addRequestSection($rootNode); $this->addAssetsSection($rootNode, $enableIfStandalone); $this->addTranslatorSection($rootNode, $enableIfStandalone); - $this->addValidationSection($rootNode, $enableIfStandalone, $willBeAvailable); + $this->addValidationSection($rootNode, $enableIfStandalone); $this->addAnnotationsSection($rootNode, $willBeAvailable); - $this->addSerializerSection($rootNode, $enableIfStandalone, $willBeAvailable); + $this->addSerializerSection($rootNode, $enableIfStandalone); $this->addPropertyAccessSection($rootNode, $willBeAvailable); $this->addPropertyInfoSection($rootNode, $enableIfStandalone); $this->addCacheSection($rootNode, $willBeAvailable); @@ -152,6 +170,7 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addExceptionsSection($rootNode); $this->addWebLinkSection($rootNode, $enableIfStandalone); $this->addLockSection($rootNode, $enableIfStandalone); + $this->addSemaphoreSection($rootNode, $enableIfStandalone); $this->addMessengerSection($rootNode, $enableIfStandalone); $this->addRobotsIndexSection($rootNode); $this->addHttpClientSection($rootNode, $enableIfStandalone); @@ -160,6 +179,7 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addNotifierSection($rootNode, $enableIfStandalone); $this->addRateLimiterSection($rootNode, $enableIfStandalone); $this->addUidSection($rootNode, $enableIfStandalone); + $this->addHtmlSanitizerSection($rootNode, $enableIfStandalone); return $treeBuilder; } @@ -305,6 +325,7 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode) ->booleanNode('only_exceptions')->defaultFalse()->end() ->booleanNode('only_main_requests')->defaultFalse()->end() ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() + ->booleanNode('collect_serializer_data')->info('Enables the serializer data collector and profiler panel')->defaultFalse()->end() ->end() ->end() ->end() @@ -847,7 +868,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e ; } - private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, callable $willBeAvailable) + private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) { $rootNode ->children() @@ -957,7 +978,7 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode, callable $ ; } - private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, callable $willBeAvailable) + private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) { $rootNode ->children() @@ -1049,7 +1070,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end() ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end() ->scalarNode('default_doctrine_dbal_provider')->defaultValue('database_connection')->end() - ->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) ? 'database_connection' : null)->end() + ->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) && class_exists(DoctrineAdapter::class) ? 'database_connection' : null)->end() ->arrayNode('pools') ->useAttributeAsKey('name') ->prototype('array') @@ -1091,7 +1112,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe ->booleanNode('public')->defaultFalse()->end() ->scalarNode('default_lifetime') ->info('Default lifetime of the pool') - ->example('"600" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression') + ->example('"300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression') ->end() ->scalarNode('provider') ->info('Overwrite the setting from the default provider for this adapter.') @@ -1164,49 +1185,49 @@ private function addExceptionsSection(ArrayNodeDefinition $rootNode) $logLevels = (new \ReflectionClass(LogLevel::class))->getConstants(); $rootNode + ->fixXmlConfig('exception') ->children() ->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; } - // Fix XML normalization - $data = isset($v['exception'][0]) ? $v['exception'] : [$v['exception']]; - $exceptions = []; - foreach ($data as $exception) { - $config = []; - if (\array_key_exists('log-level', $exception)) { - $config['log_level'] = $exception['log-level']; - } - if (\array_key_exists('status-code', $exception)) { - $config['status_code'] = $exception['status-code']; - } - $exceptions[$exception['name']] = $config; + $v = $v['exception']; + unset($v['exception']); + + foreach ($v as &$exception) { + $exception['class'] = $exception['name']; + unset($exception['name']); } - return $exceptions; + return $v; }) ->end() ->prototype('array') - ->fixXmlConfig('exception') ->children() ->scalarNode('log_level') ->info('The level of log message. Null to let Symfony decide.') ->validate() - ->ifTrue(function ($v) use ($logLevels) { return !\in_array($v, $logLevels); }) + ->ifTrue(function ($v) use ($logLevels) { return null !== $v && !\in_array($v, $logLevels, true); }) ->thenInvalid(sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels))) ->end() ->defaultNull() ->end() ->scalarNode('status_code') - ->info('The status code of the response. Null to let Symfony decide.') + ->info('The status code of the response. Null or 0 to let Symfony decide.') + ->beforeNormalization() + ->ifTrue(function ($v) { return 0 === $v; }) + ->then(function ($v) { return null; }) + ->end() ->validate() - ->ifTrue(function ($v) { return $v < 100 || $v > 599; }) - ->thenInvalid('The log level is not valid. Pick a value between 100 and 599.') + ->ifTrue(function ($v) { return null !== $v && ($v < 100 || $v > 599); }) + ->thenInvalid('The status code is not valid. Pick a value between 100 and 599.') ->end() ->defaultNull() ->end() @@ -1241,12 +1262,15 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI }) ->end() ->addDefaultsIfNotSet() + ->validate() + ->ifTrue(static function (array $config) { return $config['enabled'] && !$config['resources']; }) + ->thenInvalid('At least one resource must be defined.') + ->end() ->fixXmlConfig('resource') ->children() ->arrayNode('resources') ->normalizeKeys(false) ->useAttributeAsKey('name') - ->requiresAtLeastOneElement() ->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']]) ->beforeNormalization() ->ifString()->then(function ($v) { return ['default' => $v]; }) @@ -1277,6 +1301,61 @@ private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableI ; } + private function addSemaphoreSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) + { + $rootNode + ->children() + ->arrayNode('semaphore') + ->info('Semaphore configuration') + ->{$enableIfStandalone('symfony/semaphore', Semaphore::class)}() + ->beforeNormalization() + ->ifString()->then(function ($v) { return ['enabled' => true, 'resources' => $v]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); }) + ->then(function ($v) { return $v + ['enabled' => true]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']) && !isset($v['resource']); }) + ->then(function ($v) { + $e = $v['enabled']; + unset($v['enabled']); + + return ['enabled' => $e, 'resources' => $v]; + }) + ->end() + ->addDefaultsIfNotSet() + ->fixXmlConfig('resource') + ->children() + ->arrayNode('resources') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->requiresAtLeastOneElement() + ->beforeNormalization() + ->ifString()->then(function ($v) { return ['default' => $v]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && array_is_list($v); }) + ->then(function ($v) { + $resources = []; + foreach ($v as $resource) { + $resources[] = \is_array($resource) && isset($resource['name']) + ? [$resource['name'] => $resource['value']] + : ['default' => $resource] + ; + } + + return array_merge_recursive([], ...$resources); + }) + ->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ; + } + private function addWebLinkSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) { $rootNode @@ -1425,6 +1504,7 @@ function ($a) { ->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.') @@ -1835,7 +1915,7 @@ private function addHttpClientRetrySection() ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness in percent (between 0 and 1) to apply to the delay')->end() ->end() - ; + ; } private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) @@ -2043,4 +2123,155 @@ private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIf ->end() ; } + + private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) + { + $rootNode + ->children() + ->arrayNode('html_sanitizer') + ->info('HtmlSanitizer configuration') + ->{$enableIfStandalone('symfony/html-sanitizer', HtmlSanitizerInterface::class)}() + ->fixXmlConfig('sanitizer') + ->children() + ->arrayNode('sanitizers') + ->useAttributeAsKey('name') + ->arrayPrototype() + ->fixXmlConfig('allow_element') + ->fixXmlConfig('block_element') + ->fixXmlConfig('drop_element') + ->fixXmlConfig('allow_attribute') + ->fixXmlConfig('drop_attribute') + ->fixXmlConfig('force_attribute') + ->fixXmlConfig('allowed_link_scheme') + ->fixXmlConfig('allowed_link_host') + ->fixXmlConfig('allowed_media_scheme') + ->fixXmlConfig('allowed_media_host') + ->fixXmlConfig('with_attribute_sanitizer') + ->fixXmlConfig('without_attribute_sanitizer') + ->children() + ->booleanNode('allow_safe_elements') + ->info('Allows "safe" elements and attributes.') + ->defaultFalse() + ->end() + ->booleanNode('allow_static_elements') + ->info('Allows all static elements and attributes from the W3C Sanitizer API standard.') + ->defaultFalse() + ->end() + ->arrayNode('allow_elements') + ->info('Configures the elements that the sanitizer should retain from the input. The element name is the key, the value is either a list of allowed attributes for this element or "*" to allow the default set of attributes (https://wicg.github.io/sanitizer-api/#default-configuration).') + ->example(['i' => '*', 'a' => ['title'], 'span' => 'class']) + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->variablePrototype() + ->beforeNormalization() + ->ifArray()->then(fn ($n) => $n['attribute'] ?? $n) + ->end() + ->validate() + ->ifTrue(fn ($n): bool => !\is_string($n) && !\is_array($n)) + ->thenInvalid('The value must be either a string or an array of strings.') + ->end() + ->end() + ->end() + ->arrayNode('block_elements') + ->info('Configures elements as blocked. Blocked elements are elements the sanitizer should remove from the input, but retain their children.') + ->beforeNormalization() + ->ifString() + ->then(fn (string $n): array => (array) $n) + ->end() + ->scalarPrototype()->end() + ->end() + ->arrayNode('drop_elements') + ->info('Configures elements as dropped. Dropped elements are elements the sanitizer should remove from the input, including their children.') + ->beforeNormalization() + ->ifString() + ->then(fn (string $n): array => (array) $n) + ->end() + ->scalarPrototype()->end() + ->end() + ->arrayNode('allow_attributes') + ->info('Configures attributes as allowed. Allowed attributes are attributes the sanitizer should retain from the input.') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->variablePrototype() + ->beforeNormalization() + ->ifArray()->then(fn ($n) => $n['element'] ?? $n) + ->end() + ->end() + ->end() + ->arrayNode('drop_attributes') + ->info('Configures attributes as dropped. Dropped attributes are attributes the sanitizer should remove from the input.') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->variablePrototype() + ->beforeNormalization() + ->ifArray()->then(fn ($n) => $n['element'] ?? $n) + ->end() + ->end() + ->end() + ->arrayNode('force_attributes') + ->info('Forcefully set the values of certain attributes on certain elements.') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->arrayPrototype() + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->scalarPrototype()->end() + ->end() + ->end() + ->booleanNode('force_https_urls') + ->info('Transforms URLs using the HTTP scheme to use the HTTPS scheme instead.') + ->defaultFalse() + ->end() + ->arrayNode('allowed_link_schemes') + ->info('Allows only a given list of schemes to be used in links href attributes.') + ->scalarPrototype()->end() + ->end() + ->variableNode('allowed_link_hosts') + ->info('Allows only a given list of hosts to be used in links href attributes.') + ->defaultValue(null) + ->validate() + ->ifTrue(function ($v) { return !\is_array($v) && null !== $v; }) + ->thenInvalid('The "allowed_link_hosts" parameter must be an array or null') + ->end() + ->end() + ->booleanNode('allow_relative_links') + ->info('Allows relative URLs to be used in links href attributes.') + ->defaultFalse() + ->end() + ->arrayNode('allowed_media_schemes') + ->info('Allows only a given list of schemes to be used in media source attributes (img, audio, video, ...).') + ->scalarPrototype()->end() + ->end() + ->variableNode('allowed_media_hosts') + ->info('Allows only a given list of hosts to be used in media source attributes (img, audio, video, ...).') + ->defaultValue(null) + ->validate() + ->ifTrue(function ($v) { return !\is_array($v) && null !== $v; }) + ->thenInvalid('The "allowed_media_hosts" parameter must be an array or null') + ->end() + ->end() + ->booleanNode('allow_relative_medias') + ->info('Allows relative URLs to be used in media source attributes (img, audio, video, ...).') + ->defaultFalse() + ->end() + ->arrayNode('with_attribute_sanitizers') + ->info('Registers custom attribute sanitizers.') + ->scalarPrototype()->end() + ->end() + ->arrayNode('without_attribute_sanitizers') + ->info('Unregisters custom attribute sanitizers.') + ->scalarPrototype()->end() + ->end() + ->integerNode('max_input_length') + ->info('The maximum length allowed for the sanitized input.') + ->defaultValue(0) + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b81e8d147f921..7a62507f5fd53 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; +use Composer\InstalledVersions; use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Annotations\Reader; use Http\Client\HttpClient; @@ -67,10 +68,14 @@ use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Finder\Finder; use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; +use Symfony\Component\Form\Extension\HtmlSanitizer\Type\TextTypeHtmlSanitizerExtension; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormTypeExtensionInterface; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\FormTypeInterface; +use Symfony\Component\HtmlSanitizer\HtmlSanitizer; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; use Symfony\Component\HttpClient\RetryableHttpClient; @@ -80,6 +85,7 @@ use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -107,6 +113,7 @@ use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; +use Symfony\Component\Messenger\Stamp\SerializedMessageStamp; use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; use Symfony\Component\Messenger\Transport\TransportFactoryInterface; use Symfony\Component\Messenger\Transport\TransportInterface; @@ -117,6 +124,7 @@ use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory; use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory; use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory; +use Symfony\Component\Notifier\Bridge\Engagespot\EngagespotTransportFactory; use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory; use Symfony\Component\Notifier\Bridge\Expo\ExpoTransportFactory; use Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory; @@ -144,6 +152,7 @@ use Symfony\Component\Notifier\Bridge\OrangeSms\OrangeSmsTransportFactory; use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; +use Symfony\Component\Notifier\Bridge\Sendberry\SendberryTransportFactory; use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory as SendinblueNotifierTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; @@ -159,10 +168,13 @@ use Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory; use Symfony\Component\Notifier\Bridge\Yunpian\YunpianTransportFactory; use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; +use Symfony\Component\Notifier\ChatterInterface; use Symfony\Component\Notifier\Notifier; use Symfony\Component\Notifier\Recipient\Recipient; +use Symfony\Component\Notifier\TexterInterface; use Symfony\Component\Notifier\Transport\TransportFactoryInterface as NotifierTransportFactoryInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor; use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; @@ -180,8 +192,15 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Semaphore\PersistingStoreInterface as SemaphoreStoreInterface; +use Symfony\Component\Semaphore\Semaphore; +use Symfony\Component\Semaphore\SemaphoreFactory; +use Symfony\Component\Semaphore\Store\StoreFactory as SemaphoreStoreFactory; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; +use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; +use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; +use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer; @@ -192,6 +211,7 @@ use Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory; use Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory; use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; +use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Component\Translation\PseudoLocalizationTranslator; use Symfony\Component\Translation\Translator; use Symfony\Component\Uid\Factory\UuidFactory; @@ -229,6 +249,7 @@ class FrameworkExtension extends Extension private bool $mailerConfigEnabled = false; private bool $httpClientConfigEnabled = false; private bool $notifierConfigEnabled = false; + private bool $serializerConfigEnabled = false; private bool $propertyAccessConfigEnabled = false; private static bool $lockConfigEnabled = false; @@ -241,9 +262,13 @@ public function load(array $configs, ContainerBuilder $container) { $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.'); + } + $loader->load('web.php'); - if (\PHP_VERSION_ID < 80100 || !class_exists(BackedEnumValueResolver::class)) { + if (!class_exists(BackedEnumValueResolver::class)) { $container->removeDefinition('argument_resolver.backed_enum_resolver'); } @@ -317,6 +342,7 @@ public function load(array $configs, ContainerBuilder $container) } $container->setParameter('kernel.http_method_override', $config['http_method_override']); + $container->setParameter('kernel.trust_x_sendfile_type_header', $config['trust_x_sendfile_type_header']); $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); $container->setParameter('kernel.default_locale', $config['default_locale']); $container->setParameter('kernel.enabled_locales', $config['enabled_locales']); @@ -374,7 +400,7 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']); - if ($this->isConfigEnabled($container, $config['serializer'])) { + if ($this->serializerConfigEnabled = $this->isConfigEnabled($container, $config['serializer'])) { if (!class_exists(\Symfony\Component\Serializer\Serializer::class)) { throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".'); } @@ -390,6 +416,10 @@ public function load(array $configs, ContainerBuilder $container) $this->registerLockConfiguration($config['lock'], $container, $loader); } + if ($this->isConfigEnabled($container, $config['semaphore'])) { + $this->registerSemaphoreConfiguration($config['semaphore'], $container, $loader); + } + if ($this->isConfigEnabled($container, $config['rate_limiter'])) { if (!interface_exists(LimiterInterface::class)) { throw new LogicException('Rate limiter support cannot be enabled as the RateLimiter component is not installed. Try running "composer require symfony/rate-limiter".'); @@ -412,6 +442,8 @@ public function load(array $configs, ContainerBuilder $container) } $this->registerUidConfiguration($config['uid'], $container, $loader); + } else { + $container->removeDefinition('argument_resolver.uid'); } // register cache before session so both can share the connection services @@ -456,6 +488,9 @@ public function load(array $configs, ContainerBuilder $container) $container->removeDefinition('form.type_extension.form.validator'); $container->removeDefinition('form.type_guesser.validator'); } + if (!$this->isConfigEnabled($container, $config['html_sanitizer']) || !class_exists(TextTypeHtmlSanitizerExtension::class)) { + $container->removeDefinition('form.type_extension.form.html_sanitizer'); + } } else { $container->removeDefinition('console.command.form_debug'); } @@ -502,15 +537,23 @@ public function load(array $configs, ContainerBuilder $container) $this->registerNotifierConfiguration($config['notifier'], $container, $loader); } - // profiler depends on form, validation, translation, messenger, mailer, http-client, notifier being registered + // profiler depends on form, validation, translation, messenger, mailer, http-client, notifier, serializer being registered $this->registerProfilerConfiguration($config['profiler'], $container, $loader); + if ($this->isConfigEnabled($container, $config['html_sanitizer'])) { + if (!class_exists(HtmlSanitizerConfig::class)) { + throw new LogicException('HtmlSanitizer support cannot be enabled as the HtmlSanitizer component is not installed. Try running "composer require symfony/html-sanitizer".'); + } + + $this->registerHtmlSanitizerConfiguration($config['html_sanitizer'], $container, $loader); + } + $this->addAnnotatedClassesToCompile([ '**\\Controller\\', '**\\Entity\\', // Added explicitly so that we don't rely on the class map being dumped to make it work - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', + AbstractController::class, ]); if (ContainerBuilder::willBeAvailable('symfony/mime', MimeTypes::class, ['symfony/framework-bundle'])) { @@ -609,13 +652,30 @@ public function load(array $configs, ContainerBuilder $container) $container->registerAttributeForAutoconfiguration(AsController::class, static function (ChildDefinition $definition, AsController $attribute): void { $definition->addTag('controller.service_arguments'); }); - $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute): void { - $tagAttributes = get_object_vars($attribute); - $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; - unset($tagAttributes['fromTransport']); - $definition->addTag('messenger.message_handler', $tagAttributes); - }); + if (class_exists(SerializedMessageStamp::class)) { + // symfony/messenger >= 6.1 + $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); + }); + } else { + // symfony/messenger < 6.1 + $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute): void { + $tagAttributes = get_object_vars($attribute); + $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; + unset($tagAttributes['fromTransport']); + $definition->addTag('messenger.message_handler', $tagAttributes); + }); + } if (!$container->getParameter('kernel.debug')) { // remove tagged iterator argument for resource checkers @@ -630,6 +690,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('routing.route_loader'); $container->setParameter('container.behavior_describing_tags', [ + 'annotations.cached_reader', + 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'kernel.event_subscriber', @@ -661,6 +723,10 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont } if ($this->isConfigEnabled($container, $config['form']['csrf_protection'])) { + if (!$container->hasDefinition('security.csrf.token_generator')) { + throw new \LogicException('To use form CSRF protection, "framework.csrf_protection" must be enabled.'); + } + $loader->load('form_csrf.php'); $container->setParameter('form.type_extension.csrf.enabled', true); @@ -779,6 +845,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $loader->load('notifier_debug.php'); } + if ($this->serializerConfigEnabled && $config['collect_serializer_data']) { + $loader->load('serializer_debug.php'); + } + $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']); $container->setParameter('profiler_listener.only_main_requests', $config['only_main_requests']); @@ -909,7 +979,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ if (isset($workflow['marking_store']['type'])) { $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method'); $markingStoreDefinition->setArguments([ - 'state_machine' === $type, //single state + 'state_machine' === $type, // single state $workflow['marking_store']['property'], ]); } elseif (isset($workflow['marking_store']['service'])) { @@ -1256,6 +1326,11 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder } $loader->load('translation.php'); + + if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleSwitcher::class, ['symfony/framework-bundle'])) { + $container->removeDefinition('translation.locale_switcher'); + } + $loader->load('translation_providers.php'); // Use the "real" translator instead of the identity default @@ -1570,9 +1645,16 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $loader->load('annotations.php'); + // registerUniqueLoader exists since doctrine/annotations v1.6 if (!method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { - $container->getDefinition('annotations.dummy_registry') - ->setMethodCalls([['registerLoader', ['class_exists']]]); + // registerLoader exists only in doctrine/annotations v1 + if (method_exists(AnnotationRegistry::class, 'registerLoader')) { + $container->getDefinition('annotations.dummy_registry') + ->setMethodCalls([['registerLoader', ['class_exists']]]); + } else { + // remove the dummy registry when doctrine/annotations v2 is used + $container->removeDefinition('annotations.dummy_registry'); + } } if ('none' === $config['cache']) { @@ -1604,9 +1686,8 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $container ->getDefinition('annotations.cached_reader') ->replaceArgument(2, $config['debug']) - // temporary property to lazy-reference the cache provider without using it until AddAnnotationsCachedReaderPass runs - ->setProperty('cacheProviderBackup', new ServiceClosureArgument(new Reference($cacheService))) - ->addTag('annotations.cached_reader') + // reference the cache provider without using it until AddAnnotationsCachedReaderPass runs + ->addArgument(new ServiceClosureArgument(new Reference($cacheService))) ; $container->setAlias('annotation_reader', 'annotations.cached_reader'); @@ -1731,7 +1812,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $serializerLoaders = []; if (isset($config['enable_annotations']) && $config['enable_annotations']) { $annotationLoader = new Definition( - 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', + AnnotationLoader::class, [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] ); $annotationLoader->setPublic(false); @@ -1740,7 +1821,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder } $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { - $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', [$path]); + $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? YamlFileLoader::class : XmlFileLoader::class, [$path]); $definition->setPublic(false); $serializerLoaders[] = $definition; }; @@ -1813,7 +1894,7 @@ private function registerPropertyInfoConfiguration(ContainerBuilder $container, } if (ContainerBuilder::willBeAvailable('phpdocumentor/reflection-docblock', DocBlockFactoryInterface::class, ['symfony/framework-bundle', 'symfony/property-info'], true)) { - $definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor'); + $definition = $container->register('property_info.php_doc_extractor', PhpDocExtractor::class); $definition->addTag('property_info.description_extractor', ['priority' => -1000]); $definition->addTag('property_info.type_extractor', ['priority' => -1001]); } @@ -1834,11 +1915,11 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont // Generate stores $storeDefinitions = []; - foreach ($resourceStores as $storeDsn) { - $storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs); + foreach ($resourceStores as $resourceStore) { + $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); $storeDefinition = new Definition(PersistingStoreInterface::class); $storeDefinition->setFactory([StoreFactory::class, 'createStore']); - $storeDefinition->setArguments([$storeDsn]); + $storeDefinition->setArguments([$resourceStore]); $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); @@ -1869,6 +1950,39 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont } } + private function registerSemaphoreConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) + { + $loader->load('semaphore.php'); + + foreach ($config['resources'] as $resourceName => $resourceStore) { + $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); + $storeDefinition = new Definition(SemaphoreStoreInterface::class); + $storeDefinition->setFactory([SemaphoreStoreFactory::class, 'createStore']); + $storeDefinition->setArguments([$resourceStore]); + + $container->setDefinition($storeDefinitionId = '.semaphore.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); + + // Generate factories for each resource + $factoryDefinition = new ChildDefinition('semaphore.factory.abstract'); + $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId)); + $container->setDefinition('semaphore.'.$resourceName.'.factory', $factoryDefinition); + + // Generate services for semaphore instances + $semaphoreDefinition = new Definition(Semaphore::class); + $semaphoreDefinition->setPublic(false); + $semaphoreDefinition->setFactory([new Reference('semaphore.'.$resourceName.'.factory'), 'createSemaphore']); + $semaphoreDefinition->setArguments([$resourceName]); + + // provide alias for default resource + if ('default' === $resourceName) { + $container->setAlias('semaphore.factory', new Alias('semaphore.'.$resourceName.'.factory', false)); + $container->setAlias(SemaphoreFactory::class, new Alias('semaphore.factory', false)); + } else { + $container->registerAliasForArgument('semaphore.'.$resourceName.'.factory', SemaphoreFactory::class, $resourceName.'.semaphore.factory'); + } + } + } + private function registerMessengerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, array $validationConfig) { if (!interface_exists(MessageBusInterface::class)) { @@ -2342,11 +2456,11 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', + OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', SesTransportFactory::class => 'mailer.transport_factory.amazon', - OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', ]; foreach ($classToServices as $class => $service) { @@ -2390,11 +2504,13 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ $container->getDefinition('chatter.transports')->setArgument(0, $config['chatter_transports']); } else { $container->removeDefinition('chatter'); + $container->removeAlias(ChatterInterface::class); } if ($config['texter_transports']) { $container->getDefinition('texter.transports')->setArgument(0, $config['texter_transports']); } else { $container->removeDefinition('texter'); + $container->removeAlias(TexterInterface::class); } if ($this->mailerConfigEnabled) { @@ -2431,6 +2547,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ AmazonSnsTransportFactory::class => 'notifier.transport_factory.amazon-sns', ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell', DiscordTransportFactory::class => 'notifier.transport_factory.discord', + EngagespotTransportFactory::class => 'notifier.transport_factory.engagespot', EsendexTransportFactory::class => 'notifier.transport_factory.esendex', ExpoTransportFactory::class => 'notifier.transport_factory.expo', FakeChatTransportFactory::class => 'notifier.transport_factory.fake-chat', @@ -2458,6 +2575,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ OrangeSmsTransportFactory::class => 'notifier.transport_factory.orange-sms', OvhCloudTransportFactory::class => 'notifier.transport_factory.ovh-cloud', RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', + SendberryTransportFactory::class => 'notifier.transport_factory.sendberry', SendinblueNotifierTransportFactory::class => 'notifier.transport_factory.sendinblue', SinchTransportFactory::class => 'notifier.transport_factory.sinch', SlackTransportFactory::class => 'notifier.transport_factory.slack', @@ -2485,7 +2603,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ } } - if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages)) { + if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages) && \in_array(MercureBundle::class, $container->getParameter('kernel.bundles'), true)) { $container->getDefinition($classToServices[MercureTransportFactory::class]) ->replaceArgument('$registry', new Reference(HubRegistry::class)); } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages)) { @@ -2573,6 +2691,94 @@ private function registerUidConfiguration(array $config, ContainerBuilder $conta $container->getDefinition('name_based_uuid.factory') ->setArguments([$config['name_based_uuid_namespace']]); } + + if (!class_exists(UidValueResolver::class)) { + $container->removeDefinition('argument_resolver.uid'); + } + } + + private function registerHtmlSanitizerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) + { + $loader->load('html_sanitizer.php'); + + foreach ($config['sanitizers'] as $sanitizerName => $sanitizerConfig) { + $configId = 'html_sanitizer.config.'.$sanitizerName; + $def = $container->register($configId, HtmlSanitizerConfig::class); + + // Base + if ($sanitizerConfig['allow_safe_elements']) { + $def->addMethodCall('allowSafeElements', [], true); + } + + if ($sanitizerConfig['allow_static_elements']) { + $def->addMethodCall('allowStaticElements', [], true); + } + + // Configures elements + foreach ($sanitizerConfig['allow_elements'] as $element => $attributes) { + $def->addMethodCall('allowElement', [$element, $attributes], true); + } + + foreach ($sanitizerConfig['block_elements'] as $element) { + $def->addMethodCall('blockElement', [$element], true); + } + + foreach ($sanitizerConfig['drop_elements'] as $element) { + $def->addMethodCall('dropElement', [$element], true); + } + + // Configures attributes + foreach ($sanitizerConfig['allow_attributes'] as $attribute => $elements) { + $def->addMethodCall('allowAttribute', [$attribute, $elements], true); + } + + foreach ($sanitizerConfig['drop_attributes'] as $attribute => $elements) { + $def->addMethodCall('dropAttribute', [$attribute, $elements], true); + } + + // Force attributes + foreach ($sanitizerConfig['force_attributes'] as $element => $attributes) { + foreach ($attributes as $attrName => $attrValue) { + $def->addMethodCall('forceAttribute', [$element, $attrName, $attrValue], true); + } + } + + // Settings + $def->addMethodCall('forceHttpsUrls', [$sanitizerConfig['force_https_urls']], true); + if ($sanitizerConfig['allowed_link_schemes']) { + $def->addMethodCall('allowLinkSchemes', [$sanitizerConfig['allowed_link_schemes']], true); + } + $def->addMethodCall('allowLinkHosts', [$sanitizerConfig['allowed_link_hosts']], true); + $def->addMethodCall('allowRelativeLinks', [$sanitizerConfig['allow_relative_links']], true); + if ($sanitizerConfig['allowed_media_schemes']) { + $def->addMethodCall('allowMediaSchemes', [$sanitizerConfig['allowed_media_schemes']], true); + } + $def->addMethodCall('allowMediaHosts', [$sanitizerConfig['allowed_media_hosts']], true); + $def->addMethodCall('allowRelativeMedias', [$sanitizerConfig['allow_relative_medias']], true); + + // Custom attribute sanitizers + foreach ($sanitizerConfig['with_attribute_sanitizers'] as $serviceName) { + $def->addMethodCall('withAttributeSanitizer', [new Reference($serviceName)], true); + } + + foreach ($sanitizerConfig['without_attribute_sanitizers'] as $serviceName) { + $def->addMethodCall('withoutAttributeSanitizer', [new Reference($serviceName)], true); + } + + if ($sanitizerConfig['max_input_length']) { + $def->addMethodCall('withMaxInputLength', [$sanitizerConfig['max_input_length']], true); + } + + // Create the sanitizer and link its config + $sanitizerId = 'html_sanitizer.sanitizer.'.$sanitizerName; + $container->register($sanitizerId, HtmlSanitizer::class) + ->addTag('html_sanitizer', ['sanitizer' => $sanitizerName]) + ->addArgument(new Reference($configId)); + + if ('default' !== $sanitizerName) { + $container->registerAliasForArgument($sanitizerId, HtmlSanitizerInterface::class, $sanitizerName); + } + } } private function resolveTrustedHeaders(array $headers): int diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 794686e3cdf5f..3b86ea1344fcf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -44,6 +44,7 @@ use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; use Symfony\Component\Form\DependencyInjection\FormPass; use Symfony\Component\HttpClient\DependencyInjection\HttpClientPass; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; @@ -94,6 +95,10 @@ public function boot() if ($this->container->getParameter('kernel.http_method_override')) { Request::enableHttpMethodParameterOverride(); } + + if ($this->container->hasParameter('kernel.trust_x_sendfile_type_header') && $this->container->getParameter('kernel.trust_x_sendfile_type_header')) { + BinaryFileResponse::trustXSendfileTypeHeader(); + } } public function build(ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php index f32286a8d9bfa..dbf77b3bd94bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php @@ -82,6 +82,10 @@ private function configureRoutes(RoutingConfigurator $routes): void } else { $routes->import($configDir.'/{routes}.php'); } + + if (false !== ($fileName = (new \ReflectionObject($this))->getFileName())) { + $routes->import($fileName, 'annotation'); + } } /** @@ -214,6 +218,8 @@ public function loadRoutes(LoaderInterface $loader): RouteCollection if (\is_array($controller) && [0, 1] === array_keys($controller) && $this === $controller[0]) { $route->setDefault('_controller', ['kernel', $controller[1]]); + } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !str_contains($r->name, '{closure}')) { + $route->setDefault('_controller', ['kernel', $r->name]); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php index 6795e3c22aa0e..999b5a1c501ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php +++ b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php @@ -115,11 +115,11 @@ public function loginUser(object $user, string $firewallContext = 'main'): stati } if (!$user instanceof UserInterface) { - throw new \LogicException(sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, \is_object($user) ? \get_class($user) : \gettype($user))); + throw new \LogicException(sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, get_debug_type($user))); } $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); - // required for compatibilty with Symfony 5.4 + // required for compatibility with Symfony 5.4 if (method_exists($token, 'isAuthenticated')) { $token->setAuthenticated(true, false); } @@ -156,6 +156,7 @@ protected function doRequest(object $request): Response // avoid shutting down the Kernel if no request has been performed yet // WebTestCase::createClient() boots the Kernel but do not handle a request if ($this->hasPerformedRequest && $this->reboot) { + $this->kernel->boot(); $this->kernel->shutdown(); } else { $this->hasPerformedRequest = true; diff --git a/src/Symfony/Bundle/FrameworkBundle/LICENSE b/src/Symfony/Bundle/FrameworkBundle/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/LICENSE +++ b/src/Symfony/Bundle/FrameworkBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bundle/FrameworkBundle/README.md b/src/Symfony/Bundle/FrameworkBundle/README.md index 76c7700fa03af..db59697577dde 100644 --- a/src/Symfony/Bundle/FrameworkBundle/README.md +++ b/src/Symfony/Bundle/FrameworkBundle/README.md @@ -4,6 +4,19 @@ FrameworkBundle FrameworkBundle provides a tight integration between Symfony components and the Symfony full-stack framework. +Sponsor +------- + +The FrameworkBundle for Symfony 6.1 is [backed][1] by [alximy][2]. + +A team of passionate humans from very different backgrounds, sharing their love of +PHP, Symfony and its ecosystem. Their CTO, Expert developers, tech leads, can help +you learn or develop the tools you need, and perform audits or tailored workshops. +They value contributing to the Open Source community and are willing to mentor new +contributors in their team or yours. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -11,3 +24,7 @@ Resources * [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) + +[1]: https://symfony.com/backers +[2]: https://alximy.io/ +[3]: https://symfony.com/sponsor diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php index 4920c43ebe182..55658f5b19b76 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + require dirname(__DIR__, 6).'/vendor/autoload.php'; use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php index fd25a3ab2fb2e..ec86fed495498 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.php @@ -25,7 +25,7 @@ ->set('annotations.reader', AnnotationReader::class) ->call('addGlobalIgnoredName', [ 'required', - service('annotations.dummy_registry'), // dummy arg to register class_exists as annotation loader only when required + service('annotations.dummy_registry')->nullOnInvalid(), // dummy arg to register class_exists as annotation loader only when required ]) ->set('annotations.dummy_registry', AnnotationRegistry::class) @@ -37,6 +37,8 @@ inline_service(ArrayAdapter::class), abstract_arg('Debug-Flag'), ]) + ->tag('annotations.cached_reader') + ->tag('container.do_not_inline') ->set('annotations.filesystem_cache_adapter', FilesystemAdapter::class) ->args([ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.php index 82461d91a69dd..8f29d9f1dc579 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.php @@ -35,5 +35,5 @@ ], ]) ->tag('kernel.cache_warmer', ['priority' => 64]) - ; + ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.php index ca0362a3e0965..7ac9f905337ba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.php @@ -21,5 +21,5 @@ ->set('esi_listener', SurrogateListener::class) ->args([service('esi')->ignoreOnInvalid()]) ->tag('kernel.event_subscriber') - ; + ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.php index 75bfb7eb651af..3c936a284b325 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.php @@ -19,8 +19,10 @@ use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension; use Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension; +use Symfony\Component\Form\Extension\HtmlSanitizer\Type\TextTypeHtmlSanitizerExtension; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\Extension\HttpFoundation\Type\FormTypeHttpFoundationExtension; use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; @@ -113,6 +115,10 @@ ->args([service('translator')->ignoreOnInvalid()]) ->tag('form.type_extension', ['extended-type' => FormType::class]) + ->set('form.type_extension.form.html_sanitizer', TextTypeHtmlSanitizerExtension::class) + ->args([tagged_locator('html_sanitizer', 'sanitizer')]) + ->tag('form.type_extension', ['extended-type' => TextType::class]) + ->set('form.type_extension.form.http_foundation', FormTypeHttpFoundationExtension::class) ->args([service('form.type_extension.form.request_handler')]) ->tag('form.type_extension') diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/html_sanitizer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/html_sanitizer.php new file mode 100644 index 0000000000000..175dc2e23d0da --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/html_sanitizer.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\HtmlSanitizer\HtmlSanitizer; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; + +return static function (ContainerConfigurator $container) { + $container->services() + ->set('html_sanitizer.config.default', HtmlSanitizerConfig::class) + ->call('allowSafeElements', [], true) + + ->set('html_sanitizer.sanitizer.default', HtmlSanitizer::class) + ->args([service('html_sanitizer.config.default')]) + ->tag('html_sanitizer', ['sanitizer' => 'default']) + + ->alias('html_sanitizer', 'html_sanitizer.sanitizer.default') + ->alias(HtmlSanitizerInterface::class, 'html_sanitizer') + ; +}; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php index 73beb2c346698..fde0533140809 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier.php @@ -22,6 +22,7 @@ use Symfony\Component\Notifier\ChatterInterface; use Symfony\Component\Notifier\EventListener\NotificationLoggerListener; use Symfony\Component\Notifier\EventListener\SendFailedMessageToNotifierListener; +use Symfony\Component\Notifier\FlashMessage\DefaultFlashMessageImportanceMapper; use Symfony\Component\Notifier\Message\ChatMessage; use Symfony\Component\Notifier\Message\PushMessage; use Symfony\Component\Notifier\Message\SmsMessage; @@ -43,8 +44,11 @@ ->set('notifier.channel_policy', ChannelPolicy::class) ->args([[]]) + ->set('notifier.flash_message_importance_mapper', DefaultFlashMessageImportanceMapper::class) + ->args([[]]) + ->set('notifier.channel.browser', BrowserChannel::class) - ->args([service('request_stack')]) + ->args([service('request_stack'), service('notifier.flash_message_importance_mapper')]) ->tag('notifier.channel', ['channel' => 'browser']) ->set('notifier.channel.chat', ChatChannel::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php index 647d056406c6e..819177c337787 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php @@ -15,6 +15,7 @@ use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory; use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory; use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory; +use Symfony\Component\Notifier\Bridge\Engagespot\EngagespotTransportFactory; use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory; use Symfony\Component\Notifier\Bridge\Expo\ExpoTransportFactory; use Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory; @@ -42,6 +43,7 @@ use Symfony\Component\Notifier\Bridge\OrangeSms\OrangeSmsTransportFactory; use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; +use Symfony\Component\Notifier\Bridge\Sendberry\SendberryTransportFactory; use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory; use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; @@ -155,6 +157,10 @@ ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') + ->set('notifier.transport_factory.sendberry', SendberryTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory') + ->set('notifier.transport_factory.sendinblue', SendinblueTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') @@ -256,5 +262,9 @@ ->set('notifier.transport_factory.kaz-info-teh', KazInfoTehTransportFactory::class) ->parent('notifier.transport_factory.abstract') ->tag('texter.transport_factory') + + ->set('notifier.transport_factory.engagespot', EngagespotTransportFactory::class) + ->parent('notifier.transport_factory.abstract') + ->tag('texter.transport_factory') ; }; 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 d48e8ca1520f7..242c65e56a908 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 @@ -30,7 +30,9 @@ + + @@ -38,10 +40,12 @@ + + @@ -100,6 +104,7 @@ + @@ -291,7 +296,14 @@ - + + + + + + + + @@ -353,14 +365,29 @@ - + - - + - + + + + + + + + + + + + + + + + + @@ -481,6 +508,21 @@ + + + + + + + + + + + + + + + @@ -802,4 +844,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/semaphore.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/semaphore.php new file mode 100644 index 0000000000000..ce35c25089548 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/semaphore.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\Semaphore\SemaphoreFactory; + +return static function (ContainerConfigurator $container) { + $container->services() + ->set('semaphore.factory.abstract', SemaphoreFactory::class)->abstract() + ->args([abstract_arg('Store')]) + ->call('setLogger', [service('logger')->ignoreOnInvalid()]) + ->tag('monolog.logger', ['channel' => 'semaphore']) + ; +}; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index 5655c05a26e35..5ffc869ca7bd9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -76,7 +76,8 @@ // Normalizer ->set('serializer.normalizer.constraint_violation_list', ConstraintViolationListNormalizer::class) - ->args([[], service('serializer.name_converter.metadata_aware')]) + ->args([1 => service('serializer.name_converter.metadata_aware')]) + ->autowire(true) ->tag('serializer.normalizer', ['priority' => -915]) ->set('serializer.normalizer.mime_message', MimeMessageNormalizer::class) @@ -98,7 +99,7 @@ ->set('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class) ->args([null, null]) - ->tag('serializer.normalizer', ['priority' => -900]) + ->tag('serializer.normalizer', ['priority' => -950]) ->set('serializer.normalizer.problem', ProblemNormalizer::class) ->args([param('kernel.debug')]) @@ -122,7 +123,6 @@ service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, - [], ]) ->tag('serializer.normalizer', ['priority' => -1000]) @@ -135,7 +135,6 @@ service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, - [], ]) ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') @@ -174,6 +173,7 @@ ->tag('serializer.encoder') ->set('serializer.encoder.json', JsonEncoder::class) + ->args([null, null]) ->tag('serializer.encoder') ->set('serializer.encoder.yaml', YamlEncoder::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer_debug.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer_debug.php new file mode 100644 index 0000000000000..45b764fdd6b7d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer_debug.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\Serializer\DataCollector\SerializerDataCollector; +use Symfony\Component\Serializer\Debug\TraceableSerializer; + +return static function (ContainerConfigurator $container) { + $container->services() + ->set('debug.serializer', TraceableSerializer::class) + ->decorate('serializer') + ->args([ + service('debug.serializer.inner'), + service('serializer.data_collector'), + ]) + + ->set('serializer.data_collector', SerializerDataCollector::class) + ->tag('data_collector', [ + 'template' => '@WebProfiler/Collector/serializer.html.twig', + 'id' => 'serializer', + ]) + ; +}; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php index 2a6e18e835e42..f662343e331b8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php @@ -200,6 +200,14 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] ]) ->tag('routing.expression_language_function', ['function' => 'env']) + ->set('container.get_routing_condition_service', \Closure::class) + ->public() + ->factory([\Closure::class, 'fromCallable']) + ->args([ + [tagged_locator('routing.condition_service', 'alias'), 'get'], + ]) + ->tag('routing.expression_language_function', ['function' => 'service']) + // inherit from this service to lazily access env vars ->set('container.env', LazyString::class) ->abstract() diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php index 185e85838271c..30a622d02c8fb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.php @@ -77,7 +77,7 @@ ->set('session.abstract_handler', AbstractSessionHandler::class) ->factory([SessionHandlerFactory::class, 'createHandler']) - ->args([abstract_arg('A string or a connection object')]) + ->args([abstract_arg('A string or a connection object'), []]) ->set('session_listener', SessionListener::class) ->args([ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php index 706e4928ee2e0..e40f1aae4d619 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php @@ -39,11 +39,13 @@ use Symfony\Component\Translation\Loader\QtFileLoader; use Symfony\Component\Translation\Loader\XliffFileLoader; use Symfony\Component\Translation\Loader\YamlFileLoader; +use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Component\Translation\LoggingTranslator; use Symfony\Component\Translation\Reader\TranslationReader; use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Symfony\Component\Translation\Writer\TranslationWriter; use Symfony\Component\Translation\Writer\TranslationWriterInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; use Symfony\Contracts\Translation\TranslatorInterface; return static function (ContainerConfigurator $container) { @@ -114,6 +116,10 @@ ->set('translation.dumper.xliff', XliffFileDumper::class) ->tag('translation.dumper', ['alias' => 'xlf']) + ->set('translation.dumper.xliff.xliff', XliffFileDumper::class) + ->args(['xliff']) + ->tag('translation.dumper', ['alias' => 'xliff']) + ->set('translation.dumper.po', PoFileDumper::class) ->tag('translation.dumper', ['alias' => 'po']) @@ -158,5 +164,16 @@ ->args([service(ContainerInterface::class)]) ->tag('container.service_subscriber', ['id' => 'translator']) ->tag('kernel.cache_warmer') + + ->set('translation.locale_switcher', LocaleSwitcher::class) + ->args([ + param('kernel.default_locale'), + tagged_iterator('kernel.locale_aware', exclude: 'translation.locale_switcher'), + service('router.request_context')->ignoreOnInvalid(), + ]) + ->tag('kernel.reset', ['method' => 'reset']) + ->tag('kernel.locale_aware') + ->alias(LocaleAwareInterface::class, 'translation.locale_switcher') + ->alias(LocaleSwitcher::class, 'translation.locale_switcher') ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php index 2eaa5b5ec2c78..3fd066ee37f1f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.php @@ -102,5 +102,5 @@ service('property_info'), ]) ->tag('validator.auto_mapper') - ; + ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php index a7d91bfd4a69d..d28e88995f84c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php @@ -14,11 +14,13 @@ use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DateTimeValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\UidValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; use Symfony\Component\HttpKernel\Controller\ErrorController; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; @@ -26,7 +28,6 @@ use Symfony\Component\HttpKernel\EventListener\ErrorListener; use Symfony\Component\HttpKernel\EventListener\LocaleListener; use Symfony\Component\HttpKernel\EventListener\ResponseListener; -use Symfony\Component\HttpKernel\EventListener\StreamedResponseListener; use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener; return static function (ContainerConfigurator $container) { @@ -47,9 +48,13 @@ ]) ->set('argument_resolver.backed_enum_resolver', BackedEnumValueResolver::class) - ->tag('controller.argument_value_resolver', [ - 'priority' => 105, // prior to the RequestAttributeValueResolver - ]) + ->tag('controller.argument_value_resolver', ['priority' => 100]) + + ->set('argument_resolver.uid', UidValueResolver::class) + ->tag('controller.argument_value_resolver', ['priority' => 100]) + + ->set('argument_resolver.datetime', DateTimeValueResolver::class) + ->tag('controller.argument_value_resolver', ['priority' => 100]) ->set('argument_resolver.request_attribute', RequestAttributeValueResolver::class) ->tag('controller.argument_value_resolver', ['priority' => 100]) @@ -79,9 +84,6 @@ ]) ->tag('kernel.event_subscriber') - ->set('streamed_response_listener', StreamedResponseListener::class) - ->tag('kernel.event_subscriber') - ->set('locale_listener', LocaleListener::class) ->args([ service('request_stack'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Attribute/AsRoutingConditionService.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Attribute/AsRoutingConditionService.php new file mode 100644 index 0000000000000..d1f1a5f34a654 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Attribute/AsRoutingConditionService.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing\Attribute; + +use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; + +/** + * Service tag to autoconfigure routing condition services. + * + * You can tag a service: + * + * #[AsRoutingConditionService('foo')] + * class SomeFooService + * { + * public function bar(): bool + * { + * // ... + * } + * } + * + * Then you can use the tagged service in the routing condition: + * + * class PageController + * { + * #[Route('/page', condition: "service('foo').bar()")] + * public function page(): Response + * { + * // ... + * } + * } + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class AsRoutingConditionService extends AutoconfigureTag +{ + public function __construct( + string $alias = null, + int $priority = 0, + ) { + parent::__construct('routing.condition_service', ['alias' => $alias, 'priority' => $priority]); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index b213019d3579a..8fda00a771fe0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -49,9 +49,9 @@ public function __construct(ContainerInterface $container, mixed $resource, arra $this->setOptions($options); if ($parameters) { - $this->paramFetcher = \Closure::fromCallable([$parameters, 'get']); + $this->paramFetcher = $parameters->get(...); } elseif ($container instanceof SymfonyContainerInterface) { - $this->paramFetcher = \Closure::fromCallable([$container, 'getParameter']); + $this->paramFetcher = $container->getParameter(...); } else { throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); } @@ -76,7 +76,7 @@ public function getRouteCollection(): RouteCollection } else { $this->collection->addResource(new FileExistenceResource($containerFile)); } - } catch (ParameterNotFoundException $exception) { + } catch (ParameterNotFoundException) { } } @@ -175,14 +175,14 @@ private function resolve(mixed $value): mixed $resolved = ($this->paramFetcher)($match[1]); - if (is_scalar($resolved)) { + if (\is_scalar($resolved)) { $this->collectedParameters[$match[1]] = $resolved; if (\is_string($resolved)) { $resolved = $this->resolve($resolved); } - if (is_scalar($resolved)) { + if (\is_scalar($resolved)) { return false === $resolved ? '0' : (string) $resolved; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php b/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php index 1f8cbff6693f2..ff1cd7fb87908 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php +++ b/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php @@ -51,7 +51,7 @@ public function generateKeys(bool $override = false): bool try { $this->loadKeys(); - } catch (\RuntimeException $e) { + } catch (\RuntimeException) { // ignore failures to load keys } diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index d68ae4c8b3ba5..d189b88db5799 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Test; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\HttpKernel\KernelInterface; @@ -35,11 +36,10 @@ abstract class KernelTestCase extends TestCase protected static $booted = false; - private static ?ContainerInterface $kernelContainer = null; - protected function tearDown(): void { static::ensureKernelShutdown(); + static::$class = null; static::$kernel = null; static::$booted = false; } @@ -68,12 +68,11 @@ protected static function bootKernel(array $options = []): KernelInterface { static::ensureKernelShutdown(); - static::$kernel = static::createKernel($options); - static::$kernel->boot(); + $kernel = static::createKernel($options); + $kernel->boot(); + static::$kernel = $kernel; static::$booted = true; - self::$kernelContainer = static::$kernel->getContainer(); - return static::$kernel; } @@ -85,7 +84,7 @@ protected static function bootKernel(array $options = []): KernelInterface * * Using this method is the best way to get a container from your test code. * - * @return TestContainer + * @return Container */ protected static function getContainer(): ContainerInterface { @@ -94,7 +93,7 @@ protected static function getContainer(): ContainerInterface } try { - return self::$kernelContainer->get('test.service_container'); + return self::$kernel->getContainer()->get('test.service_container'); } catch (ServiceNotFoundException $e) { throw new \LogicException('Could not find service "test.service_container". Try updating the "framework.test" config to "true".', 0, $e); } @@ -143,14 +142,14 @@ protected static function createKernel(array $options = []): KernelInterface protected static function ensureKernelShutdown() { if (null !== static::$kernel) { + static::$kernel->boot(); + $container = static::$kernel->getContainer(); static::$kernel->shutdown(); static::$booted = false; - } - if (self::$kernelContainer instanceof ResetInterface) { - self::$kernelContainer->reset(); + if ($container instanceof ResetInterface) { + $container->reset(); + } } - - self::$kernelContainer = null; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php b/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php index 875c84d4813da..d6b29d2b5a0c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php @@ -91,7 +91,7 @@ public static function assertEmailAddressContains(RawMessage $email, string $hea } /** - * @return MessageEvents[] + * @return MessageEvent[] */ public static function getMailerEvents(string $transport = null): array { @@ -123,10 +123,6 @@ private static function getMessageMailerEvents(): MessageEvents return $container->get('mailer.message_logger_listener')->getEvents(); } - if ($container->has('mailer.logger_message_listener')) { - return $container->get('mailer.logger_message_listener')->getEvents(); - } - static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php index 1f7f0802d3ce1..de31d4ba92c94 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php @@ -45,7 +45,7 @@ protected static function createClient(array $options = [], array $server = []): try { $client = $kernel->getContainer()->get('test.client'); - } catch (ServiceNotFoundException $e) { + } catch (ServiceNotFoundException) { if (class_exists(KernelBrowser::class)) { throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php index 8253c525df8f6..75e6ce8f7271b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/AnnotationsCacheWarmerTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; use Doctrine\Common\Annotations\AnnotationReader; @@ -151,10 +160,7 @@ public function testWarmupRemoveCacheMisses() $this->assertTrue(isset($data[0]['bar_hit'])); } - /** - * @return MockObject&Reader - */ - private function getReadOnlyReader(): Reader + private function getReadOnlyReader(): MockObject&Reader { $readerMock = $this->createMock(Reader::class); $readerMock->expects($this->exactly(0))->method('getClassAnnotations'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/Fixture/TestAppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/Fixture/TestAppKernel.php index c15bf83cb1cf8..cc55da770ed2d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/Fixture/TestAppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/Fixture/TestAppKernel.php @@ -32,6 +32,11 @@ public function getProjectDir(): string public function registerContainerConfiguration(LoaderInterface $loader) { + $loader->load(static function (ContainerBuilder $container) { + $container->loadFromExtension('framework', [ + 'http_method_override' => false, + ]); + }); } protected function build(ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/config.yml index 68f8d040610c4..449f26f2b7d1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/config.yml @@ -1,2 +1,3 @@ framework: + http_method_override: false secret: test diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php index 169fcd8c2d75d..722199f227296 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php @@ -52,10 +52,7 @@ public function provideCompletionSuggestions() ]; } - /** - * @return MockObject&KernelInterface - */ - private function getKernel(): KernelInterface + private function getKernel(): MockObject&KernelInterface { $container = $this->createMock(ContainerInterface::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php index f643bc1259901..24371b9f532dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php @@ -106,10 +106,7 @@ public function provideCompletionSuggestions() ]; } - /** - * @return MockObject&KernelInterface - */ - private function getKernel(): KernelInterface + private function getKernel(): MockObject&KernelInterface { $container = $this->createMock(ContainerInterface::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php index 32d60124ebb5a..983956fcb9b82 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php @@ -50,10 +50,7 @@ private function getEmptyRewindableGenerator(): RewindableGenerator }, 0); } - /** - * @return MockObject&KernelInterface - */ - private function getKernel(): KernelInterface + private function getKernel(): MockObject&KernelInterface { $container = $this->createMock(ContainerInterface::class); @@ -71,10 +68,7 @@ private function getKernel(): KernelInterface return $kernel; } - /** - * @return MockObject&PruneableInterface - */ - private function getPruneableInterfaceMock(): PruneableInterface + private function getPruneableInterfaceMock(): MockObject&PruneableInterface { $pruneable = $this->createMock(PruneableInterface::class); $pruneable diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php index 213e639f06698..c02bc91761084 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php index 4f0d2225d148a..135907b374d26 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index d755e11e730af..70f94d6a34d48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -15,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\ExtensionWithoutConfigTestBundle; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\DependencyInjection\Container; @@ -36,7 +37,7 @@ public function testDebugMissingMessages() $res = $tester->execute(['locale' => 'en', 'bundle' => 'foo']); $this->assertMatchesRegularExpression('/missing/', $tester->getDisplay()); - $this->assertEquals(TranslationDebugCommand::EXIT_CODE_MISSING, $res); + $this->assertSame(TranslationDebugCommand::EXIT_CODE_MISSING, $res); } public function testDebugUnusedMessages() @@ -45,7 +46,7 @@ public function testDebugUnusedMessages() $res = $tester->execute(['locale' => 'en', 'bundle' => 'foo']); $this->assertMatchesRegularExpression('/unused/', $tester->getDisplay()); - $this->assertEquals(TranslationDebugCommand::EXIT_CODE_UNUSED, $res); + $this->assertSame(TranslationDebugCommand::EXIT_CODE_UNUSED, $res); } public function testDebugFallbackMessages() @@ -54,7 +55,7 @@ public function testDebugFallbackMessages() $res = $tester->execute(['locale' => 'fr', 'bundle' => 'foo']); $this->assertMatchesRegularExpression('/fallback/', $tester->getDisplay()); - $this->assertEquals(TranslationDebugCommand::EXIT_CODE_FALLBACK, $res); + $this->assertSame(TranslationDebugCommand::EXIT_CODE_FALLBACK, $res); } public function testNoDefinedMessages() @@ -63,7 +64,7 @@ public function testNoDefinedMessages() $res = $tester->execute(['locale' => 'fr', 'bundle' => 'test']); $this->assertMatchesRegularExpression('/No defined or extracted messages for locale "fr"/', $tester->getDisplay()); - $this->assertEquals(TranslationDebugCommand::EXIT_CODE_GENERAL_ERROR, $res); + $this->assertSame(TranslationDebugCommand::EXIT_CODE_GENERAL_ERROR, $res); } public function testDebugDefaultDirectory() @@ -74,7 +75,7 @@ public function testDebugDefaultDirectory() $this->assertMatchesRegularExpression('/missing/', $tester->getDisplay()); $this->assertMatchesRegularExpression('/unused/', $tester->getDisplay()); - $this->assertEquals($expectedExitStatus, $res); + $this->assertSame($expectedExitStatus, $res); } public function testDebugDefaultRootDirectory() @@ -92,7 +93,7 @@ public function testDebugDefaultRootDirectory() $this->assertMatchesRegularExpression('/missing/', $tester->getDisplay()); $this->assertMatchesRegularExpression('/unused/', $tester->getDisplay()); - $this->assertEquals($expectedExitStatus, $res); + $this->assertSame($expectedExitStatus, $res); } public function testDebugCustomDirectory() @@ -112,7 +113,7 @@ public function testDebugCustomDirectory() $this->assertMatchesRegularExpression('/missing/', $tester->getDisplay()); $this->assertMatchesRegularExpression('/unused/', $tester->getDisplay()); - $this->assertEquals($expectedExitStatus, $res); + $this->assertSame($expectedExitStatus, $res); } public function testDebugInvalidDirectory() @@ -128,6 +129,22 @@ public function testDebugInvalidDirectory() $tester->execute(['locale' => 'en', 'bundle' => 'dir']); } + public function testNoErrorWithOnlyMissingOptionAndNoResults() + { + $tester = $this->createCommandTester([], ['foo' => 'foo']); + $res = $tester->execute(['locale' => 'en', '--only-missing' => true]); + + $this->assertSame(Command::SUCCESS, $res); + } + + public function testNoErrorWithOnlyUnusedOptionAndNoResults() + { + $tester = $this->createCommandTester(['foo' => 'foo']); + $res = $tester->execute(['locale' => 'en', '--only-unused' => true]); + + $this->assertSame(Command::SUCCESS, $res); + } + protected function setUp(): void { $this->fs = new Filesystem(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index 5c6fa8ec35ea2..f883fac0c57ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -140,6 +140,46 @@ public function testWriteMessagesForSpecificDomain() $this->assertMatchesRegularExpression('/Translation files were successfully updated./', $tester->getDisplay()); } + public function testFilterDuplicateTransPaths() + { + $transPaths = [ + $this->translationDir.'/a/test/folder/with/a/subfolder', + $this->translationDir.'/a/test/folder/', + $this->translationDir.'/a/test/folder/with/a/subfolder/and/a/file.txt', + $this->translationDir.'/a/different/test/folder', + ]; + + foreach ($transPaths as $transPath) { + if (realpath($transPath)) { + continue; + } + + if (preg_match('/\.[a-z]+$/', $transPath)) { + if (!realpath(\dirname($transPath))) { + mkdir(\dirname($transPath), 0777, true); + } + + touch($transPath); + } else { + mkdir($transPath, 0777, true); + } + } + + $command = $this->createMock(TranslationUpdateCommand::class); + + $method = new \ReflectionMethod(TranslationUpdateCommand::class, 'filterDuplicateTransPaths'); + $method->setAccessible(true); + + $filteredTransPaths = $method->invoke($command, $transPaths); + + $expectedPaths = [ + realpath($this->translationDir.'/a/different/test/folder'), + realpath($this->translationDir.'/a/test/folder'), + ]; + + $this->assertEquals($expectedPaths, $filteredTransPaths); + } + protected function setUp(): void { $this->fs = new Filesystem(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php index 3a38da0d14ed6..fa5a2711820f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -122,9 +122,7 @@ public function getDescribeContainerDefinitionWithArgumentsShownTestData() $definitionsWithArgs[str_replace('definition_', 'definition_arguments_', $key)] = $definition; } - if (\PHP_VERSION_ID >= 80100) { - $definitionsWithArgs['definition_arguments_with_enum'] = (new Definition('definition_with_enum'))->setArgument(0, FooUnitEnum::FOO); - } + $definitionsWithArgs['definition_arguments_with_enum'] = (new Definition('definition_with_enum'))->setArgument(0, FooUnitEnum::FOO); return $this->getDescriptionTestData($definitionsWithArgs); } @@ -208,11 +206,25 @@ public function testDescribeCallable($callable, $expectedDescription) $this->assertDescription($expectedDescription, $callable); } - public function getDescribeCallableTestData() + public function getDescribeCallableTestData(): array { return $this->getDescriptionTestData(ObjectsProvider::getCallables()); } + /** + * @group legacy + * @dataProvider getDescribeDeprecatedCallableTestData + */ + public function testDescribeDeprecatedCallable($callable, $expectedDescription) + { + $this->assertDescription($expectedDescription, $callable); + } + + public function getDescribeDeprecatedCallableTestData(): array + { + return $this->getDescriptionTestData(ObjectsProvider::getDeprecatedCallables()); + } + /** @dataProvider getClassDescriptionTestData */ public function testGetClassDescription($object, $expectedDescription) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index a9fc9252bf350..94fcbcfa3bcd3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -71,10 +71,6 @@ public static function getContainerParameters() 'array' => [12, 'Hello world!', true], ]); - if (\PHP_VERSION_ID < 80100) { - return; - } - yield 'parameters_enums' => new ParameterBag([ 'unit_enum' => FooUnitEnum::BAR, 'backed_enum' => Suit::Hearts, @@ -142,6 +138,7 @@ public static function getContainerDefinitions() { $definition1 = new Definition('Full\\Qualified\\Class1'); $definition2 = new Definition('Full\\Qualified\\Class2'); + $definition3 = new Definition('Full\\Qualified\\Class3'); return [ 'definition_1' => $definition1 @@ -174,6 +171,9 @@ public static function getContainerDefinitions() ->addTag('tag2') ->addMethodCall('setMailer', [new Reference('mailer')]) ->setFactory([new Reference('factory.service'), 'get']), + '.definition_3' => $definition3 + ->setFile('/path/to/file') + ->setFactory([new Definition('Full\\Qualified\\FactoryClass'), 'get']), 'definition_without_class' => new Definition(), ]; } @@ -249,17 +249,23 @@ public static function getEventDispatchers() return ['event_dispatcher_1' => $eventDispatcher]; } - public static function getCallables() + public static function getCallables(): array { return [ 'callable_1' => 'array_key_exists', 'callable_2' => ['Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass', 'staticMethod'], 'callable_3' => [new CallableClass(), 'method'], 'callable_4' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass::staticMethod', - 'callable_5' => ['Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\ExtendedCallableClass', 'parent::staticMethod'], 'callable_6' => function () { return 'Closure'; }, 'callable_7' => new CallableClass(), - 'callable_from_callable' => \Closure::fromCallable(new CallableClass()), + 'callable_from_callable' => (new CallableClass())(...), + ]; + } + + public static function getDeprecatedCallables(): array + { + return [ + 'callable_5' => ['Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\ExtendedCallableClass', 'parent::staticMethod'], ]; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index f4215d39832de..da6997df578c4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -79,10 +79,6 @@ public function testSubscribedServices() public function testGetParameter() { - if (!class_exists(ContainerBag::class)) { - $this->markTestSkipped('ContainerBag class does not exist'); - } - $container = new Container(new FrozenParameterBag(['foo' => 'bar'])); $container->set('parameter_bag', new ContainerBag($container)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php index 7dc9e6f59ec99..355b1527d64bf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php @@ -43,6 +43,13 @@ public function testProcess() ->setPublic(true) ->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42']) ; + $container->register('Test\soon_private_service_decorated') + ->setPublic(true) + ->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42']) + ; + $container->register('Test\soon_private_service_decorator') + ->setDecoratedService('Test\soon_private_service_decorated') + ->setArguments(['Test\soon_private_service_decorator.inner']); $container->register('Test\private_used_shared_service'); $container->register('Test\private_unused_shared_service'); @@ -55,6 +62,8 @@ public function testProcess() 'Test\private_used_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_shared_service')), 'Test\private_used_non_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_non_shared_service')), 'Test\soon_private_service' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service')), + 'Test\soon_private_service_decorator' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')), + 'Test\soon_private_service_decorated' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')), ]; $privateServices = $container->getDefinition('test.private_services_locator')->getArgument(0); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 5a769c85f5e5f..035031a18a9d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -15,9 +15,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration; use Symfony\Bundle\FullStack; +use Symfony\Component\Cache\Adapter\DoctrineAdapter; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HtmlSanitizer\HtmlSanitizer; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Mailer\Mailer; @@ -31,7 +33,7 @@ class ConfigurationTest extends TestCase public function testDefaultConfig() { $processor = new Processor(); - $config = $processor->processConfiguration(new Configuration(true), [['secret' => 's3cr3t']]); + $config = $processor->processConfiguration(new Configuration(true), [['http_method_override' => false, 'secret' => 's3cr3t']]); $this->assertEquals(self::getBundleDefaultConfig(), $config); } @@ -55,7 +57,7 @@ public function testInvalidSessionName($sessionName) $processor = new Processor(); $processor->processConfiguration( new Configuration(true), - [['session' => ['name' => $sessionName]]] + [['http_method_override' => false, 'session' => ['name' => $sessionName]]] ); } @@ -75,7 +77,7 @@ public function testAssetsCanBeEnabled() { $processor = new Processor(); $configuration = new Configuration(true); - $config = $processor->processConfiguration($configuration, [['assets' => null]]); + $config = $processor->processConfiguration($configuration, [['http_method_override' => false, 'assets' => null]]); $defaultConfig = [ 'enabled' => true, @@ -101,6 +103,7 @@ public function testValidAssetsPackageNameConfiguration($packageName) $configuration = new Configuration(true); $config = $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'assets' => [ 'packages' => [ $packageName => [], @@ -133,6 +136,7 @@ public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMess $configuration = new Configuration(true); $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'assets' => $assetConfig, ], ]); @@ -182,6 +186,7 @@ public function testValidLockConfiguration($lockConfig, $processedConfig) $configuration = new Configuration(true); $config = $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'lock' => $lockConfig, ], ]); @@ -242,11 +247,13 @@ public function testLockMergeConfigs() $configuration = new Configuration(true); $config = $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'lock' => [ 'payload' => 'flock', ], ], [ + 'http_method_override' => false, 'lock' => [ 'payload' => 'semaphore', ], @@ -264,6 +271,58 @@ public function testLockMergeConfigs() ); } + /** + * @dataProvider provideValidSemaphoreConfigurationTests + */ + public function testValidSemaphoreConfiguration($semaphoreConfig, $processedConfig) + { + $processor = new Processor(); + $configuration = new Configuration(true); + $config = $processor->processConfiguration($configuration, [ + [ + 'http_method_override' => false, + 'semaphore' => $semaphoreConfig, + ], + ]); + + $this->assertArrayHasKey('semaphore', $config); + + $this->assertEquals($processedConfig, $config['semaphore']); + } + + public function provideValidSemaphoreConfigurationTests() + { + yield [null, ['enabled' => true, 'resources' => []]]; + + yield ['redis://default', ['enabled' => true, 'resources' => ['default' => 'redis://default']]]; + yield [['foo' => 'redis://foo', 'bar' => 'redis://bar'], ['enabled' => true, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']]]; + yield [['default' => 'redis://default'], ['enabled' => true, 'resources' => ['default' => 'redis://default']]]; + + yield [['enabled' => false, 'redis://default'], ['enabled' => false, 'resources' => ['default' => 'redis://default']]]; + yield [['enabled' => false, 'foo' => 'redis://foo', 'bar' => 'redis://bar'], ['enabled' => false, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']]]; + yield [['enabled' => false, 'default' => 'redis://default'], ['enabled' => false, 'resources' => ['default' => 'redis://default']]]; + + yield [['resources' => 'redis://default'], ['enabled' => true, 'resources' => ['default' => 'redis://default']]]; + yield [['resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']], ['enabled' => true, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']]]; + yield [['resources' => ['default' => 'redis://default']], ['enabled' => true, 'resources' => ['default' => 'redis://default']]]; + + yield [['enabled' => false, 'resources' => 'redis://default'], ['enabled' => false, 'resources' => ['default' => 'redis://default']]]; + yield [['enabled' => false, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']], ['enabled' => false, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']]]; + yield [['enabled' => false, 'resources' => ['default' => 'redis://default']], ['enabled' => false, 'resources' => ['default' => 'redis://default']]]; + + // xml + + yield [['resource' => ['redis://default']], ['enabled' => true, 'resources' => ['default' => 'redis://default']]]; + yield [['resource' => ['redis://default', ['name' => 'foo', 'value' => 'redis://default']]], ['enabled' => true, 'resources' => ['default' => 'redis://default', 'foo' => 'redis://default']]]; + yield [['resource' => [['name' => 'foo', 'value' => 'redis://default']]], ['enabled' => true, 'resources' => ['foo' => 'redis://default']]]; + yield [['resource' => [['name' => 'foo', 'value' => 'redis://default'], ['name' => 'bar', 'value' => 'redis://default']]], ['enabled' => true, 'resources' => ['foo' => 'redis://default', 'bar' => 'redis://default']]]; + + yield [['enabled' => false, 'resource' => ['redis://default']], ['enabled' => false, 'resources' => ['default' => 'redis://default']]]; + yield [['enabled' => false, 'resource' => ['redis://default', ['name' => 'foo', 'value' => 'redis://default']]], ['enabled' => false, 'resources' => ['default' => 'redis://default', 'foo' => 'redis://default']]]; + yield [['enabled' => false, 'resource' => [['name' => 'foo', 'value' => 'redis://default']]], ['enabled' => false, 'resources' => ['foo' => 'redis://default']]]; + yield [['enabled' => false, 'resource' => [['name' => 'foo', 'value' => 'redis://foo'], ['name' => 'bar', 'value' => 'redis://bar']]], ['enabled' => false, 'resources' => ['foo' => 'redis://foo', 'bar' => 'redis://bar']]]; + } + public function testItShowANiceMessageIfTwoMessengerBusesAreConfiguredButNoDefaultBus() { $expectedMessage = 'You must specify the "default_bus" if you define more than one bus.'; @@ -274,6 +333,7 @@ public function testItShowANiceMessageIfTwoMessengerBusesAreConfiguredButNoDefau $processor->processConfiguration($configuration, [ 'framework' => [ + 'http_method_override' => false, 'messenger' => [ 'default_bus' => null, 'buses' => [ @@ -291,6 +351,7 @@ public function testBusMiddlewareDontMerge() $configuration = new Configuration(true); $config = $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'messenger' => [ 'default_bus' => 'existing_bus', 'buses' => [ @@ -305,6 +366,7 @@ public function testBusMiddlewareDontMerge() ], ], [ + 'http_method_override' => false, 'messenger' => [ 'buses' => [ 'common_bus' => [ @@ -353,6 +415,7 @@ public function testItErrorsWhenDefaultBusDoesNotExist() $processor->processConfiguration($configuration, [ [ + 'http_method_override' => false, 'messenger' => [ 'default_bus' => 'foo', 'buses' => [ @@ -364,10 +427,42 @@ public function testItErrorsWhenDefaultBusDoesNotExist() ]); } + public function testLockCanBeDisabled() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $config = $processor->processConfiguration($configuration, [ + [ + 'http_method_override' => false, + 'lock' => ['enabled' => false], + ], + ]); + + $this->assertFalse($config['lock']['enabled']); + } + + public function testEnabledLockNeedsResources() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('Invalid configuration for path "framework.lock": At least one resource must be defined.'); + + $processor->processConfiguration($configuration, [ + [ + 'http_method_override' => false, + 'lock' => ['enabled' => true], + ], + ]); + } + protected static function getBundleDefaultConfig() { return [ - 'http_method_override' => true, + 'http_method_override' => false, + 'trust_x_sendfile_type_header' => false, 'ide' => '%env(default::SYMFONY_IDE)%', 'default_locale' => 'en', 'enabled_locales' => [], @@ -404,6 +499,7 @@ protected static function getBundleDefaultConfig() 'dsn' => 'file:%kernel.cache_dir%/profiler', 'collect' => true, 'collect_parameter' => null, + 'collect_serializer_data' => false, ], 'translator' => [ 'enabled' => !class_exists(FullStack::class), @@ -501,7 +597,7 @@ protected static function getBundleDefaultConfig() 'default_redis_provider' => 'redis://localhost', 'default_memcached_provider' => 'memcached://localhost', 'default_doctrine_dbal_provider' => 'database_connection', - 'default_pdo_provider' => ContainerBuilder::willBeAvailable('doctrine/dbal', Connection::class, ['symfony/framework-bundle']) ? 'database_connection' : null, + 'default_pdo_provider' => ContainerBuilder::willBeAvailable('doctrine/dbal', Connection::class, ['symfony/framework-bundle']) && class_exists(DoctrineAdapter::class) ? 'database_connection' : null, 'prefix_seed' => '_%kernel.project_dir%.%kernel.container_class%', ], 'workflows' => [ @@ -523,6 +619,11 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], ], ], + 'semaphore' => [ + 'enabled' => !class_exists(FullStack::class), + 'resources' => [ + ], + ], 'messenger' => [ 'enabled' => !class_exists(FullStack::class) && interface_exists(MessageBusInterface::class), 'routing' => [], @@ -581,6 +682,10 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor 'name_based_uuid_version' => 5, 'time_based_uuid_version' => 6, ], + 'html_sanitizer' => [ + 'enabled' => !class_exists(FullStack::class) && class_exists(HtmlSanitizer::class), + 'sanitizers' => [], + ], 'exceptions' => [], ]; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php index f26621001c9ec..4b71fb9c751ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'assets' => [ 'version' => 'SomeVersionScheme', 'base_urls' => 'http://cdn.example.com', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_disabled.php index d10595fba9df1..0513da761df91 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'assets' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_version_strategy_as_service.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_version_strategy_as_service.php index b57f78ba47bb5..611259c00c4f9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_version_strategy_as_service.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets_version_strategy_as_service.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'assets' => [ 'version_strategy' => 'assets.custom_version_strategy', 'base_urls' => 'http://cdn.example.com', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php index 9ca04b6c63bf9..13b659b6327a5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'cache' => [ 'pools' => [ 'cache.foo' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware.php index 44855c62adbf1..ca8834fc3697b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'cache' => [ 'app' => 'cache.adapter.redis_tag_aware', ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware_pool.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware_pool.php index bf3ee2de2b357..3ca0f1c77bfea 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware_pool.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/cache_app_redis_tag_aware_pool.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'cache' => [ 'app' => 'cache.redis_tag_aware.foo', 'pools' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf.php index 8b712475fda58..9db840d5194cd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'csrf_protection' => true, 'session' => [ 'storage_factory_id' => 'session.storage.factory.native', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf_needs_session.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf_needs_session.php index 34fdb4c1f9931..2e1a54221a28d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf_needs_session.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/csrf_needs_session.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'csrf_protection' => [ 'enabled' => true, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/default_config.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/default_config.php index 4b2021df7bb2e..34e2894f9fb9f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/default_config.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/default_config.php @@ -1,3 +1,4 @@ loadFromExtension('framework', []); +$container->loadFromExtension('framework', [ + 'http_method_override' => false,]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php index beada36b84359..facad13cdf786 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'fragments' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php index a24cd8158c6b7..76e3ddfbe766c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'esi' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/exceptions.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/exceptions.php index 5d0dde0e0ac64..be0663972ec5b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/exceptions.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/exceptions.php @@ -1,12 +1,28 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'exceptions' => [ BadRequestHttpException::class => [ 'log_level' => 'info', 'status_code' => 422, ], + NotFoundHttpException::class => [ + 'log_level' => 'info', + 'status_code' => null, + ], + ConflictHttpException::class => [ + 'log_level' => 'info', + 'status_code' => 0, + ], + ServiceUnavailableHttpException::class => [ + 'log_level' => null, + 'status_code' => 500, + ], ], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php new file mode 100644 index 0000000000000..3ab6a6a19e332 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_disabled.php @@ -0,0 +1,9 @@ +loadFromExtension('framework', [ + 'csrf_protection' => false, + 'form' => [ + 'csrf_protection' => true, + ], + 'http_method_override' => false, +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_default_csrf.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_default_csrf.php index a57d5233806fa..0c491714a05a9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_default_csrf.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_default_csrf.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'form' => [ 'legacy_error_messages' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php index e0befdb320612..53eaad2668771 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_no_csrf.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'form' => [ 'csrf_protection' => [ 'enabled' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/fragments_and_hinclude.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/fragments_and_hinclude.php index dbcf5b786dba9..0f3ee9c194a9f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/fragments_and_hinclude.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/fragments_and_hinclude.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'fragments' => [ 'enabled' => true, 'hinclude_default_template' => 'global_hinclude_template', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index 52903cd0b12a7..fd04b996da496 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -11,6 +11,7 @@ ], ], 'http_method_override' => false, + 'trust_x_sendfile_type_header' => true, 'esi' => [ 'enabled' => true, ], @@ -79,4 +80,7 @@ 'pdf' => 'application/pdf', ], ], + 'html_sanitizer' => [ + 'enabled' => true, + ], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer.php new file mode 100644 index 0000000000000..2d117e8380a45 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer.php @@ -0,0 +1,47 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'html_sanitizer' => [ + 'sanitizers' => [ + 'custom' => [ + 'allow_safe_elements' => true, + 'allow_static_elements' => true, + 'allow_elements' => [ + 'iframe' => 'src', + 'custom-tag' => ['data-attr', 'data-attr-1'], + 'custom-tag-2' => '*', + ], + 'block_elements' => ['section'], + 'drop_elements' => ['video'], + 'allow_attributes' => [ + 'src' => ['iframe'], + 'data-attr' => '*', + ], + 'drop_attributes' => [ + 'data-attr' => ['custom-tag'], + 'data-attr-1' => [], + 'data-attr-2' => '*', + ], + 'force_attributes' => [ + 'a' => ['rel' => 'noopener noreferrer'], + 'h1' => ['class' => 'bp4-heading'], + ], + 'force_https_urls' => true, + 'allowed_link_schemes' => ['http', 'https', 'mailto'], + 'allowed_link_hosts' => ['symfony.com'], + 'allow_relative_links' => true, + 'allowed_media_schemes' => ['http', 'https', 'data'], + 'allowed_media_hosts' => ['symfony.com'], + 'allow_relative_medias' => true, + 'with_attribute_sanitizers' => [ + 'App\\Sanitizer\\CustomAttributeSanitizer', + ], + 'without_attribute_sanitizers' => [ + 'App\\Sanitizer\\OtherCustomAttributeSanitizer', + ], + ], + 'all.sanitizer' => null, + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_allowed_link_and_media_hosts.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_allowed_link_and_media_hosts.php new file mode 100644 index 0000000000000..952c066de0cc2 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_allowed_link_and_media_hosts.php @@ -0,0 +1,10 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'html_sanitizer' => [ + 'sanitizers' => [ + 'custom_default' => null, + ], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_config.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_config.php new file mode 100644 index 0000000000000..ae973a2db6b5c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/html_sanitizer_default_config.php @@ -0,0 +1,5 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'html_sanitizer' => null]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php index 5f71a92847f34..b8f63d8190b84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_default_options.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'max_host_connections' => 4, 'default_options' => null, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php index cf83e31af2f02..865ddd14e1203 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_full_default_options.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'default_options' => [ 'headers' => ['X-powered' => 'PHP'], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_mock_response_factory.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_mock_response_factory.php index 5b64c3ae0a1d4..de2dd604e3f88 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_mock_response_factory.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_mock_response_factory.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'default_options' => null, 'mock_response_factory' => 'my_response_factory', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php index 8ba8dd7b92ec8..c66ce8851b42e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_override_default_options.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'max_host_connections' => 4, 'default_options' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_retry.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_retry.php index f2ab01d1e1196..63914440a7be2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_retry.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_retry.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'default_options' => [ 'retry_failed' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_scoped_without_query_option.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_scoped_without_query_option.php index 0d3dc88472f84..653ca421846ae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_scoped_without_query_option.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_scoped_without_query_option.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'scoped_clients' => [ 'foo' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_xml_key.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_xml_key.php index 64778c61561b6..d613dc05d2fdb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_xml_key.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/http_client_xml_key.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'http_client' => [ 'default_options' => [ 'resolve' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/legacy_translator_enabled_locales.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/legacy_translator_enabled_locales.php index a585c6ee5de6d..46acfce8c144d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/legacy_translator_enabled_locales.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/legacy_translator_enabled_locales.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => 's3cr3t', 'default_locale' => 'fr', 'router' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer.php index 5e3093b33b431..918d837c411f2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'dsn' => 'smtp://example.com', 'envelope' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_disabled_message_bus.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_disabled_message_bus.php index 4f2471ed95802..bea83e8fe66cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_disabled_message_bus.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_disabled_message_bus.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'dsn' => 'smtp://example.com', 'message_bus' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php index df2ca46e46ee9..3d991932e7e64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_dsn.php @@ -4,6 +4,7 @@ return static function (ContainerConfigurator $container) { $container->extension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'dsn' => 'smtp://example.com', 'envelope' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_specific_message_bus.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_specific_message_bus.php index 32b936af9d88e..ba9e9f573b562 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_specific_message_bus.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_specific_message_bus.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'dsn' => 'smtp://example.com', 'message_bus' => 'app.another_bus', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php index 8b13bc269b24a..bc1a7925d8e51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/mailer_with_transports.php @@ -4,6 +4,7 @@ return static function (ContainerConfigurator $container) { $container->extension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'transports' => [ 'transport1' => 'smtp://example1.com', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php index adb8239d04737..dc22cd5ff8917 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'routing' => [ FooMessage::class => ['sender.bar', 'sender.biz'], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_disabled.php index e02542d9778c6..d14d6e94b617e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_disabled.php @@ -1,5 +1,6 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => false, ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_middleware_factory_erroneous_format.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_middleware_factory_erroneous_format.php index cb4ee5e5127b9..6d8e6bbffbb2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_middleware_factory_erroneous_format.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_middleware_factory_erroneous_format.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'buses' => [ 'command_bus' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php index 627e21f3084e9..665c664bfb216 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'default_bus' => 'messenger.bus.commands', 'buses' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php index 8f85259aa6908..30b000f9bb5aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'transports' => [ 'transport_1' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php index 0cff76887b152..3848ee59f7ad1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_failure_transports_global.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'failure_transport' => 'failure_transport_global', 'transports' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing.php index eb459509015dd..77f4d5b93bebc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => true, 'messenger' => [ 'serializer' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_invalid_transport.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_invalid_transport.php index ee77e3a3f2dbf..b552a3ebe5d5b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_invalid_transport.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_invalid_transport.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => true, 'messenger' => [ 'serializer' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_single.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_single.php index e58814589b870..f487a0f8f90d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_single.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_routing_single.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'routing' => [ 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage' => ['amqp'], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport.php index 7baab29dc57ce..34f95dbee6e63 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transport.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => true, 'messenger' => [ 'serializer' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php index 90c5def3ac100..8236fced45021 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => true, 'messenger' => [ 'failure_transport' => 'failed', 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 index dda2e30108b87..3cb006c46750b 100644 --- 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 @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'reset_on_message' => false, 'routing' => [ 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 index 73102d522db57..ee689ae0932db 100644 --- 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 @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'reset_on_message' => true, 'routing' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier.php index 5ffe142be4dfc..f517084713550 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'messenger' => [ 'enabled' => true ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php index 6d51ef98517f4..a1cea02ac86d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_mailer.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php index 454cf5ef7ca81..bc4280b97a551 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_messenger.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'mailer' => [ 'dsn' => 'smtp://example.com', ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php index 9bc87dbee2f58..0d3223198528e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/notifier_without_transports.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'notifier' => [ 'enabled' => true, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_disabled.php index cff0582bf3b3d..0e552a97853d2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'php_errors' => [ 'log' => false, 'throw' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_enabled.php index 9afa5d1c02266..f26bf7da296e0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_enabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_enabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'php_errors' => [ 'log' => true, 'throw' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_level.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_level.php index 87fdd64d0b6fe..997ea4c393108 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_level.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_level.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'php_errors' => [ 'log' => 8, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_levels.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_levels.php index 620a5871e098f..72f4685af1ce8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_levels.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/php_errors_log_levels.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'php_errors' => [ 'log' => [ \E_NOTICE => \Psr\Log\LogLevel::ERROR, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php index 552c95e137bb3..6cf9ee4a671c4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler.php @@ -1,7 +1,11 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'profiler' => [ 'enabled' => true, ], + 'serializer' => [ + 'enabled' => true + ], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php new file mode 100644 index 0000000000000..e870073299c59 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/profiler_collect_serializer_data.php @@ -0,0 +1,12 @@ +loadFromExtension('framework', [ + 'http_method_override' => false, + 'profiler' => [ + 'enabled' => true, + 'collect_serializer_data' => true, + ], + 'serializer' => [ + 'enabled' => true, + ] +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php index dc6954fe89da4..cce084b77fa6e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'property_access' => [ 'magic_call' => true, 'magic_get' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_info.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_info.php index bff8d41158582..bbf4b58b4ec57 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_info.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_info.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'property_info' => [ 'enabled' => true, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/request.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/request.php index d69d7512ad995..2a1a9d10d7461 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/request.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/request.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'request' => [ 'formats' => [], ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php index 937a07c2255cd..d8ec0560a8c2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php index de3381c21e3a1..f40405e7a011f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => [ 'enabled' => true, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_legacy_cache.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_legacy_cache.php index 9636b1d6613aa..6695d9f7988ba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_legacy_cache.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_legacy_cache.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'serializer' => [ 'enabled' => true, 'cache' => 'foo', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php index 2f6f48e95888d..d68a9f76f7699 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'annotations' => ['enabled' => true], 'serializer' => [ 'enable_annotations' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session.php index 8b4c6e6e4c3b1..1f2556a5cfcbe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'session' => [ 'storage_factory_id' => 'session.storage.factory.native', 'handler_id' => null, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session_cookie_secure_auto.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session_cookie_secure_auto.php index b52935c726a0f..b07b6f8b2f1a2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session_cookie_secure_auto.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/session_cookie_secure_auto.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'session' => [ 'storage_factory_id' => 'session.storage.factory.native', 'handler_id' => null, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php index 32e1bf0c554da..f1c56a38cd581 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'ssi' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php index 6f2568ffd511e..92383e5a9bd11 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'translator' => [ 'cache_dir' => null, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_fallbacks.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_fallbacks.php index 592a61de65a7f..0989890ee454a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_fallbacks.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_fallbacks.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'translator' => [ 'fallbacks' => ['en', 'fr'], ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_annotations.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_annotations.php index 933410dfee767..cb2bf7f3f597e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_annotations.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_annotations.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => 's3cr3t', 'validation' => [ 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_auto_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_auto_mapping.php index e15762d6d8a13..4d879f6c5d884 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_auto_mapping.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_auto_mapping.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'property_info' => ['enabled' => true], 'validation' => [ 'auto_mapping' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_email_validation_mode.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_email_validation_mode.php index 5100e01e12bb4..75a12bbd98afd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_email_validation_mode.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_email_validation_mode.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'validation' => [ 'email_validation_mode' => 'html5', ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php index f8b19e34801c9..6be94689035db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_mapping.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'validation' => [ 'mapping' => [ 'paths' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_multiple_static_methods.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_multiple_static_methods.php index ad2bd817a208f..475bb595a818c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_multiple_static_methods.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_multiple_static_methods.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => 's3cr3t', 'validation' => [ 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_no_static_method.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_no_static_method.php index a9d98e17c68db..8adb5c26b8b6c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_no_static_method.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_no_static_method.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => 's3cr3t', 'validation' => [ 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_translation_domain.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_translation_domain.php index 42ea0713030a3..104dbbace0c87 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_translation_domain.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/validation_translation_domain.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'validation' => [ 'translation_domain' => 'messages', ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php index 44d52e402d8b8..5b022da2067dc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/web_link.php @@ -1,5 +1,6 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'web_link' => ['enabled' => true], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_not_valid.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_not_valid.php index 5d6ed54d6739f..efb5767a3b535 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_not_valid.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_not_valid.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'my_workflow' => [ 'type' => 'state_machine', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_guard_expression.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_guard_expression.php index 2037b5f904f69..37a1d7ac73007 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_guard_expression.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_guard_expression.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'article' => [ 'type' => 'workflow', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php index 35a9df3730b2a..2ba2b3491c705 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_multiple_transitions_with_same_name.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'article' => [ 'type' => 'workflow', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php index e4eefd4c28440..81fe174b1b2a3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_no_events_to_dispatch.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'my_workflow' => [ 'type' => 'state_machine', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php index 0fc5c29c8b43e..1c434cd99c4ee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_specified_events_to_dispatch.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'my_workflow' => [ 'type' => 'state_machine', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php index 063755b130d34..120bb364722dc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_with_support_and_support_strategy.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'my_workflow' => [ 'type' => 'workflow', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php index 5eef5cc4d0827..641455eb36b3f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflow_without_support_and_support_strategy.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'my_workflow' => [ 'type' => 'workflow', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php index 995fabffe38b7..5cdb2563ac2b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php @@ -3,6 +3,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest; $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'article' => [ 'type' => 'workflow', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php index eb17731940973..9f2fabe3e57ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php @@ -1,5 +1,6 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => null, ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled.php index f048de1ceb5ad..ad71b2729853f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'enabled' => true, 'foo' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled_named_workflows.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled_named_workflows.php index f79a2d10e97f9..49ab48914e1ba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled_named_workflows.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_explicitly_enabled_named_workflows.php @@ -1,6 +1,7 @@ loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'enabled' => true, 'workflows' => [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml index dadee4529d8b5..bb4b62ee6a0c7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + http://cdn.example.com diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_disabled.xml index 3c1303144b515..cd53b664d4417 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_disabled.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_version_strategy_as_service.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_version_strategy_as_service.xml index 7bc70332bcc98..0a7e6bc3ff3b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_version_strategy_as_service.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets_version_strategy_as_service.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + http://cdn.example.com diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml index 7c75178c8cf0a..a0ae5219ba9a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware.xml index 2929e87e200e8..630c2385c597d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + cache.adapter.redis_tag_aware diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware_pool.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware_pool.xml index 65c06a1da6df7..40ce365c5bda9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware_pool.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/cache_app_redis_tag_aware_pool.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + cache.redis_tag_aware.foo diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf.xml index 24acb3e32707c..97104d0571e52 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_disabled.xml index 63a26d3843970..7f9ff7fb92505 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_disabled.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_needs_session.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_needs_session.xml index a9e168638df31..013435d6b6baa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_needs_session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/csrf_needs_session.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/default_config.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/default_config.xml index d98c43d992d8e..efbd656c0a13d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/default_config.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/default_config.xml @@ -5,5 +5,5 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml index 5fe9be69b7cba..70dd10405580a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml index d4a46b62fcfb9..961882a6a58d5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions.xml index cc73b8de3ced6..4a877c1eb3499 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions.xml @@ -5,9 +5,26 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - - - - + + + + + + + + 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 new file mode 100644 index 0000000000000..2e6048fa7c7aa --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/exceptions_legacy.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml new file mode 100644 index 0000000000000..5ebe1c4332966 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_disabled.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml index 30fcf6b7f3929..55616c2d6a7ad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml index 1e89bca965ea2..cf88a085adc5e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_default_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_default_csrf.xml index 9ed40084722b8..c2700a6b20a76 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_default_csrf.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_default_csrf.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml index 3af5322be212f..afb1869c5ab5d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_no_csrf.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/fragments_and_hinclude.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/fragments_and_hinclude.xml index fb007313b9a71..2031cac377cb1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/fragments_and_hinclude.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/fragments_and_hinclude.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 2e115a5aebbc0..00da2a6c0f963 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + fr en diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer.xml new file mode 100644 index 0000000000000..771652c8d1a28 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer.xml @@ -0,0 +1,63 @@ + + + + + + + + + src + + + data-attr + data-attr-1 + + + * + + section + video + + iframe + + + * + + + custom-tag + + + + * + + + noopener noreferrer + + + bp4-heading + + http + https + mailto + symfony.com + http + https + data + symfony.com + App\Sanitizer\CustomAttributeSanitizer + App\Sanitizer\OtherCustomAttributeSanitizer + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_allowed_link_and_media_hosts.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_allowed_link_and_media_hosts.xml new file mode 100644 index 0000000000000..fff1592d37e0a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_allowed_link_and_media_hosts.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_config.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_config.xml new file mode 100644 index 0000000000000..fcc232a739302 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/html_sanitizer_default_config.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml index c00eb314415b9..9674ceaf21649 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_default_options.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml index 8dd84123ca4b5..fdee9a9132a35 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_override_default_options.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + bar diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_retry.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_retry.xml index eb7798914488b..248fd81801e2d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_retry.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/http_client_retry.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + - + - + 127.0.0.1 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml index d531fbaba218f..d16fa7e5bf7fa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml index 72e583a902395..b44dd675ffdce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml @@ -10,7 +10,7 @@ redis://paas.com - + semaphore flock diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_disabled_message_bus.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_disabled_message_bus.xml index e6d3a47e38a93..cac6ba833daa6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_disabled_message_bus.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_disabled_message_bus.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml index be53f59bc3cad..fc4f9861e98eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_dsn.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + sender@example.org diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_specific_message_bus.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_specific_message_bus.xml index 116ba032a03a3..ee541be7f94b3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_specific_message_bus.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_specific_message_bus.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml index cbe538d33e99c..71cd4c118a1f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/mailer_with_transports.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + smtp://example1.com smtp://example2.com diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger.xml index bacd772dcb6fc..fef09b934a3aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_disabled.xml index 6f57398b30d2b..513842ece8392 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_disabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml index 1642e57988505..a8f515e7166bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports.xml index b8e9f19759429..bad9fb16fb67c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports_global.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports_global.xml index c6e5c530fda1b..096c26f4628ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports_global.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_failure_transports_global.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing.xml index 0b022e78a0c8c..30b249b415c31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_invalid_transport.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_invalid_transport.xml index 98c487fbf8bfa..cbff44e09f593 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_invalid_transport.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_invalid_transport.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_single.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_single.xml index 349a3728d3935..972f5201fb382 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_single.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_routing_single.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport.xml index e5e60a39823a6..f2e7cfc6c49b8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transport.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml index b0510d580ceaf..d78c802810ae6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + 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 index 67a2a414e8fcf..c0bc33bcde151 100644 --- 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 @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + 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 index 1451bb66f516d..4c208aad2f0b2 100644 --- 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 @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier.xml index 47e2e2b0c1b13..8c675c4603786 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_mailer.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_mailer.xml index 1c62b5265b897..a93064b21384c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_mailer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_mailer.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_messenger.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_messenger.xml index c2a5134762588..7d65d064e9947 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_messenger.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_messenger.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_transports.xml index a1ec7863cda1a..ee6653c3449e0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/notifier_without_transports.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_disabled.xml index cb50daa65e883..62d677a54e74f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_disabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_enabled.xml index db6a8a9bf03c0..a57c4e6c6843e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_enabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_enabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_level.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_level.xml index ebd7948452b7f..608842c27b483 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_level.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_level.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_levels.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_levels.xml index 1b6642a575c4c..004a6d3284228 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_levels.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/php_errors_log_levels.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler.xml index a5f5448e18f2d..6a46cbc3dbda7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler.xml @@ -6,7 +6,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler_collect_serializer_data.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler_collect_serializer_data.xml new file mode 100644 index 0000000000000..e17589222d814 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/profiler_collect_serializer_data.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml index 9406919e92394..aacbb7531a16f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_info.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_info.xml index 7bf63b6540c54..112635383e6a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_info.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_info.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/request.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/request.xml index f1e8184c149d1..0bcabe2697267 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/request.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/request.xml @@ -5,7 +5,7 @@ xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore.xml new file mode 100644 index 0000000000000..be7264689f3dc --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/semaphore.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml index 0c62272c51003..b5d55599e0e1e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml index 3d59d62833ea4..a0b95b01e1e6a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_legacy_cache.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_legacy_cache.xml index b76ceb86b714a..9296670bb1657 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_legacy_cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_legacy_cache.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml index 1ae06c85e13c1..988abf90e0586 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session.xml index e91d51955e6fa..338404bc8688c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session_cookie_secure_auto.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session_cookie_secure_auto.xml index 3023c43fc13ad..7b9408e897886 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session_cookie_secure_auto.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/session_cookie_secure_auto.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml index 6aa752a4695d5..054f191f1ea15 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml index 5704ff7cd7ddb..229a722860242 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_fallbacks.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_fallbacks.xml index 521f8e381512d..d6b09f34ee461 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_fallbacks.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_fallbacks.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + en fr diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_annotations.xml index 2324b9ca6e374..42bcdc3f47d9e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_annotations.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_auto_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_auto_mapping.xml index a05aaf8016a56..71109f8e44ae2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_auto_mapping.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_auto_mapping.xml @@ -3,7 +3,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_email_validation_mode.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_email_validation_mode.xml index 7274d815894d7..961b9adba4531 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_email_validation_mode.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_email_validation_mode.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml index 8d74ebb2118f9..ad70508b6bfdc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_mapping.xml @@ -4,7 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony"> - + %kernel.project_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_multiple_static_methods.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_multiple_static_methods.xml index c2e84c3b906c7..abd9ba9b740fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_multiple_static_methods.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_multiple_static_methods.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + loadFoo loadBar diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_no_static_method.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_no_static_method.xml index 61770d88a7fa6..7554cd16f281c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_no_static_method.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_no_static_method.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_translation_domain.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_translation_domain.xml index 3690f9e10eda4..05ad899763c38 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_translation_domain.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/validation_translation_domain.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml index 718ceb31a372c..9c617ccbdea9a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/web_link.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_not_valid.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_not_valid.xml index df299c89deb50..12bc1b463b68d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_not_valid.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_not_valid.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_guard_expression.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_guard_expression.xml index ffc12c4d0d420..1a953f96352e6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_guard_expression.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_guard_expression.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + draft Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml index db79f9323c47e..3bf4657eccac3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_multiple_transitions_with_same_name.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + draft Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml index 2f563da4bf96b..4fc6a02341fd1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_no_events_to_dispatch.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + one diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml index d442828f8cfbf..48091a9b01184 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_specified_events_to_dispatch.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + one diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml index 54a346ebda198..139259826af2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_with_support_and_support_strategy.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml index c6ee7d77b5c6a..b40b24707a876 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflow_without_support_and_support_strategy.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml index 79361af57a61f..5e9f1d1bff700 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + draft diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml index 26e622e9e0074..a5567a8101d0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled.xml index af93d44e18387..a3d7f8bfa623b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest bar diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled_named_workflows.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled_named_workflows.xml index 41fd29a1f27d9..3569297c45784 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled_named_workflows.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_explicitly_enabled_named_workflows.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> - + bar Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml index cfd4f07b04346..2c1450de8cc75 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false assets: version: SomeVersionScheme version_format: '%%s?version=%%s' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_disabled.yml index 17ba4e90afb75..baa169f48ce72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false assets: enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_version_strategy_as_service.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_version_strategy_as_service.yml index 2528462f83cb5..cdfc43ca648eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_version_strategy_as_service.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets_version_strategy_as_service.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false assets: version_strategy: assets.custom_version_strategy base_urls: http://cdn.example.com diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml index c89c027f5aecf..b886dcd1b3ce9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false cache: pools: cache.foo: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware.yml index b1c89adafa0ca..11204defe4d32 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false cache: app: cache.adapter.redis_tag_aware diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware_pool.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware_pool.yml index 9eb8b83c775c5..42717b2aa51b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware_pool.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/cache_app_redis_tag_aware_pool.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false cache: app: cache.redis_tag_aware.foo pools: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf.yml index 643e7bda4554a..71f6a34e22d2d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: s3cr3t csrf_protection: ~ session: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf_needs_session.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf_needs_session.yml index b8065b6fb678b..8fb542365010b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf_needs_session.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/csrf_needs_session.yml @@ -1,2 +1,3 @@ framework: + http_method_override: false csrf_protection: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/default_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/default_config.yml index 00874fbe8d11d..26f9bb5a672a6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/default_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/default_config.yml @@ -1 +1,2 @@ -framework: ~ +framework: + http_method_override: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml index 49d63c8d60a15..a1140cc31c044 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false fragments: enabled: false esi: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml index 2a78e6da0e725..9e9a03f072ff2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false esi: enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/exceptions.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/exceptions.yml index 82fab4e04a9f9..88e3b0da04d5a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/exceptions.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/exceptions.yml @@ -1,5 +1,15 @@ framework: + http_method_override: false exceptions: Symfony\Component\HttpKernel\Exception\BadRequestHttpException: log_level: info status_code: 422 + Symfony\Component\HttpKernel\Exception\NotFoundHttpException: + log_level: info + status_code: null + Symfony\Component\HttpKernel\Exception\ConflictHttpException: + log_level: info + status_code: 0 + Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException: + log_level: null + status_code: 500 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml new file mode 100644 index 0000000000000..0b7fa0199b7bd --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_disabled.yml @@ -0,0 +1,5 @@ +framework: + csrf_protection: false + form: + csrf_protection: true + http_method_override: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_default_csrf.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_default_csrf.yml index 5036cc8577735..d6e9d77b93678 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_default_csrf.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_default_csrf.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false form: legacy_error_messages: false session: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml index e3ac7e8daf42d..7f1d94ad2040e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_no_csrf.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false form: csrf_protection: enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/fragments_and_hinclude.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/fragments_and_hinclude.yml index b03f37da7946e..92dc6fe7771c2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/fragments_and_hinclude.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/fragments_and_hinclude.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false fragments: enabled: true hinclude_default_template: global_hinclude_template diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 6da130bbec556..67b10bb5f833e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -7,6 +7,7 @@ framework: csrf_protection: field_name: _csrf http_method_override: false + trust_x_sendfile_type_header: true esi: enabled: true ssi: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer.yml new file mode 100644 index 0000000000000..007f4875b6f79 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer.yml @@ -0,0 +1,40 @@ +framework: + http_method_override: false + html_sanitizer: + sanitizers: + custom: + allow_safe_elements: true + allow_static_elements: true + allow_elements: + iframe: 'src' + custom-tag: ['data-attr', 'data-attr-1'] + custom-tag-2: '*' + block_elements: + - section + drop_elements: + - video + allow_attributes: + src: ['iframe'] + data-attr: '*' + drop_attributes: + data-attr: [custom-tag] + data-attr-1: [] + data-attr-2: '*' + force_attributes: + a: + rel: noopener noreferrer + h1: + class: bp4-heading + force_https_urls: true + allowed_link_schemes: ['http', 'https', 'mailto'] + allowed_link_hosts: ['symfony.com'] + allow_relative_links: true + allowed_media_schemes: ['http', 'https', 'data'] + allowed_media_hosts: ['symfony.com'] + allow_relative_medias: true + with_attribute_sanitizers: + - App\Sanitizer\CustomAttributeSanitizer + without_attribute_sanitizers: + - App\Sanitizer\OtherCustomAttributeSanitizer + + all.sanitizer: null diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_allowed_link_and_media_hosts.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_allowed_link_and_media_hosts.yml new file mode 100644 index 0000000000000..5c9ac2b475593 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_allowed_link_and_media_hosts.yml @@ -0,0 +1,5 @@ +framework: + http_method_override: false + html_sanitizer: + sanitizers: + custom_default: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_config.yml new file mode 100644 index 0000000000000..94fff31d66886 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/html_sanitizer_default_config.yml @@ -0,0 +1,3 @@ +framework: + http_method_override: false + html_sanitizer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml index 6828f8ec231fb..4bc3637624fb2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_default_options.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: max_host_connections: 4 default_options: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml index ba3aa46259b46..de9300e17f158 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_full_default_options.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: default_options: headers: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_mock_response_factory.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_mock_response_factory.yml index b958591084136..a90016a026e0e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_mock_response_factory.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_mock_response_factory.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: default_options: ~ mock_response_factory: my_response_factory diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml index 1528a313d64e3..14a6915380dba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_override_default_options.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: max_host_connections: 4 default_options: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_retry.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_retry.yml index eba686819c300..9f02eb5bce2bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_retry.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_retry.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: default_options: retry_failed: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_scoped_without_query_option.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_scoped_without_query_option.yml index ecfc9d41fd4c3..8da495f14e634 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_scoped_without_query_option.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_scoped_without_query_option.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: scoped_clients: foo: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_xml_key.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_xml_key.yml index dc87555a901ae..51ac6c30a1acd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_xml_key.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/http_client_xml_key.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false http_client: default_options: resolve: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml index 70f578a143a56..3ca4a46ab8639 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml @@ -1,2 +1,3 @@ framework: + http_method_override: false lock: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml index 6d0cb5ca638bd..02ffcf5b71c58 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml @@ -2,6 +2,7 @@ parameters: env(REDIS_DSN): redis://paas.com framework: + http_method_override: false lock: foo: semaphore bar: flock diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_disabled_message_bus.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_disabled_message_bus.yml index f941f7c8c4f6b..180be920d08c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_disabled_message_bus.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_disabled_message_bus.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: dsn: 'smtp://example.com' message_bus: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml index f8b3c87c4302c..8677cc5ece83d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_dsn.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: dsn: 'smtp://example.com' envelope: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_specific_message_bus.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_specific_message_bus.yml index ddfc7a479a49d..bc227c96cf796 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_specific_message_bus.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_specific_message_bus.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: dsn: 'smtp://example.com' message_bus: app.another_bus diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml index bc4657d3a4397..6486fdeeedf1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/mailer_with_transports.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: transports: transport1: 'smtp://example1.com' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml index 82fea3b27af23..29174a9b407f2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: routing: 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage': ['sender.bar', 'sender.biz'] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_disabled.yml index 1b2d2d1a4f475..8bbd594e3839b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_disabled.yml @@ -1,2 +1,3 @@ framework: + http_method_override: false messenger: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_middleware_factory_erroneous_format.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_middleware_factory_erroneous_format.yml index 74431414ba99c..fcafe4b57b97c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_middleware_factory_erroneous_format.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_middleware_factory_erroneous_format.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: buses: command_bus: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml index 0e67039733272..0699ecfaed0a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: default_bus: messenger.bus.commands buses: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports.yml index 863f18a7d1a1f..04e6d1f24e200 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: transports: transport_1: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports_global.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports_global.yml index 10023edb0b9fd..bac747b7a1b58 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports_global.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_failure_transports_global.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: failure_transport: failure_transport_global transports: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing.yml index 0e493eb882a02..bfd682c706fbe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false serializer: true messenger: serializer: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_invalid_transport.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_invalid_transport.yml index 3bf0f2ddf9c03..3b01d3d3bca35 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_invalid_transport.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_invalid_transport.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false serializer: true messenger: serializer: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_single.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_single.yml index caa88641887c7..73544ddda6e49 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_single.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_routing_single.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: routing: 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage': [amqp] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport.yml index b51feb73bce95..cc7e613b28896 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transport.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false serializer: true messenger: serializer: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml index d00f4a65dd37c..b16f9b6a8f09d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false serializer: true messenger: failure_transport: failed diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_disabled_reset_on_message.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_disabled_reset_on_message.yml index f67395c85c191..37e1e90b530df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_disabled_reset_on_message.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_disabled_reset_on_message.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: reset_on_message: false routing: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_explict_reset_on_message_legacy.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_explict_reset_on_message_legacy.yml index 3bf374f474c75..17b779a254fe9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_explict_reset_on_message_legacy.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_with_explict_reset_on_message_legacy.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: reset_on_message: true routing: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier.yml index 586cb98a4a138..da8e3fa7a46d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false messenger: enabled: true mailer: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_mailer.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_mailer.yml index 75fa3cf889825..57febaaeb3109 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_mailer.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_mailer.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: enabled: false messenger: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_messenger.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_messenger.yml index 93d1f0aa190a7..9ff92d0ac74af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_messenger.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_messenger.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false mailer: dsn: 'smtp://example.com' messenger: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_transports.yml index 856b0cd7c7a0e..081b7af9f12ff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_transports.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/notifier_without_transports.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false notifier: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_disabled.yml index 958f75638ab75..c0091d3c480f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false php_errors: throw: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_enabled.yml index f48531014e4fb..9080d5cccca3b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_enabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_enabled.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false php_errors: log: true throw: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_level.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_level.yml index e5cff7767dbe4..0cc44c7e8d1d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_level.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_level.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false php_errors: log: 8 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_levels.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_levels.yml index ad9fd30667de2..c8b4f7e5ebec0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_levels.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/php_errors_log_levels.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false php_errors: log: !php/const \E_NOTICE: !php/const Psr\Log\LogLevel::ERROR diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml index 9052a2bdfb0c8..190e82dae5b71 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler.yml @@ -1,3 +1,6 @@ framework: + http_method_override: false profiler: enabled: true + serializer: + enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler_collect_serializer_data.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler_collect_serializer_data.yml new file mode 100644 index 0000000000000..ad397fb99ee0c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/profiler_collect_serializer_data.yml @@ -0,0 +1,7 @@ +framework: + http_method_override: false + serializer: + enabled: true + profiler: + enabled: true + collect_serializer_data: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml index 931b50383f210..5e83cd44be75d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false property_access: magic_call: true magic_get: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_info.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_info.yml index fbdf7a7b0d715..60b9cb920975e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_info.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_info.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false property_info: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/request.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/request.yml index 9beae1dc59755..3e57df27cfa42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/request.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/request.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false request: formats: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore.yml new file mode 100644 index 0000000000000..fe53f99d2e15e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore.yml @@ -0,0 +1,3 @@ +framework: + http_method_override: false + semaphore: redis://localhost diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore_named.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore_named.yml new file mode 100644 index 0000000000000..e1b9d1b69a229 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/semaphore_named.yml @@ -0,0 +1,8 @@ +parameters: + env(REDIS_DSN): redis://paas.com + +framework: + http_method_override: false + semaphore: + foo: redis://paas.com + qux: "%env(REDIS_DSN)%" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml index 330e19a6976e7..2e9cd798dfad9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false serializer: enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml index 40a1ff7d65b3b..47e8c356c7edd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false serializer: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_legacy_cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_legacy_cache.yml index 5fadc886ab1bc..5fd44373fcdda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_legacy_cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_legacy_cache.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false serializer: enabled: true cache: foo diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml index 77c9d517a33b0..3291dc2a47777 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false annotations: enabled: true serializer: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session.yml index eb0df8d01c76c..51a14623654be 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false session: storage_factory_id: session.storage.factory.native handler_id: null diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session_cookie_secure_auto.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session_cookie_secure_auto.yml index 739b49b1e6ab9..d89a8f7aa1093 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session_cookie_secure_auto.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/session_cookie_secure_auto.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false session: storage_factory_id: session.storage.factory.native handler_id: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml index 3a8a820c71438..f3c359f7b95bb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false ssi: enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml index 6ad1c7330f965..a6745633e011a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false translator: cache_dir: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_fallbacks.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_fallbacks.yml index 271d781184755..5534797b5b96c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_fallbacks.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_fallbacks.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false translator: fallbacks: [en, fr] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_annotations.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_annotations.yml index 97b433f8cfb08..8595a0f533cd0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_annotations.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_annotations.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: s3cr3t validation: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_auto_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_auto_mapping.yml index 2564a8d243ef8..6a25af86ce34b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_auto_mapping.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_auto_mapping.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false property_info: { enabled: true } validation: auto_mapping: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_email_validation_mode.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_email_validation_mode.yml index a695e1a62a7d7..e8aebd9976fd1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_email_validation_mode.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_email_validation_mode.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false validation: email_validation_mode: html5 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml index f05e33bb6c134..5b9859a3a284b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_mapping.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false validation: mapping: paths: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_multiple_static_methods.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_multiple_static_methods.yml index 6ca343351328a..350ef4472612e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_multiple_static_methods.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_multiple_static_methods.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: s3cr3t validation: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_no_static_method.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_no_static_method.yml index ca5214964259e..5c4d765ce0360 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_no_static_method.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_no_static_method.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: s3cr3t validation: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_translation_domain.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_translation_domain.yml index 167b5fcce85b1..c8b39054a2c81 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_translation_domain.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/validation_translation_domain.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false validation: translation_domain: messages diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml index 4276aacbe21c1..4cb63387696b8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/web_link.yml @@ -1,3 +1,4 @@ framework: + http_method_override: false web_link: enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_not_valid.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_not_valid.yml index 123505de9754f..29eeb8e9ad18d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_not_valid.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_not_valid.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: my_workflow: type: state_machine diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_guard_expression.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_guard_expression.yml index 80a85a307b738..6855c013053b2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_guard_expression.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_guard_expression.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: article: type: workflow diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml index 12df7b79e7c4f..384bd47170bfa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_multiple_transitions_with_same_name.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: article: type: workflow diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml index e0a281f27db46..c511543df056d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_no_events_to_dispatch.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: my_workflow: type: state_machine diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml index d5ff3d5e5fe0d..703195b557664 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_specified_events_to_dispatch.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: my_workflow: type: state_machine diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml index de0b36d8fa491..a57bc555b6fb7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_with_support_and_support_strategy.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: my_workflow: type: workflow diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml index de74adbe59b20..9ba3c88399cb7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflow_without_support_and_support_strategy.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: my_workflow: type: workflow diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml index e4ac9c01890e3..ff1b926b09997 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: article: type: workflow diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml index 2a716ff0a1b14..4c5f97f0b2a0d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml @@ -1,2 +1,3 @@ framework: + http_method_override: false workflows: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled.yml index bbecf4bfc420e..1ee334125e3d1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: enabled: true workflows: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled_named_workflows.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled_named_workflows.yml index 786e3bcad292e..0dcfc93a1c209 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled_named_workflows.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_explicitly_enabled_named_workflows.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false workflows: enabled: true workflows: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index ccd35edd68d08..6297172706661 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -14,6 +14,7 @@ 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\Tests\Fixtures\Messenger\DummyMessage; @@ -36,6 +37,7 @@ use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; +use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; @@ -46,12 +48,17 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Finder\Finder; use Symfony\Component\Form\Form; +use Symfony\Component\HtmlSanitizer\HtmlSanitizer; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig; +use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Component\HttpClient\ScopingHttpClient; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; use Symfony\Component\Messenger\Transport\TransportFactory; +use Symfony\Component\Notifier\ChatterInterface; +use Symfony\Component\Notifier\TexterInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; @@ -65,8 +72,8 @@ use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\DependencyInjection\TranslatorPass; +use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; -use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow; @@ -78,6 +85,8 @@ abstract class FrameworkExtensionTest extends TestCase { + use ExpectDeprecationTrait; + private static $containerCache = []; abstract protected function loadFromFile(ContainerBuilder $container, $file); @@ -94,6 +103,14 @@ public function testFormCsrfProtection() $this->assertEquals('%form.type_extension.csrf.field_name%', $def->getArgument(2)); } + public function testFormCsrfProtectionWithCsrfDisabled() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('To use form CSRF protection, "framework.csrf_protection" must be enabled.'); + + $this->createContainerFromFile('form_csrf_disabled'); + } + public function testPropertyAccessWithDefaultValue() { $container = $this->createContainerFromFile('full'); @@ -174,6 +191,13 @@ public function testHttpMethodOverride() $this->assertFalse($container->getParameter('kernel.http_method_override')); } + public function testTrustXSendfileTypeHeader() + { + $container = $this->createContainerFromFile('full'); + + $this->assertTrue($container->getParameter('kernel.trust_x_sendfile_type_header')); + } + public function testEsi() { $container = $this->createContainerFromFile('full'); @@ -240,6 +264,24 @@ public function testDisabledProfiler() $this->assertFalse($container->hasDefinition('data_collector.config'), '->registerProfilerConfiguration() does not load collectors.xml'); } + public function testProfilerCollectSerializerDataEnabled() + { + $container = $this->createContainerFromFile('profiler_collect_serializer_data'); + + $this->assertTrue($container->hasDefinition('profiler')); + $this->assertTrue($container->hasDefinition('serializer.data_collector')); + $this->assertTrue($container->hasDefinition('debug.serializer')); + } + + public function testProfilerCollectSerializerDataDefaultDisabled() + { + $container = $this->createContainerFromFile('profiler'); + + $this->assertTrue($container->hasDefinition('profiler')); + $this->assertFalse($container->hasDefinition('serializer.data_collector')); + $this->assertFalse($container->hasDefinition('debug.serializer')); + } + public function testWorkflows() { $container = $this->createContainerFromFile('workflows'); @@ -534,12 +576,34 @@ public function testExceptionsConfig() { $container = $this->createContainerFromFile('exceptions'); + $configuration = $container->getDefinition('exception_listener')->getArgument(3); + $this->assertSame([ - \Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class => [ - 'log_level' => 'info', - 'status_code' => 422, - ], - ], $container->getDefinition('exception_listener')->getArgument(3)); + \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 testRouter() @@ -560,7 +624,7 @@ public function testRouterRequiresResourceOption() $this->expectException(InvalidConfigurationException::class); $container = $this->createContainer(); $loader = new FrameworkExtension(); - $loader->load([['router' => true]], $container); + $loader->load([['http_method_override' => false, 'router' => true]], $container); } public function testSession() @@ -709,6 +773,26 @@ 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'); @@ -969,6 +1053,17 @@ public function testMessengerInvalidTransportRouting() $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'); @@ -1111,7 +1206,7 @@ public function testAnnotations() public function testFileLinkFormat() { - if (ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) { + if (\ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) { $this->markTestSkipped('A custom file_link_format is defined.'); } @@ -1253,10 +1348,6 @@ public function testValidationMapping() public function testValidationAutoMapping() { - if (!class_exists(PropertyInfoLoader::class)) { - $this->markTestSkipped('Auto-mapping requires symfony/validation 4.2+'); - } - $container = $this->createContainerFromFile('validation_auto_mapping'); $parameter = [ 'App\\' => ['services' => ['foo', 'bar']], @@ -1380,7 +1471,7 @@ public function testJsonSerializableNormalizerRegistered() $tag = $definition->getTag('serializer.normalizer'); $this->assertEquals(JsonSerializableNormalizer::class, $definition->getClass()); - $this->assertEquals(-900, $tag[0]['priority']); + $this->assertEquals(-950, $tag[0]['priority']); } public function testObjectNormalizerRegistered() @@ -1681,11 +1772,11 @@ public function testCachePoolInvalidateTagsCommandRegistered() public function testRemovesResourceCheckerConfigCacheFactoryArgumentOnlyIfNoDebug() { $container = $this->createContainer(['kernel.debug' => true]); - (new FrameworkExtension())->load([], $container); + (new FrameworkExtension())->load([['http_method_override' => false]], $container); $this->assertCount(1, $container->getDefinition('config_cache_factory')->getArguments()); $container = $this->createContainer(['kernel.debug' => false]); - (new FrameworkExtension())->load([], $container); + (new FrameworkExtension())->load([['http_method_override' => false]], $container); $this->assertEmpty($container->getDefinition('config_cache_factory')->getArguments()); } @@ -1716,21 +1807,21 @@ public function testSessionCookieSecureAuto() public function testRobotsTagListenerIsRegisteredInDebugMode() { $container = $this->createContainer(['kernel.debug' => true]); - (new FrameworkExtension())->load([], $container); + (new FrameworkExtension())->load([['http_method_override' => false]], $container); $this->assertTrue($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should be registered'); $definition = $container->getDefinition('disallow_search_engine_index_response_listener'); $this->assertTrue($definition->hasTag('kernel.event_subscriber'), 'DisallowRobotsIndexingListener should have the correct tag'); $container = $this->createContainer(['kernel.debug' => true]); - (new FrameworkExtension())->load([['disallow_search_engine_index' => false]], $container); + (new FrameworkExtension())->load([['http_method_override' => false, 'disallow_search_engine_index' => false]], $container); $this->assertFalse( $container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should not be registered when explicitly disabled' ); $container = $this->createContainer(['kernel.debug' => false]); - (new FrameworkExtension())->load([], $container); + (new FrameworkExtension())->load([['http_method_override' => false]], $container); $this->assertFalse($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should NOT be registered'); } @@ -1907,6 +1998,8 @@ public function testRegisterParameterCollectingBehaviorDescribingTags() $this->assertTrue($container->hasParameter('container.behavior_describing_tags')); $this->assertEquals([ + 'annotations.cached_reader', + 'container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'kernel.event_subscriber', @@ -1950,7 +2043,9 @@ public function testNotifierWithoutTransports() $this->assertTrue($container->hasDefinition('notifier')); $this->assertFalse($container->hasDefinition('chatter')); + $this->assertFalse($container->hasAlias(ChatterInterface::class)); $this->assertFalse($container->hasDefinition('texter')); + $this->assertFalse($container->hasAlias(TexterInterface::class)); } public function testIfNotifierTransportsAreKnownByFrameworkExtension() @@ -1967,6 +2062,126 @@ public function testIfNotifierTransportsAreKnownByFrameworkExtension() } } + public function testLocaleSwitcherServiceRegistered() + { + if (!class_exists(LocaleSwitcher::class)) { + $this->markTestSkipped('LocaleSwitcher not available.'); + } + + $container = $this->createContainerFromFile('full', compile: false); + $container->addCompilerPass(new ResolveTaggedIteratorArgumentPass()); + $container->compile(); + + $this->assertTrue($container->has('translation.locale_switcher')); + + $switcherDef = $container->getDefinition('translation.locale_switcher'); + + $this->assertSame('%kernel.default_locale%', $switcherDef->getArgument(0)); + $this->assertInstanceOf(TaggedIteratorArgument::class, $switcherDef->getArgument(1)); + $this->assertSame('kernel.locale_aware', $switcherDef->getArgument(1)->getTag()); + $this->assertEquals(new Reference('router.request_context', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $switcherDef->getArgument(2)); + + $localeAwareServices = array_map(fn (Reference $r) => (string) $r, $switcherDef->getArgument(1)->getValues()); + + $this->assertNotContains('translation.locale_switcher', $localeAwareServices); + } + + public function testHtmlSanitizer() + { + $container = $this->createContainerFromFile('html_sanitizer'); + + // html_sanitizer service + $this->assertSame(HtmlSanitizer::class, $container->getDefinition('html_sanitizer.sanitizer.custom')->getClass()); + $this->assertCount(1, $args = $container->getDefinition('html_sanitizer.sanitizer.custom')->getArguments()); + $this->assertSame('html_sanitizer.config.custom', (string) $args[0]); + + // config + $this->assertTrue($container->hasDefinition('html_sanitizer.config.custom'), '->registerHtmlSanitizerConfiguration() loads custom sanitizer'); + $this->assertSame(HtmlSanitizerConfig::class, $container->getDefinition('html_sanitizer.config.custom')->getClass()); + $this->assertCount(23, $calls = $container->getDefinition('html_sanitizer.config.custom')->getMethodCalls()); + $this->assertSame( + [ + ['allowSafeElements', [], true], + ['allowStaticElements', [], true], + ['allowElement', ['iframe', 'src'], true], + ['allowElement', ['custom-tag', ['data-attr', 'data-attr-1']], true], + ['allowElement', ['custom-tag-2', '*'], true], + ['blockElement', ['section'], true], + ['dropElement', ['video'], true], + ['allowAttribute', ['src', $this instanceof XmlFrameworkExtensionTest ? 'iframe' : ['iframe']], true], + ['allowAttribute', ['data-attr', '*'], true], + ['dropAttribute', ['data-attr', $this instanceof XmlFrameworkExtensionTest ? 'custom-tag' : ['custom-tag']], true], + ['dropAttribute', ['data-attr-1', []], true], + ['dropAttribute', ['data-attr-2', '*'], true], + ['forceAttribute', ['a', 'rel', 'noopener noreferrer'], true], + ['forceAttribute', ['h1', 'class', 'bp4-heading'], true], + ['forceHttpsUrls', [true], true], + ['allowLinkSchemes', [['http', 'https', 'mailto']], true], + ['allowLinkHosts', [['symfony.com']], true], + ['allowRelativeLinks', [true], true], + ['allowMediaSchemes', [['http', 'https', 'data']], true], + ['allowMediaHosts', [['symfony.com']], true], + ['allowRelativeMedias', [true], true], + ['withAttributeSanitizer', ['@App\\Sanitizer\\CustomAttributeSanitizer'], true], + ['withoutAttributeSanitizer', ['@App\\Sanitizer\\OtherCustomAttributeSanitizer'], true], + ], + + // Convert references to their names for easier assertion + array_map( + static function ($call) { + foreach ($call[1] as $k => $arg) { + $call[1][$k] = $arg instanceof Reference ? '@'.$arg : $arg; + } + + return $call; + }, + $calls + ) + ); + + // Named alias + $this->assertSame('html_sanitizer.sanitizer.all.sanitizer', (string) $container->getAlias(HtmlSanitizerInterface::class.' $allSanitizer')); + $this->assertFalse($container->hasAlias(HtmlSanitizerInterface::class.' $default')); + } + + public function testHtmlSanitizerDefaultNullAllowedLinkMediaHost() + { + $container = $this->createContainerFromFile('html_sanitizer_default_allowed_link_and_media_hosts'); + + $calls = $container->getDefinition('html_sanitizer.config.custom_default')->getMethodCalls(); + $this->assertContains(['allowLinkHosts', [null], true], $calls); + $this->assertContains(['allowRelativeLinks', [false], true], $calls); + $this->assertContains(['allowMediaHosts', [null], true], $calls); + $this->assertContains(['allowRelativeMedias', [false], true], $calls); + } + + public function testHtmlSanitizerDefaultConfig() + { + $container = $this->createContainerFromFile('html_sanitizer_default_config'); + + // html_sanitizer service + $this->assertTrue($container->hasAlias('html_sanitizer'), '->registerHtmlSanitizerConfiguration() loads default_config'); + $this->assertSame('html_sanitizer.sanitizer.default', (string) $container->getAlias('html_sanitizer')); + $this->assertSame(HtmlSanitizer::class, $container->getDefinition('html_sanitizer.sanitizer.default')->getClass()); + $this->assertCount(1, $args = $container->getDefinition('html_sanitizer.sanitizer.default')->getArguments()); + $this->assertSame('html_sanitizer.config.default', (string) $args[0]); + + // config + $this->assertTrue($container->hasDefinition('html_sanitizer.config.default'), '->registerHtmlSanitizerConfiguration() loads custom sanitizer'); + $this->assertSame(HtmlSanitizerConfig::class, $container->getDefinition('html_sanitizer.config.default')->getClass()); + $this->assertCount(1, $calls = $container->getDefinition('html_sanitizer.config.default')->getMethodCalls()); + $this->assertSame( + ['allowSafeElements', [], true], + $calls[0] + ); + + // Named alias + $this->assertFalse($container->hasAlias(HtmlSanitizerInterface::class.' $default')); + + // Default alias + $this->assertSame('html_sanitizer', (string) $container->getAlias(HtmlSanitizerInterface::class)); + } + protected function createContainer(array $data = []) { return new ContainerBuilder(new EnvPlaceholderParameterBag(array_merge([ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index d9f4b1192f456..9c9f12a010ed1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -31,6 +31,7 @@ public function testAssetsCannotHavePathAndUrl() $this->expectException(\LogicException::class); $this->createContainerFromClosure(function ($container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'assets' => [ 'base_urls' => 'http://cdn.example.com', 'base_path' => '/foo', @@ -44,6 +45,7 @@ public function testAssetPackageCannotHavePathAndUrl() $this->expectException(\LogicException::class); $this->createContainerFromClosure(function ($container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'assets' => [ 'packages' => [ 'impossible' => [ @@ -62,6 +64,7 @@ public function testWorkflowValidationStateMachine() $this->expectExceptionMessage('A transition from a place/state must have an unique name. Multiple transitions named "a_to_b" from place/state "a" were found on StateMachine "article".'); $this->createContainerFromClosure(function ($container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'workflows' => [ 'article' => [ 'type' => 'state_machine', @@ -90,6 +93,7 @@ public function testRateLimiterWithLockFactory() try { $this->createContainerFromClosure(function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'lock' => false, 'rate_limiter' => [ 'with_lock' => ['policy' => 'fixed_window', 'limit' => 10, 'interval' => '1 hour'], @@ -104,6 +108,7 @@ public function testRateLimiterWithLockFactory() $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'lock' => true, 'rate_limiter' => [ 'with_lock' => ['policy' => 'fixed_window', 'limit' => 10, 'interval' => '1 hour'], @@ -119,6 +124,7 @@ public function testRateLimiterLockFactory() { $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { $container->loadFromExtension('framework', [ + 'http_method_override' => false, 'rate_limiter' => [ 'without_lock' => ['policy' => 'fixed_window', 'limit' => 10, 'interval' => '1 hour', 'lock_factory' => null], ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php index ebc37d93bed84..131bb07f0c657 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php @@ -32,4 +32,38 @@ 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]); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt index 12e90d48ae40b..4fd20cf7e5fab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt @@ -8,9 +8,9 @@ ----------------- --------------------------------- Service ID .service_2 Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2)  - tag1 (attr3: val3)  - tag2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 Calls setMailer Public no Synthetic yes diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json index 0eda1932f7a15..401c588c03d42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json @@ -34,6 +34,20 @@ "parameters": [] } ] + }, + ".definition_3": { + "class": "Full\\Qualified\\Class3", + "public": false, + "synthetic": false, + "lazy": false, + "shared": true, + "abstract": false, + "autowire": false, + "autoconfigure": false, + "file": "\/path\/to\/file", + "factory_service": "inline factory service (Full\\Qualified\\FactoryClass)", + "factory_method": "get", + "tags": [] } }, "aliases": { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md index d793c5900a65a..d6daca9971dc7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md @@ -25,6 +25,20 @@ Definitions - Attr3: val3 - Tag: `tag2` +### .definition_3 + +- Class: `Full\Qualified\Class3` +- Public: no +- Synthetic: no +- Lazy: no +- Shared: yes +- Abstract: no +- Autowired: no +- Autoconfigured: no +- File: `/path/to/file` +- Factory Service: inline factory service (`Full\Qualified\FactoryClass`) +- Factory Method: `get` + Aliases ------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.txt index cdefb65d208dd..daf47ddc39187 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.txt @@ -7,5 +7,6 @@ --------------- ------------------------ .alias_2 alias for ".service_2" .definition_2 Full\Qualified\Class2 - --------------- ------------------------ + .definition_3 Full\Qualified\Class3 + --------------- ------------------------ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml index a311a2e2bb991..b9416fd069d05 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml @@ -17,4 +17,7 @@ + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt index 2d5b03794ea80..0ceb807a45c2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt @@ -3,9 +3,9 @@ ----------------- --------------------------------- Service ID - Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2)  - tag1 (attr3: val3)  - tag2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 Calls setMailer Public no Synthetic yes diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.json new file mode 100644 index 0000000000000..4bf56746493f8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.json @@ -0,0 +1,14 @@ +{ + "class": "Full\\Qualified\\Class3", + "public": false, + "synthetic": false, + "lazy": false, + "shared": true, + "abstract": false, + "autowire": false, + "autoconfigure": false, + "file": "\/path\/to\/file", + "factory_service": "inline factory service (Full\\Qualified\\FactoryClass)", + "factory_method": "get", + "tags": [] +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.md new file mode 100644 index 0000000000000..68f51634db99f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.md @@ -0,0 +1,11 @@ +- Class: `Full\Qualified\Class3` +- Public: no +- Synthetic: no +- Lazy: no +- Shared: yes +- Abstract: no +- Autowired: no +- Autoconfigured: no +- File: `/path/to/file` +- Factory Service: inline factory service (`Full\Qualified\FactoryClass`) +- Factory Method: `get` diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.txt new file mode 100644 index 0000000000000..35ddaf3e452a8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.txt @@ -0,0 +1,18 @@ + ----------------- ------------------------------------------------------ +  Option   Value  + ----------------- ------------------------------------------------------ + Service ID - + Class Full\Qualified\Class3 + Tags - + Public no + Synthetic no + Lazy no + Shared yes + Abstract no + Autowired no + Autoconfigured no + Required File /path/to/file + Factory Service inline factory service (Full\Qualified\FactoryClass) + Factory Method get + ----------------- ------------------------------------------------------ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.xml new file mode 100644 index 0000000000000..e81c77014253f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_3.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt index af3410f83d5b9..635fadc7d8742 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt @@ -13,13 +13,13 @@ Autoconfigured no Factory Class Full\Qualified\FactoryClass Factory Method get - Arguments Service(.definition_2)  - %parameter%  - Inlined Service  - Array (3 element(s))  - Iterator (2 element(s))  - - Service(definition_1)  - - Service(.definition_2)  - Abstract argument (placeholder) + Arguments Service(.definition_2) + %parameter% + Inlined Service + Array (3 element(s)) + Iterator (2 element(s)) + - Service(definition_1) + - Service(.definition_2) + Abstract argument (placeholder) ---------------- --------------------------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt index 2d5b03794ea80..0ceb807a45c2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt @@ -3,9 +3,9 @@ ----------------- --------------------------------- Service ID - Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2)  - tag1 (attr3: val3)  - tag2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 Calls setMailer Public no Synthetic yes diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.json new file mode 100644 index 0000000000000..94c2fda5402fc --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.json @@ -0,0 +1,15 @@ +{ + "class": "Full\\Qualified\\Class3", + "public": false, + "synthetic": false, + "lazy": false, + "shared": true, + "abstract": false, + "autowire": false, + "autoconfigure": false, + "arguments": [], + "file": "\/path\/to\/file", + "factory_service": "inline factory service (Full\\Qualified\\FactoryClass)", + "factory_method": "get", + "tags": [] +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.md new file mode 100644 index 0000000000000..2ce1f264dfc6c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.md @@ -0,0 +1,12 @@ +- Class: `Full\Qualified\Class3` +- Public: no +- Synthetic: no +- Lazy: no +- Shared: yes +- Abstract: no +- Autowired: no +- Autoconfigured: no +- Arguments: no +- File: `/path/to/file` +- Factory Service: inline factory service (`Full\Qualified\FactoryClass`) +- Factory Method: `get` diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.txt new file mode 100644 index 0000000000000..6e400de44e8ff --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.txt @@ -0,0 +1,18 @@ + ----------------- ------------------------------------------------------ +  Option   Value  + ----------------- ------------------------------------------------------ + Service ID - + Class Full\Qualified\Class3 + Tags - + Public no + Synthetic no + Lazy no + Shared yes + Abstract no + Autowired no + Autoconfigured no + Required File /path/to/file + Factory Service inline factory service (Full\Qualified\FactoryClass) + Factory Method get + ----------------- ------------------------------------------------------ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.xml new file mode 100644 index 0000000000000..e81c77014253f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_3.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt index 25074dfd18b2c..9814273b7a221 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt @@ -11,7 +11,7 @@ | Requirements | name: [a-z]+ | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | | Defaults | name: Joseph | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | +--------------+-------------------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt index 4d4a18e5a71b8..ad7a4c8c844fb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt @@ -10,9 +10,9 @@ | Method | GET|HEAD | | Requirements | name: [a-z]+ | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | -| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=58\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | -| | name: Joseph | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=58\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | +| | name: Joseph | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | +--------------+-----------------------------------------------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt index 5853dd013d3a3..533409d402add 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt @@ -11,8 +11,8 @@ | Requirements | NO CUSTOM | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | | Defaults | NONE | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | | Condition | context.getMethod() in ['GET', 'HEAD', 'POST'] | +--------------+-------------------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt index a690b9798d90a..8e3fe4ca7d65f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt @@ -11,8 +11,8 @@ | Requirements | NO CUSTOM | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | | Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=58\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | -| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | -| | opt1: val1 | -| | opt2: val2 | +| Options | compiler_class: Symfony\Component\Routing\RouteCompiler | +| | opt1: val1 | +| | opt2: val2 | | Condition | context.getMethod() in ['GET', 'HEAD', 'POST'] | +--------------+-----------------------------------------------------------------------------------------------+ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php index 8c7a89574729f..2a53127eaa41a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php index 0c0812f3f9553..ddd1589495139 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php index d380bcaad17fa..400384f616f29 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php index 265e9bb138fbf..497a7a99d6d2b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php index 5fe9fcdb7799f..71fae639a1db6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Controller/DefaultController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Controller/DefaultController.php new file mode 100644 index 0000000000000..feaa957e77d46 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Controller/DefaultController.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Controller; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; + +class DefaultController +{ + #[Route( + path: '/allowed/manually-tagged', + condition: 'service("manually_tagged").giveMeTrue()', + )] + public function allowedByManuallyTagged(): Response + { + return new Response(); + } + + #[Route( + path: '/allowed/auto-configured', + condition: 'service("auto_configured").flip(false)', + )] + public function allowedByAutoConfigured(): Response + { + return new Response(); + } + + #[Route( + path: '/allowed/auto-configured-non-aliased', + condition: 'service("auto_configured_non_aliased").alwaysTrue()', + )] + public function allowedByAutoConfiguredNonAliased(): Response + { + return new Response(); + } + + #[Route( + path: '/denied/manually-tagged', + condition: 'service("manually_tagged").giveMeFalse()', + )] + public function deniedByManuallyTagged(): Response + { + return new Response(); + } + + #[Route( + path: '/denied/auto-configured', + condition: 'service("auto_configured").flip(true)', + )] + public function deniedByAutoConfigured(): Response + { + return new Response(); + } + + #[Route( + path: '/denied/auto-configured-non-aliased', + condition: 'service("auto_configured_non_aliased").alwaysFalse()', + )] + public function deniedByAutoConfiguredNonAliased(): Response + { + return new Response(); + } + + #[Route( + path: '/denied/overridden', + condition: 'service("foo").isAllowed()', + )] + public function deniedByOverriddenAlias(): Response + { + return new Response(); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/RoutingConditionServiceBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/RoutingConditionServiceBundle.php new file mode 100644 index 0000000000000..8ab6891f12820 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/RoutingConditionServiceBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class RoutingConditionServiceBundle extends Bundle +{ +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredNonAliasedService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredNonAliasedService.php new file mode 100644 index 0000000000000..a24df7ca90245 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredNonAliasedService.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service; + +use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService; + +#[AsRoutingConditionService] +class AutoConfiguredNonAliasedService +{ + public function alwaysFalse(): bool + { + return false; + } + + public function alwaysTrue(): bool + { + return true; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredService.php new file mode 100644 index 0000000000000..dbbd5eac25538 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/AutoConfiguredService.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service; + +use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService; + +#[AsRoutingConditionService('auto_configured')] +class AutoConfiguredService +{ + public function flip(bool $value): bool + { + return !$value; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooOriginalService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooOriginalService.php new file mode 100644 index 0000000000000..d78b332383308 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooOriginalService.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service; + +use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService; + +#[AsRoutingConditionService('foo')] +class FooOriginalService +{ + public function isAllowed(): bool + { + return true; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooReplacementService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooReplacementService.php new file mode 100644 index 0000000000000..5e69264c9dc70 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/FooReplacementService.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service; + +use Symfony\Bundle\FrameworkBundle\Routing\Attribute\AsRoutingConditionService; + +#[AsRoutingConditionService(alias: 'foo', priority: -1)] +class FooReplacementService +{ + public function isAllowed(): bool + { + return false; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/ManuallyTaggedService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/ManuallyTaggedService.php new file mode 100644 index 0000000000000..85f0feb027fec --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/RoutingConditionServiceBundle/Service/ManuallyTaggedService.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service; + +class ManuallyTaggedService +{ + public function giveMeTrue(): bool + { + return true; + } + + public function giveMeFalse(): bool + { + return false; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/UidController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/UidController.php new file mode 100644 index 0000000000000..2653f9fbcf82b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/UidController.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\UuidV1; + +class UidController +{ + #[Route(path: '/1/uuid-v1/{userId}')] + public function anyFormat(UuidV1 $userId): Response + { + return new Response($userId); + } + + #[Route(path: '/2/ulid/{id}', requirements: ['id' => '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}'])] + public function specificFormatInAttribute(Ulid $id): Response + { + return new Response($id); + } + + #[Route(path: '/3/uuid-v1/{id<[0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz]{26}>}')] + public function specificFormatInPath(UuidV1 $id): Response + { + return new Response($id); + } + + #[Route(path: '/4/uuid-v1/{postId}/custom-uid/{commentId}')] + public function manyUids(UuidV1 $postId, TestCommentIdentifier $commentId): Response + { + return new Response($postId."\n".$commentId); + } +} + +class TestCommentIdentifier extends Ulid +{ +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml index 8d41ce3267131..bfd37826b268b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml @@ -60,3 +60,7 @@ array_controller: send_email: path: /send_email defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\EmailController::indexAction } + +uid: + resource: "../../Controller/UidController.php" + type: "annotation" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/NonPublicService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/NonPublicService.php index 5c9261ac77bba..284cfd073b242 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/NonPublicService.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/NonPublicService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer; class NonPublicService diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php index 6c7e05e532210..6a244cb40ce54 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer; class PrivateService diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PublicService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PublicService.php index 1ea7b0b0ae180..14de890b630fe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PublicService.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PublicService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer; class PublicService diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/UnusedPrivateService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/UnusedPrivateService.php index 25a7244a50158..3becdba88b78b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/UnusedPrivateService.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/UnusedPrivateService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer; class UnusedPrivateService diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index b3885edaa3f36..b01295607b17f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -86,7 +86,6 @@ public function testClearFailed() $pool->save($item); $r = new \ReflectionObject($pool); $p = $r->getProperty('directory'); - $p->setAccessible(true); $poolDir = $p->getValue($pool); /** @var SplFileInfo $entry */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php index 8135f4dcfe419..463318af39f47 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php @@ -70,6 +70,15 @@ public function testDefaultParameterValueIsResolvedIfConfigIsExisting() $this->assertStringContainsString(sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); } + public function testDumpExtensionConfigWithoutBundle() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'test_dump']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('enabled: true', $tester->getDisplay()); + } + public function testDumpUndefinedBundleOption() { $tester = $this->createCommandTester(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php index e86a7ff790ef7..4747b785f8149 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php @@ -50,6 +50,15 @@ public function testDumpBundleName() $this->assertStringContainsString(' custom:', $tester->getDisplay()); } + public function testDumpExtensionConfigWithoutBundle() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'test_dump']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('enabled: true', $tester->getDisplay()); + } + public function testDumpAtPath() { $tester = $this->createCommandTester(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index ff2cc045b7ac1..ee56012d307ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -117,7 +117,7 @@ public function testDescribeEnvVars() * UNKNOWN TXT - , $tester->getDisplay(true)); + , $tester->getDisplay(true)); putenv('REAL'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Extension/TestDumpExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Extension/TestDumpExtension.php new file mode 100644 index 0000000000000..d8cef92850992 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Extension/TestDumpExtension.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Extension; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; + +class TestDumpExtension extends Extension implements ConfigurationInterface +{ + public function getConfigTreeBuilder(): TreeBuilder + { + $treeBuilder = new TreeBuilder('test_dump'); + $treeBuilder->getRootNode() + ->children() + ->booleanNode('enabled')->defaultTrue()->end() + ->end() + ; + + return $treeBuilder; + } + + public function load(array $configs, ContainerBuilder $container): void + { + } + + public function getConfiguration(array $config, ContainerBuilder $container): ConfigurationInterface + { + return $this; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php index ca371766deb22..942dd05178b24 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; use Psr\Log\LoggerInterface; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php index e9a8cd143b802..7390a124c3c0a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php @@ -62,6 +62,23 @@ public function testSearchMultipleRoutes() $this->assertStringContainsString('/test', $tester->getDisplay()); } + public function testSearchMultipleRoutesWithoutInteraction() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'routerdebug'], ['interactive' => false]); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringNotContainsString('Select one of the matching routes:', $tester->getDisplay()); + $this->assertStringContainsString('routerdebug_session_welcome', $tester->getDisplay()); + $this->assertStringContainsString('/session', $tester->getDisplay()); + $this->assertStringContainsString('routerdebug_session_welcome_name', $tester->getDisplay()); + $this->assertStringContainsString('/session/{name} ', $tester->getDisplay()); + $this->assertStringContainsString('routerdebug_session_logout', $tester->getDisplay()); + $this->assertStringContainsString('/session_logout', $tester->getDisplay()); + $this->assertStringContainsString('routerdebug_test', $tester->getDisplay()); + $this->assertStringContainsString('/test', $tester->getDisplay()); + } + public function testSearchWithThrow() { $this->expectException(\InvalidArgumentException::class); @@ -75,10 +92,6 @@ public function testSearchWithThrow() */ public function testComplete(array $input, array $expectedSuggestions) { - if (!class_exists(CommandCompletionTester::class)) { - $this->markTestSkipped('Test command completion requires symfony/console 5.4+.'); - } - $tester = new CommandCompletionTester($this->application->get('debug:router')); $this->assertSame($expectedSuggestions, $tester->complete($input)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php new file mode 100644 index 0000000000000..780060d7fc6f6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +class RoutingConditionServiceTest extends AbstractWebTestCase +{ + /** + * @dataProvider provideRoutes + */ + public function testCondition(int $code, string $path) + { + $client = static::createClient(['test_case' => 'RoutingConditionService']); + + $client->request('GET', $path); + $this->assertSame($code, $client->getResponse()->getStatusCode()); + } + + public function provideRoutes(): iterable + { + yield 'allowed by an autoconfigured service' => [ + 200, + '/allowed/manually-tagged', + ]; + + yield 'allowed by a manually tagged service' => [ + 200, + '/allowed/auto-configured', + ]; + + yield 'allowed by a manually tagged non aliased service' => [ + 200, + '/allowed/auto-configured-non-aliased', + ]; + + yield 'denied by an autoconfigured service' => [ + 404, + '/denied/manually-tagged', + ]; + + yield 'denied by a manually tagged service' => [ + 404, + '/denied/auto-configured', + ]; + + yield 'denied by a manually tagged non aliased service' => [ + 404, + '/denied/auto-configured-non-aliased', + ]; + + yield 'denied by an overridden service' => [ + 404, + '/denied/overridden', + ]; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php index 019aa418901d8..aaf6ad49ccca1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php @@ -32,6 +32,41 @@ public function testDeserializeArrayOfObject() $this->assertEquals($expected, $result); } + + /** + * @dataProvider provideNormalizersAndEncodersWithDefaultContextOption + */ + public function testNormalizersAndEncodersUseDefaultContextConfigOption(string $normalizerId) + { + static::bootKernel(['test_case' => 'Serializer']); + + $normalizer = static::getContainer()->get($normalizerId); + + $reflectionObject = new \ReflectionObject($normalizer); + $property = $reflectionObject->getProperty('defaultContext'); + $property->setAccessible(true); + + $defaultContext = $property->getValue($normalizer); + + self::assertArrayHasKey('fake_context_option', $defaultContext); + self::assertEquals('foo', $defaultContext['fake_context_option']); + } + + public function provideNormalizersAndEncodersWithDefaultContextOption(): array + { + return [ + ['serializer.normalizer.constraint_violation_list.alias'], + ['serializer.normalizer.dateinterval.alias'], + ['serializer.normalizer.datetime.alias'], + ['serializer.normalizer.json_serializable.alias'], + ['serializer.normalizer.problem.alias'], + ['serializer.normalizer.uid.alias'], + ['serializer.normalizer.object.alias'], + ['serializer.encoder.xml.alias'], + ['serializer.encoder.yaml.alias'], + ['serializer.encoder.csv.alias'], + ]; + } } class Foo diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php index 9108d47b244c8..76a373c0c05a9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php @@ -39,4 +39,22 @@ public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled() $this->assertTrue(static::getContainer()->has('private_service')); $this->assertFalse(static::getContainer()->has(UnusedPrivateService::class)); } + + /** + * @doesNotPerformAssertions + */ + public function testBootKernel() + { + static::bootKernel(['test_case' => 'TestServiceContainer']); + } + + /** + * @depends testBootKernel + */ + public function testKernelIsNotInitialized() + { + self::assertNull(self::$class); + self::assertNull(self::$kernel); + self::assertFalse(self::$booted); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/UidTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/UidTest.php new file mode 100644 index 0000000000000..61ba430b9b3ea --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/UidTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\UidController; +use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\UuidV1; +use Symfony\Component\Uid\UuidV4; +use Symfony\Component\Uid\UuidV6; + +/** + * @see UidController + */ +class UidTest extends AbstractWebTestCase +{ + protected function setUp(): void + { + parent::setUp(); + + self::deleteTmpDir(); + } + + public function testArgumentValueResolverDisabled() + { + $this->expectException(\TypeError::class); + $this->expectExceptionMessage('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\UidController::anyFormat(): Argument #1 ($userId) must be of type Symfony\Component\Uid\UuidV1, string given'); + + $client = $this->createClient(['test_case' => 'Uid', 'root_config' => 'config_disabled.yml']); + + $client->request('GET', '/1/uuid-v1/'.new UuidV1()); + } + + public function testArgumentValueResolverEnabled() + { + $client = $this->createClient(['test_case' => 'Uid', 'root_config' => 'config_enabled.yml']); + + // Any format + $client->request('GET', '/1/uuid-v1/'.$uuidV1 = new UuidV1()); + $this->assertSame((string) $uuidV1, $client->getResponse()->getContent()); + $client->request('GET', '/1/uuid-v1/'.$uuidV1->toBase58()); + $this->assertSame((string) $uuidV1, $client->getResponse()->getContent()); + $client->request('GET', '/1/uuid-v1/'.$uuidV1->toRfc4122()); + $this->assertSame((string) $uuidV1, $client->getResponse()->getContent()); + // Bad version + $client->request('GET', '/1/uuid-v1/'.$uuidV4 = new UuidV4()); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + + // Only base58 format + $client->request('GET', '/2/ulid/'.($ulid = new Ulid())->toBase58()); + $this->assertSame((string) $ulid, $client->getResponse()->getContent()); + $client->request('GET', '/2/ulid/'.$ulid); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + $client->request('GET', '/2/ulid/'.$ulid->toRfc4122()); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + + // Only base32 format + $client->request('GET', '/3/uuid-v1/'.$uuidV1->toBase32()); + $this->assertSame((string) $uuidV1, $client->getResponse()->getContent()); + $client->request('GET', '/3/uuid-v1/'.$uuidV1); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + $client->request('GET', '/3/uuid-v1/'.$uuidV1->toBase58()); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + // Bad version + $client->request('GET', '/3/uuid-v1/'.(new UuidV6())->toBase32()); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + + // Any format for both + $client->request('GET', '/4/uuid-v1/'.$uuidV1.'/custom-uid/'.$ulid->toRfc4122()); + $this->assertSame($uuidV1."\n".$ulid, $client->getResponse()->getContent()); + $client->request('GET', '/4/uuid-v1/'.$uuidV1->toBase58().'/custom-uid/'.$ulid->toBase58()); + $this->assertSame($uuidV1."\n".$ulid, $client->getResponse()->getContent()); + // Bad version + $client->request('GET', '/4/uuid-v1/'.$uuidV4.'/custom-uid/'.$ulid); + $this->assertSame(404, $client->getResponse()->getStatusCode()); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php index 31fcc742fd05b..b182e902d7392 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app; use Psr\Log\NullLogger; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Extension\TestDumpExtension; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Loader\LoaderInterface; @@ -80,6 +81,7 @@ public function registerContainerConfiguration(LoaderInterface $loader) protected function build(ContainerBuilder $container) { $container->register('logger', NullLogger::class); + $container->registerExtension(new TestDumpExtension()); } public function __sleep(): array diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml index fec387d87962d..87794f637eef6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/no_annotations_cache.yml @@ -2,5 +2,6 @@ imports: - { resource: config.yml } framework: + http_method_override: false annotations: cache: none diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml index 82a5a5422ab7d..7ce5cde031c7d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false translator: true validation: true serializer: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml index b991dd593148d..a5e861089e679 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml @@ -12,6 +12,7 @@ services: - name: kernel.cache_clearer framework: + http_method_override: false cache: pools: cache.private_pool: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml index d7733e0e3217f..119d9d7280787 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml @@ -6,6 +6,7 @@ parameters: env(LIFETIME_EXPRESSION): '13 seconds' framework: + http_method_override: false cache: pools: cache.pool1: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml index e5ec8c4effbc4..727cde9227279 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml @@ -5,6 +5,7 @@ parameters: env(REDIS_HOST): 'localhost' framework: + http_method_override: false cache: app: cache.adapter.redis default_redis_provider: "redis://%env(REDIS_HOST)%" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml index 419ee07a0aba0..172508c0208a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml @@ -18,6 +18,7 @@ services: provider: cache.test_redis_connection framework: + http_method_override: false cache: pools: cache.pool1: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml index 6dba635a15555..6793268174bc8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false secret: '%secret%' default_locale: '%env(LOCALE)%' enabled_locales: ['%env(LOCALE)%'] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDump/config.yml index be0eab4d5645e..3efa5f950450e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDump/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDump/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false esi: true ssi: true fragments: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Fragment/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Fragment/config.yml index 16fc81dd268d4..b22016f1e4e34 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Fragment/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Fragment/config.yml @@ -3,6 +3,7 @@ imports: - { resource: services.yml } framework: + http_method_override: false fragments: ~ twig: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Mailer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Mailer/config.yml index b464a41a0d857..2ea7269e629aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Mailer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Mailer/config.yml @@ -3,6 +3,7 @@ imports: - { resource: services.yml } framework: + http_method_override: false mailer: dsn: 'null://null' envelope: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Profiler/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Profiler/config.yml index 12ce67e548ea0..ca38aa1aeef5c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Profiler/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Profiler/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false profiler: enabled: true collect: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ProfilerCollectParameter/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ProfilerCollectParameter/config.yml index 67360dd321681..67dbec31f1949 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ProfilerCollectParameter/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ProfilerCollectParameter/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false profiler: enabled: true collect: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/bundles.php new file mode 100644 index 0000000000000..1fc9f4f2588eb --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\RoutingConditionServiceBundle; + +return [ + new FrameworkBundle(), + new RoutingConditionServiceBundle(), +]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/config.yml new file mode 100644 index 0000000000000..50cd22497fe20 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/config.yml @@ -0,0 +1,4 @@ +imports: + - { resource: ../config/default.yml } + - { resource: services_auto_configured.yml } + - { resource: services_manually_configured.yml } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/routing.yml new file mode 100644 index 0000000000000..221af8ca71770 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/routing.yml @@ -0,0 +1,4 @@ +_routingconditionservice_bundle: + prefix: / + resource: "@RoutingConditionServiceBundle/Controller" + type: annotation diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_auto_configured.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_auto_configured.yml new file mode 100644 index 0000000000000..4361226c754a1 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_auto_configured.yml @@ -0,0 +1,13 @@ +services: + + _defaults: + autoconfigure: true + + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service\AutoConfiguredService: + + auto_configured_non_aliased: + class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service\AutoConfiguredNonAliasedService + + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service\FooOriginalService: + + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service\FooReplacementService: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_manually_configured.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_manually_configured.yml new file mode 100644 index 0000000000000..d7d8f28f760e7 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/RoutingConditionService/services_manually_configured.yml @@ -0,0 +1,8 @@ +services: + + _defaults: + autoconfigure: false + + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\RoutingConditionServiceBundle\Service\ManuallyTaggedService: + tags: + - { name: 'routing.condition_service', alias: 'manually_tagged' } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml index 3721de1cac584..e51b738580255 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml @@ -2,13 +2,59 @@ imports: - { resource: ../config/default.yml } framework: + http_method_override: false serializer: enabled: true default_context: enable_max_depth: true + fake_context_option: foo property_info: { enabled: true } services: serializer.alias: alias: serializer public: true + + serializer.normalizer.constraint_violation_list.alias: + alias: serializer.normalizer.constraint_violation_list + public: true + + serializer.normalizer.dateinterval.alias: + alias: serializer.normalizer.dateinterval + public: true + + serializer.normalizer.datetime.alias: + alias: serializer.normalizer.datetime + public: true + + serializer.normalizer.json_serializable.alias: + alias: serializer.normalizer.json_serializable + public: true + + serializer.normalizer.problem.alias: + alias: serializer.normalizer.problem + public: true + + serializer.normalizer.uid.alias: + alias: serializer.normalizer.uid + public: true + + serializer.normalizer.property.alias: + alias: serializer.normalizer.property + public: true + + serializer.normalizer.object.alias: + alias: serializer.normalizer.object + public: true + + serializer.encoder.xml.alias: + alias: serializer.encoder.xml + public: true + + serializer.encoder.yaml.alias: + alias: serializer.encoder.yaml + public: true + + serializer.encoder.csv.alias: + alias: serializer.encoder.csv + public: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml index 669edf5667611..1af9cd9bd32ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml @@ -3,6 +3,7 @@ imports: - { resource: services.yml } framework: + http_method_override: false secret: '%secret%' default_locale: '%env(LOCALE)%' enabled_locales: ['%env(LOCALE)%'] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/config.yml index 84af2df662717..472c4cdcc02dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/config.yml @@ -3,4 +3,5 @@ imports: - { resource: services.yml } framework: + http_method_override: false test: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/test_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/test_disabled.yml index 6f1b62e4a7a22..6f75b77e7cbb4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/test_disabled.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/test_disabled.yml @@ -3,4 +3,5 @@ imports: - { resource: services.yml } framework: + http_method_override: false test: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml index 1cd6417b937b1..5ca63a12b8ca9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml @@ -3,6 +3,7 @@ imports: - { resource: services.yml } framework: + http_method_override: false secret: '%secret%' default_locale: '%env(LOCALE)%' enabled_locales: ['%env(LOCALE)%'] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/bundles.php new file mode 100644 index 0000000000000..15ff182c6fed5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; + +return [ + new FrameworkBundle(), + new TestBundle(), +]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_disabled.yml new file mode 100644 index 0000000000000..5e6428618b3ee --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_disabled.yml @@ -0,0 +1,7 @@ +imports: + - { resource: "../config/default.yml" } + +framework: + http_method_override: false + uid: + enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_enabled.yml new file mode 100644 index 0000000000000..f6d1682c99eb5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/config_enabled.yml @@ -0,0 +1,6 @@ +imports: + - { resource: "../config/default.yml" } + +framework: + http_method_override: false + uid: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/routing.yml new file mode 100644 index 0000000000000..46a625a0183cb --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Uid/routing.yml @@ -0,0 +1,2 @@ +uid: + resource: "@TestBundle/Resources/config/routing.yml" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml index c4087e32f585f..e13e9c1c3c782 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: test router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml", utf8: true } validation: { enabled: true, enable_annotations: true } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php index d9dd700efd92e..36ba1df088a7a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php @@ -83,6 +83,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load { $c->register('logger', NullLogger::class); $c->loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => '$ecret', 'router' => ['utf8' => true], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php index d47ca5a822139..76b02674e90a3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php @@ -89,6 +89,16 @@ public function testFlexStyle() $response = $kernel->handle($request); $this->assertEquals('Have a great day!', $response->getContent()); + + $request = Request::create('/h'); + $response = $kernel->handle($request); + + $this->assertEquals('Have a great day!', $response->getContent()); + + $request = Request::create('/easter'); + $response = $kernel->handle($request); + + $this->assertSame('easter', $response->getContent()); } public function testSecretLoadedFromExtension() @@ -101,7 +111,7 @@ public function testSecretLoadedFromExtension() public function testAnonymousMicroKernel() { - $kernel = new class('anonymous_kernel') extends MinimalKernel { + $kernel = $this->kernel = new class('anonymous_kernel') extends MinimalKernel { public function helloAction(): Response { return new Response('Hello World!'); @@ -110,6 +120,7 @@ public function helloAction(): Response protected function configureContainer(ContainerConfigurator $c): void { $c->extension('framework', [ + 'http_method_override' => false, 'router' => ['utf8' => true], ]); $c->services()->set('logger', NullLogger::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/config/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/config/bundles.php index 0691b2b32d19c..fbde1ef1c9a87 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/config/bundles.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/config/bundles.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + use Symfony\Bundle\FrameworkBundle\FrameworkBundle; return [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php index d4f2ce121be54..d3aaeb6d387fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php @@ -18,11 +18,14 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; class FlexStyleMicroKernel extends Kernel { - use MicroKernelTrait; + use MicroKernelTrait { + configureRoutes as traitConfigureRoutes; + } private $cacheDir; @@ -31,6 +34,12 @@ public function halloweenAction(\stdClass $o) return new Response($o->halloween); } + #[Route('/easter')] + public function easterAction() + { + return new Response('easter'); + } + public function createHalloween(LoggerInterface $logger, string $halloween) { $o = new \stdClass(); @@ -73,7 +82,10 @@ public function __destruct() protected function configureRoutes(RoutingConfigurator $routes): void { + $this->traitConfigureRoutes($routes); + $routes->add('halloween', '/')->controller([$this, 'halloweenAction']); + $routes->add('halloween2', '/h')->controller($this->halloweenAction(...)); } protected function configureContainer(ContainerConfigurator $c): void @@ -88,6 +100,6 @@ protected function configureContainer(ContainerConfigurator $c): void ->factory([$this, 'createHalloween']) ->arg('$halloween', '%halloween%'); - $c->extension('framework', ['router' => ['utf8' => true]]); + $c->extension('framework', ['http_method_override' => false, 'router' => ['utf8' => true]]); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php index 2770813d8a696..404a239b51282 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/KernelBrowserTest.php @@ -51,10 +51,20 @@ public function testEnableRebootKernel() $client->request('GET', '/'); } + public function testRequestAfterKernelShutdownAndPerformedRequest() + { + $this->expectNotToPerformAssertions(); + + $client = static::createClient(['test_case' => 'TestServiceContainer']); + $client->request('GET', '/'); + static::ensureKernelShutdown(); + $client->request('GET', '/'); + } + private function getKernelMock() { $mock = $this->getMockBuilder($this->getKernelClass()) - ->setMethods(['shutdown', 'boot', 'handle']) + ->setMethods(['shutdown', 'boot', 'handle', 'getContainer']) ->disableOriginalConstructor() ->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php index f4bc970a5a84a..2b619243eaf11 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/DelegatingLoaderTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php index bf61409d4ee2f..29126e130b561 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php @@ -18,9 +18,6 @@ use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -/** - * @requires function \Symfony\Component\Routing\Matcher\CompiledUrlMatcher::match - */ class RedirectableCompiledUrlMatcherTest extends TestCase { public function testRedirectWhenNoSlash() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/DotenvVaultTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/DotenvVaultTest.php index 62ca08b07ca6b..780bffcff25a1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/DotenvVaultTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/DotenvVaultTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Secrets; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php index a9b88b1763bd5..4beacafa0cb81 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php @@ -1,11 +1,23 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Secrets; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; use Symfony\Component\Filesystem\Filesystem; +/** + * @requires extension sodium + */ class SodiumVaultTest extends TestCase { private $secretsDir; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/TestBrowserTokenTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/TestBrowserTokenTest.php index 8c5387590a43a..cc308303474b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/TestBrowserTokenTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/TestBrowserTokenTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\FrameworkBundle\Tests\Test; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php index f6098ea6e8eca..8c43917df6f5e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php @@ -23,7 +23,6 @@ use Symfony\Component\HttpFoundation\Cookie as HttpFoundationCookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame; class WebTestCaseTest extends TestCase { @@ -78,10 +77,6 @@ public function testAssertResponseRedirectsWithLocationAndStatusCode() public function testAssertResponseFormat() { - if (!class_exists(ResponseFormatSame::class)) { - $this->markTestSkipped('Too old version of HttpFoundation.'); - } - $this->getResponseTester(new Response('', 200, ['Content-Type' => 'application/vnd.myformat']))->assertResponseFormatSame('custom'); $this->getResponseTester(new Response('', 200, ['Content-Type' => 'application/ld+json']))->assertResponseFormatSame('jsonld'); $this->getResponseTester(new Response())->assertResponseFormatSame(null); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index 54416a343b88e..ff0981a71444c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -139,7 +139,7 @@ public function testInvalidOptions() $this->expectExceptionMessage('The Translator does not support the following options: \'foo\''); $container = $this->createMock(ContainerInterface::class); - (new Translator($container, new MessageFormatter(), 'en', [], ['foo' => 'bar'])); + new Translator($container, new MessageFormatter(), 'en', [], ['foo' => 'bar']); } /** @dataProvider getDebugModeAndCacheDirCombinations */ diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index f19610887be35..f80271f1dcfd4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -16,34 +16,35 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "composer-runtime-api": ">=2.1", "ext-xml": "*", "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4.5|^6.0.5", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-kernel": "^6.1", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.22", "symfony/filesystem": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0" }, "require-dev": { - "doctrine/annotations": "^1.13.1", - "doctrine/persistence": "^1.3|^2.0", + "doctrine/annotations": "^1.13.1|^2", + "doctrine/persistence": "^1.3|^2|^3", "symfony/asset": "^5.4|^6.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", + "symfony/console": "^5.4.9|^6.0.9", "symfony/css-selector": "^5.4|^6.0", "symfony/dom-crawler": "^5.4|^6.0", "symfony/dotenv": "^5.4|^6.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/form": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", "symfony/http-client": "^5.4|^6.0", "symfony/lock": "^5.4|^6.0", "symfony/mailer": "^5.4|^6.0", @@ -53,7 +54,8 @@ "symfony/process": "^5.4|^6.0", "symfony/rate-limiter": "^5.4|^6.0", "symfony/security-bundle": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", + "symfony/semaphore": "^5.4|^6.0", + "symfony/serializer": "^6.1", "symfony/stopwatch": "^5.4|^6.0", "symfony/string": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", @@ -62,11 +64,10 @@ "symfony/workflow": "^5.4|^6.0", "symfony/yaml": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", "symfony/web-link": "^5.4|^6.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "paragonie/sodium_compat": "^1.8", - "twig/twig": "^2.10|^3.0", - "symfony/phpunit-bridge": "^5.4|^6.0" + "twig/twig": "^2.10|^3.0" }, "conflict": { "doctrine/annotations": "<1.13.1", @@ -86,7 +87,7 @@ "symfony/mime": "<5.4", "symfony/property-info": "<5.4", "symfony/property-access": "<5.4", - "symfony/serializer": "<5.4", + "symfony/serializer": "<6.1", "symfony/security-csrf": "<5.4", "symfony/security-core": "<5.4", "symfony/stopwatch": "<5.4", diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 3b3bb88afa573..35631064bacf3 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -3,7 +3,9 @@ CHANGELOG 6.1 --- -* The `security.access_control` now accepts a `RequestMatcherInterface` under the `request_matcher` option as scope configuration + + * The `security.access_control` now accepts a `RequestMatcherInterface` under the `request_matcher` option as scope configuration + * Display the inherited roles of the logged-in user in the Web Debug Toolbar 6.0 --- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php index ea1e44018ea05..dedcda9bd6f6f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php @@ -245,7 +245,7 @@ private function formatCallable(mixed $callable): string if (str_contains($r->name, '{closure}')) { return 'Closure()'; } - if ($class = $r->getClosureScopeClass()) { + if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { return sprintf('%s::%s()', $class->name, $r->name); } diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 394006f55b66b..c7df65486efdf 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -111,7 +111,7 @@ public function collect(Request $request, Response $response, \Throwable $except $logoutUrl = null; try { $logoutUrl = $this->logoutUrlGenerator?->getLogoutPath(); - } catch (\Exception $e) { + } catch (\Exception) { // fail silently when the logout URL cannot be generated } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php index ccab76679a32a..a0d6206134031 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface; use Symfony\Component\Security\Http\EventListener\CsrfProtectionListener; use Symfony\Component\Security\Http\EventListener\CsrfTokenClearingLogoutListener; @@ -52,7 +53,7 @@ protected function registerLogoutHandler(ContainerBuilder $container) $csrfTokenStorage = $container->findDefinition('security.csrf.token_storage'); $csrfTokenStorageClass = $container->getParameterBag()->resolveValue($csrfTokenStorage->getClass()); - if (!is_subclass_of($csrfTokenStorageClass, 'Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface')) { + if (!is_subclass_of($csrfTokenStorageClass, ClearableTokenStorageInterface::class)) { return; } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php index b26a32b5a7d6d..2b1159eff979a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterTokenUsageTrackingPass.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler; -use Symfony\Bridge\Monolog\Processor\ProcessorInterface; +use Monolog\Processor\ProcessorInterface; use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php index b0c6b5c0ecb79..6a34fe7efb703 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php @@ -80,7 +80,7 @@ protected function createAuthenticationSuccessHandler(ContainerBuilder $containe if (isset($config['success_handler'])) { $successHandler = $container->setDefinition($successHandlerId, new ChildDefinition('security.authentication.custom_success_handler')); - $successHandler->replaceArgument(0, new Reference($config['success_handler'])); + $successHandler->replaceArgument(0, new ChildDefinition($config['success_handler'])); $successHandler->replaceArgument(1, $options); $successHandler->replaceArgument(2, $id); } else { @@ -99,7 +99,7 @@ protected function createAuthenticationFailureHandler(ContainerBuilder $containe if (isset($config['failure_handler'])) { $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.custom_failure_handler')); - $failureHandler->replaceArgument(0, new Reference($config['failure_handler'])); + $failureHandler->replaceArgument(0, new ChildDefinition($config['failure_handler'])); $failureHandler->replaceArgument(1, $options); } else { $failureHandler = $container->setDefinition($id, new ChildDefinition('security.authentication.failure_handler')); diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php index 8af8e4424b270..deccbb3975469 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php @@ -35,10 +35,6 @@ public function getKey(): string public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string { $key = str_replace('-', '_', $this->getKey()); - if (!class_exists(LdapAuthenticator::class)) { - throw new \LogicException(sprintf('The "%s" authenticator requires the "symfony/ldap" package version "5.1" or higher.', $key)); - } - $authenticatorId = parent::createAuthenticator($container, $firewallName, $config, $userProviderId); $container->setDefinition('security.listener.'.$key.'.'.$firewallName, new Definition(CheckLdapCredentialsListener::class)) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginLinkFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginLinkFactory.php index 88e34192abf14..29b588631bc0a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginLinkFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginLinkFactory.php @@ -20,7 +20,6 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; -use Symfony\Component\Security\Http\LoginLink\LoginLinkHandler; /** * @internal @@ -88,10 +87,6 @@ public function getKey(): string public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string { - if (!class_exists(LoginLinkHandler::class)) { - throw new \LogicException('Login login link requires symfony/security-http:^5.2.'); - } - if (!$container->hasDefinition('security.authenticator.login_link')) { $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/../../Resources/config')); $loader->load('security_authenticator_login_link.php'); diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php index 5b5c1a55bce0a..5b2cfe781f490 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php @@ -19,7 +19,6 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface; use Symfony\Component\RateLimiter\RateLimiterFactory; -use Symfony\Component\Security\Http\EventListener\LoginThrottlingListener; use Symfony\Component\Security\Http\RateLimiter\DefaultLoginRateLimiter; /** @@ -56,10 +55,6 @@ public function addConfiguration(NodeDefinition $builder) public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): array { - if (!class_exists(LoginThrottlingListener::class)) { - throw new \LogicException('Login throttling requires symfony/security-http:^5.2.'); - } - if (!class_exists(RateLimiterFactory::class)) { throw new \LogicException('Login throttling requires the Rate Limiter component. Try running "composer require symfony/rate-limiter".'); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index 92287664ece41..2a85c2486c8f1 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -16,7 +16,6 @@ use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -71,6 +70,7 @@ public function createAuthenticator(ContainerBuilder $container, string $firewal $tokenVerifier = $this->createTokenVerifier($container, $firewallName, $config['token_verifier'] ?? null); $container->setDefinition($rememberMeHandlerId, new ChildDefinition('security.authenticator.persistent_remember_me_handler')) ->replaceArgument(0, new Reference($tokenProviderId)) + ->replaceArgument(1, $config['secret']) ->replaceArgument(2, new Reference($userProviderId)) ->replaceArgument(4, $config) ->replaceArgument(6, $tokenVerifier) @@ -79,6 +79,7 @@ public function createAuthenticator(ContainerBuilder $container, string $firewal $signatureHasherId = 'security.authenticator.remember_me_signature_hasher.'.$firewallName; $container->setDefinition($signatureHasherId, new ChildDefinition('security.authenticator.remember_me_signature_hasher')) ->replaceArgument(1, $config['signature_properties']) + ->replaceArgument(2, $config['secret']) ; $container->setDefinition($rememberMeHandlerId, new ChildDefinition('security.authenticator.signature_remember_me_handler')) @@ -140,7 +141,10 @@ public function addConfiguration(NodeDefinition $node) ; $builder - ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('secret') + ->cannotBeEmpty() + ->defaultValue('%kernel.secret%') + ->end() ->scalarNode('service')->end() ->arrayNode('user_providers') ->beforeNormalization() @@ -189,54 +193,6 @@ public function addConfiguration(NodeDefinition $node) } } - private function generateRememberMeServicesTemplateId(array $config, string $id): string - { - if (isset($config['service'])) { - return $config['service']; - } - - if (isset($config['token_provider'])) { - return 'security.authentication.rememberme.services.persistent'; - } - - return 'security.authentication.rememberme.services.simplehash'; - } - - private function createRememberMeServices(ContainerBuilder $container, string $id, string $templateId, array $userProviders, array $config): void - { - $rememberMeServicesId = $templateId.'.'.$id; - - $rememberMeServices = $container->setDefinition($rememberMeServicesId, new ChildDefinition($templateId)); - $rememberMeServices->replaceArgument(1, $config['secret']); - $rememberMeServices->replaceArgument(2, $id); - - if (isset($config['token_provider'])) { - $tokenProviderId = $this->createTokenProvider($container, $id, $config['token_provider']); - $rememberMeServices->addMethodCall('setTokenProvider', [new Reference($tokenProviderId)]); - } - - // remember-me options - $mergedOptions = array_intersect_key($config, $this->options); - if ('auto' === $mergedOptions['secure']) { - $mergedOptions['secure'] = null; - } - - $rememberMeServices->replaceArgument(3, $mergedOptions); - - if ($config['user_providers']) { - $userProviders = []; - foreach ($config['user_providers'] as $providerName) { - $userProviders[] = new Reference('security.user.provider.concrete.'.$providerName); - } - } - - if (0 === \count($userProviders)) { - throw new \RuntimeException('You must configure at least one remember-me aware listener (such as form-login) for each firewall that has remember-me enabled.'); - } - - $rememberMeServices->replaceArgument(0, new IteratorArgument(array_unique($userProviders))); - } - private function createTokenProvider(ContainerBuilder $container, string $firewallName, array $config): string { $tokenProviderId = $config['service'] ?? false; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 9e8d0f81a7374..803fc5ed5d796 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -30,7 +30,9 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\HttpFoundation\RequestMatcher; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher; @@ -43,6 +45,7 @@ use Symfony\Component\Security\Core\Authorization\Strategy\UnanimousStrategy; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\User\ChainUserProvider; +use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Authenticator\Debug\TraceableAuthenticatorManagerListener; use Symfony\Component\Security\Http\Event\CheckPassportEvent; @@ -306,7 +309,7 @@ private function createFirewalls(array $config, ContainerBuilder $container) // register an autowire alias for the UserCheckerInterface if no custom user checker service is configured if (!$customUserChecker) { - $container->setAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', new Alias('security.user_checker', false)); + $container->setAlias(UserCheckerInterface::class, new Alias('security.user_checker', false)); } } @@ -842,7 +845,7 @@ private function createExpression(ContainerBuilder $container, string $expressio } $container - ->register($id, 'Symfony\Component\ExpressionLanguage\Expression') + ->register($id, Expression::class) ->setPublic(false) ->addArgument($expression) ; @@ -881,7 +884,7 @@ private function createRequestMatcher(ContainerBuilder $container, string $path } $container - ->register($id, 'Symfony\Component\HttpFoundation\RequestMatcher') + ->register($id, RequestMatcher::class) ->setPublic(false) ->setArguments($arguments) ; diff --git a/src/Symfony/Bundle/SecurityBundle/LICENSE b/src/Symfony/Bundle/SecurityBundle/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bundle/SecurityBundle/LICENSE +++ b/src/Symfony/Bundle/SecurityBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php index e655520b0e745..04d6501952649 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php @@ -92,7 +92,10 @@ ->set('security.authentication.trust_resolver', AuthenticationTrustResolver::class) ->set('security.authentication.session_strategy', SessionAuthenticationStrategy::class) - ->args([param('security.authentication.session_strategy.strategy')]) + ->args([ + param('security.authentication.session_strategy.strategy'), + service('security.csrf.token_storage')->ignoreOnInvalid(), + ]) ->alias(SessionAuthenticationStrategyInterface::class, 'security.authentication.session_strategy') ->set('security.authentication.session_strategy_noop', SessionAuthenticationStrategy::class) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.php index 2bbe4caa39c5a..dfd94ad0d6f49 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.php @@ -102,6 +102,7 @@ ->args([ service('security.http_utils'), [], // Options + service('logger')->nullOnInvalid(), ]) ->set('security.authentication.custom_failure_handler', CustomAuthenticationFailureHandler::class) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 26b59585a1c65..cf2b54e27cbb7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -5,7 +5,7 @@ {% block toolbar %} {% if collector.firewall %} {% set icon %} - {{ include('@Security/Collector/icon.svg') }} + {{ source('@Security/Collector/icon.svg') }} {{ collector.user|default('n/a') }} {% endset %} @@ -46,6 +46,26 @@
+ {% if collector.supportsRoleHierarchy %} +
+ Inherited Roles + + {% if collector.inheritedRoles is empty %} + none + {% else %} + {% set remainingRoles = collector.inheritedRoles|slice(1) %} + {{ collector.inheritedRoles|first }} + {% if remainingRoles is not empty %} + + + + {{ remainingRoles|length }} more + + {% endif %} + {% endif %} + +
+ {% endif %} +
Token class {{ collector.tokenClass|abbr_class }} @@ -89,7 +109,7 @@ {% block menu %} - {{ include('@Security/Collector/icon.svg') }} + {{ source('@Security/Collector/icon.svg') }} Security {% endblock %} @@ -110,7 +130,7 @@
- {{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }} Authenticated
@@ -167,11 +187,11 @@ Name
- {{ include('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }} Security enabled
- {{ include('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }} Stateless
@@ -290,7 +310,7 @@ {{ profiler_dump(authenticator.stub) }} - {{ include('@WebProfiler/Icon/' ~ (authenticator.supports ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (authenticator.supports ? 'yes' : 'no') ~ '.svg') }} {{ '%0.2f'|format(authenticator.duration * 1000) }} ms {{ authenticator.passport ? profiler_dump(authenticator.passport) : '(none)' }} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php index e9dfde9344fcd..bc4d9fe8876be 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php @@ -146,7 +146,7 @@ private function createContainer($sessionStorageOptions) ]; $ext = new FrameworkExtension(); - $ext->load(['framework' => ['csrf_protection' => false, 'router' => ['resource' => 'dummy', 'utf8' => true]]], $container); + $ext->load(['framework' => ['http_method_override' => false, 'csrf_protection' => false, 'router' => ['resource' => 'dummy', 'utf8' => true]]], $container); $ext = new SecurityExtension(); $ext->load($config, $container); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 7d8384456cea8..9fc846575eb5f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -607,7 +607,7 @@ public function testDefaultAccessDecisionManagerStrategyIsAffirmative() { $container = $this->getContainer('access_decision_manager_default_strategy'); - $this->assertEquals((new Definition(AffirmativeStrategy::class, [false])), $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative'); + $this->assertEquals(new Definition(AffirmativeStrategy::class, [false]), $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative'); } public function testCustomAccessDecisionManagerService() @@ -630,7 +630,7 @@ public function testAccessDecisionManagerOptionsAreNotOverriddenByImplicitStrate $accessDecisionManagerDefinition = $container->getDefinition('security.access.decision_manager'); - $this->assertEquals((new Definition(AffirmativeStrategy::class, [true])), $accessDecisionManagerDefinition->getArgument(1)); + $this->assertEquals(new Definition(AffirmativeStrategy::class, [true]), $accessDecisionManagerDefinition->getArgument(1)); } public function testAccessDecisionManagerWithStrategyService() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php index ff4108d25cdc9..a0d9353b70483 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; class AbstractFactoryTest extends TestCase @@ -43,12 +44,19 @@ public function testDefaultFailureHandler($serviceId, $defaultHandlerInjection) $failureHandler = $this->container->getDefinition('security.authentication.failure_handler.foo.stub'); + $expectedFailureHandlerOptions = ['login_path' => '/bar']; $methodCalls = $failureHandler->getMethodCalls(); if ($defaultHandlerInjection) { $this->assertEquals('setOptions', $methodCalls[0][0]); - $this->assertEquals(['login_path' => '/bar'], $methodCalls[0][1][0]); + $this->assertEquals($expectedFailureHandlerOptions, $methodCalls[0][1][0]); } else { $this->assertCount(0, $methodCalls); + $this->assertInstanceOf(ChildDefinition::class, $failureHandler); + $this->assertEquals('security.authentication.custom_failure_handler', $failureHandler->getParent()); + $failureHandlerArguments = $failureHandler->getArguments(); + $this->assertInstanceOf(ChildDefinition::class, $failureHandlerArguments['index_0']); + $this->assertEquals($serviceId, $failureHandlerArguments['index_0']->getParent()); + $this->assertEquals($expectedFailureHandlerOptions, $failureHandlerArguments['index_1']); } } @@ -80,13 +88,22 @@ public function testDefaultSuccessHandler($serviceId, $defaultHandlerInjection) $successHandler = $this->container->getDefinition('security.authentication.success_handler.foo.stub'); $methodCalls = $successHandler->getMethodCalls(); + $expectedSuccessHandlerOptions = ['default_target_path' => '/bar']; + $expectedFirewallName = 'foo'; if ($defaultHandlerInjection) { $this->assertEquals('setOptions', $methodCalls[0][0]); - $this->assertEquals(['default_target_path' => '/bar'], $methodCalls[0][1][0]); + $this->assertEquals($expectedSuccessHandlerOptions, $methodCalls[0][1][0]); $this->assertEquals('setFirewallName', $methodCalls[1][0]); - $this->assertEquals(['foo'], $methodCalls[1][1]); + $this->assertEquals($expectedFirewallName, $methodCalls[1][1][0]); } else { $this->assertCount(0, $methodCalls); + $this->assertInstanceOf(ChildDefinition::class, $successHandler); + $this->assertEquals('security.authentication.custom_success_handler', $successHandler->getParent()); + $successHandlerArguments = $successHandler->getArguments(); + $this->assertInstanceOf(ChildDefinition::class, $successHandlerArguments['index_0']); + $this->assertEquals($serviceId, $successHandlerArguments['index_0']->getParent()); + $this->assertEquals($expectedSuccessHandlerOptions, $successHandlerArguments['index_1']); + $this->assertEquals($expectedFirewallName, $successHandlerArguments['index_2']); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index bb74850729a58..5323c16f3b2a1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -468,6 +468,46 @@ public function testCustomRememberMeHandler() $this->assertEquals([['firewall' => 'default']], $handler->getTag('security.remember_me_handler')); } + public function testSecretRememberMeHasher() + { + $container = $this->getRawContainer(); + + $container->register('custom_remember_me', \stdClass::class); + $container->loadFromExtension('security', [ + 'enable_authenticator_manager' => true, + 'firewalls' => [ + 'default' => [ + 'remember_me' => ['secret' => 'very'], + ], + ], + ]); + + $container->compile(); + + $handler = $container->getDefinition('security.authenticator.remember_me_signature_hasher.default'); + $this->assertSame('very', $handler->getArgument(2)); + } + + public function testSecretRememberMeHandler() + { + $container = $this->getRawContainer(); + + $container->register('custom_remember_me', \stdClass::class); + $container->loadFromExtension('security', [ + 'enable_authenticator_manager' => true, + 'firewalls' => [ + 'default' => [ + 'remember_me' => ['secret' => 'very', 'token_provider' => 'token_provider_id'], + ], + ], + ]); + + $container->compile(); + + $handler = $container->getDefinition('security.authenticator.remember_me_handler.default'); + $this->assertSame('very', $handler->getArgument(1)); + } + public function sessionConfigurationProvider() { return [ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php index 10eeb39ca8c5e..970a9dc9ae746 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php @@ -102,4 +102,38 @@ public function testMultipleFirewalls() $client->request('GET', '/firewall2/profile'); $this->assertResponseRedirects('http://localhost/login'); } + + public function testCustomSuccessHandler() + { + $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'custom_handlers.yml']); + + $client->request('POST', '/firewall1/login', [ + '_username' => 'jane@example.org', + '_password' => 'test', + ]); + $this->assertResponseRedirects('http://localhost/firewall1/test'); + + $client->request('POST', '/firewall1/dummy_login', [ + '_username' => 'jane@example.org', + '_password' => 'test', + ]); + $this->assertResponseRedirects('http://localhost/firewall1/dummy'); + } + + public function testCustomFailureHandler() + { + $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'custom_handlers.yml']); + + $client->request('POST', '/firewall1/login', [ + '_username' => 'jane@example.org', + '_password' => '', + ]); + $this->assertResponseRedirects('http://localhost/firewall1/login'); + + $client->request('POST', '/firewall1/dummy_login', [ + '_username' => 'jane@example.org', + '_password' => '', + ]); + $this->assertResponseRedirects('http://localhost/firewall1/dummy_login'); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/AuthenticatorBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/AuthenticatorBundle.php new file mode 100644 index 0000000000000..730974f17f169 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/AuthenticatorBundle.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle; + +use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class AuthenticatorBundle extends Bundle +{ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $this->configureSecurityExtension($container); + } + + private function configureSecurityExtension(ContainerBuilder $container): void + { + /** @var SecurityExtension $extension */ + $extension = $container->getExtension('security'); + + $extension->addAuthenticatorFactory(new DummyFormLoginFactory()); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/DummyFormLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/DummyFormLoginFactory.php new file mode 100644 index 0000000000000..fc728fe5c6f4e --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AuthenticatorBundle/DummyFormLoginFactory.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle; + +use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class DummyFormLoginFactory extends FormLoginFactory +{ + public function getKey(): string + { + return 'dummy_form_login'; + } + + public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string + { + $authenticatorId = 'security.authenticator.dummy_form_login.'.$firewallName; + $options = array_intersect_key($config, $this->options); + $authenticator = $container + ->setDefinition($authenticatorId, new ChildDefinition('security.authenticator.form_login')) + ->replaceArgument(1, new Reference($userProviderId)) + ->replaceArgument(2, new Reference($this->createAuthenticationSuccessHandler($container, $firewallName, $config))) + ->replaceArgument(3, new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config))) + ->replaceArgument(4, $options); + + if ($options['use_forward'] ?? false) { + $authenticator->addMethodCall('setHttpKernel', [new Reference('http_kernel')]); + } + + return $authenticatorId; + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/LoginLink/TestCustomLoginLinkSuccessHandler.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/LoginLink/TestCustomLoginLinkSuccessHandler.php index 0d1501508b58a..0cbc159ed4272 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/LoginLink/TestCustomLoginLinkSuccessHandler.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/LoginLink/TestCustomLoginLinkSuccessHandler.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\LoginLink; use Symfony\Component\HttpFoundation\JsonResponse; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/StaticTokenProvider.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/StaticTokenProvider.php index a51702eec15b6..24ff10a4d0199 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/StaticTokenProvider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/RememberMeBundle/Security/StaticTokenProvider.php @@ -49,11 +49,9 @@ public function updateToken(string $series, string $tokenValue, \DateTime $lastU $token = $this->loadTokenBySeries($series); $refl = new \ReflectionClass($token); $tokenValueProp = $refl->getProperty('tokenValue'); - $tokenValueProp->setAccessible(true); $tokenValueProp->setValue($token, $tokenValue); $lastUsedProp = $refl->getProperty('lastUsed'); - $lastUsedProp->setAccessible(true); $lastUsedProp->setValue($token, $lastUsed); self::$db[$series] = $token; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Controller/AdminController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Controller/AdminController.php index db494ed936cbd..f9e73b8970657 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Controller/AdminController.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Controller/AdminController.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\SecuredPageBundle\Controller; use Symfony\Component\DependencyInjection\ContainerAwareInterface; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/SecuredPageBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/SecuredPageBundle.php index 3c3c96592abb8..92d743d2c754e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/SecuredPageBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/SecuredPageBundle.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\SecuredPageBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Security/Core/User/ArrayUserProvider.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Security/Core/User/ArrayUserProvider.php index db9d39e7d6e74..68f896bcc68b1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Security/Core/User/ArrayUserProvider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/SecuredPageBundle/Security/Core/User/ArrayUserProvider.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\SecuredPageBundle\Security\Core\User; use Symfony\Bundle\SecurityBundle\Tests\Functional\UserWithoutEquatable; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php index ad2fc0c63d1e0..72a4b7bb1502b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php @@ -11,6 +11,12 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; + class CsrfFormLoginTest extends AbstractWebTestCase { /** @@ -20,6 +26,10 @@ public function testFormLoginAndLogoutWithCsrfTokens($options) { $client = $this->createClient($options); + $this->callInRequestContext($client, function () { + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); + }); + $form = $client->request('GET', '/login')->selectButton('login')->form(); $form['user_login[username]'] = 'johannes'; $form['user_login[password]'] = 'test'; @@ -40,6 +50,10 @@ public function testFormLoginAndLogoutWithCsrfTokens($options) $client->click($logoutLinks[0]); $this->assertRedirect($client->getResponse(), '/'); + + $this->callInRequestContext($client, function () { + $this->assertFalse(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + }); } /** @@ -49,6 +63,10 @@ public function testFormLoginWithInvalidCsrfToken($options) { $client = $this->createClient($options); + $this->callInRequestContext($client, function () { + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); + }); + $form = $client->request('GET', '/login')->selectButton('login')->form(); $form['user_login[_token]'] = ''; $client->submit($form); @@ -57,6 +75,10 @@ public function testFormLoginWithInvalidCsrfToken($options) $text = $client->followRedirect()->text(null, true); $this->assertStringContainsString('Invalid CSRF token.', $text); + + $this->callInRequestContext($client, function () { + $this->assertTrue(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + }); } /** @@ -105,4 +127,22 @@ public function provideClientOptions() yield [['test_case' => 'CsrfFormLogin', 'root_config' => 'config.yml']]; yield [['test_case' => 'CsrfFormLogin', 'root_config' => 'routes_as_path.yml']]; } + + private function callInRequestContext(KernelBrowser $client, callable $callable): void + { + /** @var EventDispatcherInterface $eventDispatcher */ + $eventDispatcher = static::getContainer()->get(EventDispatcherInterface::class); + $wrappedCallable = function (RequestEvent $event) use (&$callable) { + $callable(); + $event->setResponse(new Response('')); + $event->stopPropagation(); + }; + + $eventDispatcher->addListener(KernelEvents::REQUEST, $wrappedCallable); + try { + $client->request('GET', '/'.uniqid('', true)); + } finally { + $eventDispatcher->removeListener(KernelEvents::REQUEST, $wrappedCallable); + } + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php index 5da52d9602a49..3da73f20fccc5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php @@ -24,9 +24,6 @@ public function testCsrfTokensAreClearedOnLogout() { $client = $this->createClient(['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']); $client->disableReboot(); - $this->callInRequestContext($client, function () { - static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); - }); $client->request('POST', '/login', [ '_username' => 'johannes', @@ -34,8 +31,7 @@ public function testCsrfTokensAreClearedOnLogout() ]); $this->callInRequestContext($client, function () { - $this->assertTrue(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); - $this->assertSame('bar', static::getContainer()->get('security.csrf.token_storage')->getToken('foo')); + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); }); $client->request('GET', '/logout'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php index aae5f9282e546..0bd2711f25ca0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Functional; use Symfony\Component\HttpFoundation\ResponseHeaderBag; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php index d1e9eb7e0d36a..372700495208f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php @@ -12,4 +12,5 @@ return [ new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), + new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\AuthenticatorBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml index 9bf5d2aa8201f..a6adcfd0c775b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: test router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml", utf8: true } test: ~ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/custom_handlers.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/custom_handlers.yml new file mode 100644 index 0000000000000..96e9762d96833 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/custom_handlers.yml @@ -0,0 +1,34 @@ +imports: + - { resource: ./config.yml } + - { resource: ./security.yml } + +security: + enable_authenticator_manager: true + firewalls: + firewall1: + pattern: /firewall1 + provider: in_memory + entry_point: form_login + form_login: + check_path: /firewall1/login + success_handler: success_handler + failure_handler: failure_handler + default_target_path: /firewall1/test + login_path: /firewall1/login + dummy_form_login: + check_path: /firewall1/dummy_login + success_handler: success_handler + failure_handler: failure_handler + default_target_path: /firewall1/dummy + login_path: /firewall1/dummy_login + +services: + success_handler: + class: Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler + arguments: + - '@security.http_utils' + failure_handler: + class: Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler + arguments: + - '@http_kernel' + - '@security.http_utils' diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/routing.yml index 4796a3f6bc00c..76d894d9de904 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/routing.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/routing.yml @@ -22,6 +22,9 @@ security_custom_profile: firewall1_login: path: /firewall1/login +firewall_dummy_login: + path: /firewall1/dummy_login + firewall2_profile: path: /firewall2/profile defaults: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml index 758364eaed248..a613f5f24ca7e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: test router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml", utf8: true } validation: { enabled: true, enable_annotations: true } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml index 4a8cacb279b1f..2c80b9383bb28 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ./../config/framework.yml } framework: + http_method_override: false serializer: ~ security: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/legacy_config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/legacy_config.yml index d0d03c914c48f..022263a978e6d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/legacy_config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/legacy_config.yml @@ -2,6 +2,7 @@ imports: - { resource: ./../config/framework.yml } framework: + http_method_override: false serializer: ~ security: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMe/stateless_config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMe/stateless_config.yml index cf9102da35a08..31053f856373d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMe/stateless_config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMe/stateless_config.yml @@ -3,6 +3,7 @@ imports: - { resource: ./config_session.yml } framework: + http_method_override: false session: cookie_secure: auto cookie_samesite: lax diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeCookie/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeCookie/bundles.php index 8d4a02497947a..9a26fb163a77d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeCookie/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeCookie/bundles.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\SecurityBundle\SecurityBundle; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/login_throttling.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/login_throttling.yml index fa94d30dc00cc..5f22f41780cd0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/login_throttling.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/login_throttling.yml @@ -2,6 +2,7 @@ imports: - { resource: ./base_config.yml } framework: + http_method_override: false lock: ~ rate_limiter: ~ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml index 55186cd76bd3f..a86c944552644 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml @@ -1,4 +1,5 @@ framework: + http_method_override: false secret: test router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml", utf8: true } validation: { enabled: true, enable_annotations: true } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/UserAuthenticatorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/UserAuthenticatorTest.php index ecb9cd8e7e33d..95e275e26e383 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/UserAuthenticatorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/UserAuthenticatorTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bundle\SecurityBundle\Tests\Security; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 9f928c2c4fb57..17cb992d4c31b 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "composer-runtime-api": ">=2.1", "ext-xml": "*", "symfony/config": "^5.4|^6.0", @@ -27,10 +27,10 @@ "symfony/password-hasher": "^5.4|^6.0", "symfony/security-core": "^5.4|^6.0", "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^5.4|^6.0" + "symfony/security-http": "^5.4.20|~6.0.20|~6.1.12|^6.2.6" }, "require-dev": { - "doctrine/annotations": "^1.10.4", + "doctrine/annotations": "^1.10.4|^2", "symfony/asset": "^5.4|^6.0", "symfony/browser-kit": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 8bdf7748ff7d0..aaa0ae400f7a1 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +6.1 +--- + + * Add option `twig.file_name_pattern` to restrict which files are compiled by cache warmer and linter + * Deprecate option `twig.autoescape`, use `twig.autoescape_service[_method]` instead + 6.0 --- diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index cd55a6ecd26ff..63d0227513845 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -53,7 +53,7 @@ public function warmUp(string $cacheDir): array if (\is_callable([$template, 'unwrap'])) { $files[] = (new \ReflectionClass($template->unwrap()))->getFileName(); } - } catch (Error $e) { + } catch (Error) { /* * Problem during compilation, give up for this template (e.g. syntax errors). * Failing silently here allows to ignore templates that rely on functions that aren't available in diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index c9509c6582f82..5de2b2aad1358 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -13,7 +13,6 @@ use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand; use Symfony\Component\Console\Attribute\AsCommand; -use Symfony\Component\Finder\Finder; /** * Command that will validate your template syntax and output encountered errors. @@ -47,9 +46,7 @@ protected function configure() protected function findFiles(string $filename): iterable { if (str_starts_with($filename, '@')) { - $dir = $this->getApplication()->getKernel()->locateResource($filename); - - return Finder::create()->files()->in($dir)->name('*.twig'); + $filename = $this->getApplication()->getKernel()->locateResource($filename); } return parent::findFiles($filename); diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 12724e0f1cc65..6654fe08e11a9 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -69,6 +69,10 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.extension.routing')->addTag('twig.extension'); } + if ($container->has('html_sanitizer')) { + $container->getDefinition('twig.extension.htmlsanitizer')->addTag('twig.extension'); + } + if ($container->has('fragment.handler')) { $container->getDefinition('twig.extension.httpkernel')->addTag('twig.extension'); $container->getDefinition('twig.runtime.httpkernel')->addTag('twig.runtime'); diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index df688c5dd43ee..b85a3bf4b1958 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -127,7 +127,10 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode) $rootNode ->fixXmlConfig('path') ->children() - ->variableNode('autoescape')->defaultValue('name')->end() + ->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() @@ -141,6 +144,15 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode) ->info('The default path used to load templates') ->defaultValue('%kernel.project_dir%/templates') ->end() + ->arrayNode('file_name_pattern') + ->example('*.twig') + ->info('Pattern of file name used for cache warmer and linter') + ->beforeNormalization() + ->ifString() + ->then(function ($value) { return [$value]; }) + ->end() + ->prototype('scalar')->end() + ->end() ->arrayNode('paths') ->normalizeKeys(false) ->useAttributeAsKey('paths') diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php index 778d19f523942..7505c1fcd36fa 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php @@ -13,6 +13,7 @@ use Symfony\Bridge\Twig\UndefinedCallableHandler; use Twig\Environment; +use Twig\Extension\CoreExtension; // BC/FC with namespaced Twig class_exists(Environment::class); @@ -43,13 +44,13 @@ public function __construct(string $dateFormat, string $intervalFormat, ?string public function configure(Environment $environment) { - $environment->getExtension('Twig\Extension\CoreExtension')->setDateFormat($this->dateFormat, $this->intervalFormat); + $environment->getExtension(CoreExtension::class)->setDateFormat($this->dateFormat, $this->intervalFormat); if (null !== $this->timezone) { - $environment->getExtension('Twig\Extension\CoreExtension')->setTimezone($this->timezone); + $environment->getExtension(CoreExtension::class)->setTimezone($this->timezone); } - $environment->getExtension('Twig\Extension\CoreExtension')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); + $environment->getExtension(CoreExtension::class)->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); // wrap UndefinedCallableHandler in closures for lazy-autoloading $environment->registerUndefinedFilterCallback(function ($name) { return UndefinedCallableHandler::onUndefinedFilter($name); }); diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 2fb47d3746aef..f598524da4d64 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -17,10 +17,12 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\Form; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Translation\Translator; +use Symfony\Contracts\Service\ResetInterface; use Twig\Extension\ExtensionInterface; use Twig\Extension\RuntimeExtensionInterface; use Twig\Loader\LoaderInterface; @@ -40,6 +42,12 @@ public function load(array $configs, ContainerBuilder $container) if ($container::willBeAvailable('symfony/form', Form::class, ['symfony/twig-bundle'])) { $loader->load('form.php'); + + if (is_subclass_of(AbstractRendererEngine::class, ResetInterface::class)) { + $container->getDefinition('twig.form.engine')->addTag('kernel.reset', [ + 'method' => 'reset', + ]); + } } if ($container::willBeAvailable('symfony/console', Application::class, ['symfony/twig-bundle'])) { @@ -97,6 +105,12 @@ public function load(array $configs, ContainerBuilder $container) // paths are modified in ExtensionPass if forms are enabled $container->getDefinition('twig.template_iterator')->replaceArgument(1, $config['paths']); + $container->getDefinition('twig.template_iterator')->replaceArgument(3, $config['file_name_pattern']); + + if ($container->hasDefinition('twig.command.lint')) { + $container->getDefinition('twig.command.lint')->replaceArgument(1, $config['file_name_pattern'] ?: ['*.twig']); + } + foreach ($this->getBundleTemplatePaths($container, $config) as $name => $paths) { $namespace = $this->normalizeBundleName($name); foreach ($paths as $path) { diff --git a/src/Symfony/Bundle/TwigBundle/LICENSE b/src/Symfony/Bundle/TwigBundle/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bundle/TwigBundle/LICENSE +++ b/src/Symfony/Bundle/TwigBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.php b/src/Symfony/Bundle/TwigBundle/Resources/config/console.php index 0dc7ebdb7a5ad..b0303c3c24f09 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/console.php +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.php @@ -27,7 +27,7 @@ ->tag('console.command') ->set('twig.command.lint', LintCommand::class) - ->args([service('twig')]) + ->args([service('twig'), abstract_arg('File name pattern')]) ->tag('console.command') ; }; diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php index 2380d130b741b..5536315306b72 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php @@ -18,6 +18,7 @@ use Symfony\Bridge\Twig\Extension\AssetExtension; use Symfony\Bridge\Twig\Extension\CodeExtension; use Symfony\Bridge\Twig\Extension\ExpressionExtension; +use Symfony\Bridge\Twig\Extension\HtmlSanitizerExtension; use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; use Symfony\Bridge\Twig\Extension\HttpKernelExtension; use Symfony\Bridge\Twig\Extension\HttpKernelRuntime; @@ -75,7 +76,7 @@ ->call('setRequestStack', [service('request_stack')->ignoreOnInvalid()]) ->set('twig.template_iterator', TemplateIterator::class) - ->args([service('kernel'), abstract_arg('Twig paths'), param('twig.default_path')]) + ->args([service('kernel'), abstract_arg('Twig paths'), param('twig.default_path'), abstract_arg('File name pattern')]) ->set('twig.template_cache_warmer', TemplateCacheWarmer::class) ->args([service(ContainerInterface::class), service('twig.template_iterator')]) @@ -118,6 +119,9 @@ ->set('twig.extension.expression', ExpressionExtension::class) + ->set('twig.extension.htmlsanitizer', HtmlSanitizerExtension::class) + ->args([tagged_locator('html_sanitizer', 'sanitizer')]) + ->set('twig.extension.httpkernel', HttpKernelExtension::class) ->set('twig.runtime.httpkernel', HttpKernelRuntime::class) diff --git a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php index d8a7ad67d6d68..7242cfb0c5d44 100644 --- a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php +++ b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php @@ -29,16 +29,19 @@ class TemplateIterator implements \IteratorAggregate private \Traversable $templates; private array $paths; private ?string $defaultPath; + private array $namePatterns; /** - * @param array $paths Additional Twig paths to warm - * @param string|null $defaultPath The directory where global templates can be stored + * @param array $paths Additional Twig paths to warm + * @param string|null $defaultPath The directory where global templates can be stored + * @param string[] $namePatterns Pattern of file names */ - public function __construct(KernelInterface $kernel, array $paths = [], string $defaultPath = null) + public function __construct(KernelInterface $kernel, array $paths = [], string $defaultPath = null, array $namePatterns = []) { $this->kernel = $kernel; $this->paths = $paths; $this->defaultPath = $defaultPath; + $this->namePatterns = $namePatterns; } public function getIterator(): \Traversable @@ -82,7 +85,7 @@ private function findTemplatesInDirectory(string $dir, string $namespace = null, } $templates = []; - foreach (Finder::create()->files()->followLinks()->in($dir)->exclude($excludeDirs) as $file) { + foreach (Finder::create()->files()->followLinks()->in($dir)->exclude($excludeDirs)->name($this->namePatterns) as $file) { $templates[] = (null !== $namespace ? '@'.$namespace.'/' : '').str_replace('\\', '/', $file->getRelativePathname()); } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php index 8dd2be40960b1..9e7b500795ec6 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -11,7 +11,6 @@ 'bad' => ['key' => 'foo'], ], 'auto_reload' => true, - 'autoescape' => true, 'base_template_class' => 'stdClass', 'cache' => '/tmp', 'charset' => 'ISO-8859-1', diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/extra.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/extra.xml index 17bcf0acd4490..92767e411057f 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/extra.xml +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/extra.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd"> - + namespaced_path3 diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 8ece3b80b794d..3f7d1de266ec5 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd"> - + MyBundle::form.html.twig @@qux diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 24c10c23fe8f1..d186724539927 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -7,7 +7,6 @@ twig: pi: 3.14 bad: {key: foo} auto_reload: true - autoescape: true base_template_class: stdClass cache: /tmp charset: ISO-8859-1 diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 1cc9c0ebf3e5c..cd60cbb7fd9e3 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -82,7 +82,7 @@ public function testLoadFullConfiguration($format) // Twig options $options = $container->getDefinition('twig')->getArgument(1); $this->assertTrue($options['auto_reload'], '->load() sets the auto_reload option'); - $this->assertTrue($options['autoescape'], '->load() sets the autoescape option'); + $this->assertSame('name', $options['autoescape'], '->load() sets the autoescape option'); $this->assertEquals('stdClass', $options['base_template_class'], '->load() sets the base_template_class option'); $this->assertEquals('/tmp', $options['cache'], '->load() sets the cache option'); $this->assertEquals('ISO-8859-1', $options['charset'], '->load() sets the charset option'); @@ -225,7 +225,6 @@ public function testStopwatchExtensionAvailability($debug, $stopwatchEnabled, $e $tokenParsers = $container->get('test.twig.extension.debug.stopwatch')->getTokenParsers(); $stopwatchIsAvailable = new \ReflectionProperty($tokenParsers[0], 'stopwatchIsAvailable'); - $stopwatchIsAvailable->setAccessible(true); $this->assertSame($expected, $stopwatchIsAvailable->getValue($tokenParsers[0])); } @@ -297,19 +296,11 @@ private function loadFromFile(ContainerBuilder $container, $file, $format) { $locator = new FileLocator(__DIR__.'/Fixtures/'.$format); - switch ($format) { - case 'php': - $loader = new PhpFileLoader($container, $locator); - break; - case 'xml': - $loader = new XmlFileLoader($container, $locator); - break; - case 'yml': - $loader = new YamlFileLoader($container, $locator); - break; - default: - throw new \InvalidArgumentException(sprintf('Unsupported format: "%s"', $format)); - } + $loader = match ($format) { + 'php' => new PhpFileLoader($container, $locator), + 'xml' => new XmlFileLoader($container, $locator), + 'yml' => new YamlFileLoader($container, $locator), + }; $loader->load($file.'.'.$format); } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Fixtures/templates/Foo/not-twig.js b/src/Symfony/Bundle/TwigBundle/Tests/Fixtures/templates/Foo/not-twig.js new file mode 100644 index 0000000000000..ee120443f880d --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/Fixtures/templates/Foo/not-twig.js @@ -0,0 +1 @@ +/* Not Twig template */ diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php index b571d1cc76094..691430ead578b 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php @@ -64,6 +64,7 @@ public function registerContainerConfiguration(LoaderInterface $loader) $loader->load(function (ContainerBuilder $container) { $container ->loadFromExtension('framework', [ + 'http_method_override' => false, 'secret' => '$ecret', 'form' => ['enabled' => false], ]) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php b/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php index 0c6b02a707270..2ca3d80ae4e8c 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php @@ -19,15 +19,25 @@ class TemplateIteratorTest extends TestCase { public function testGetIterator() { - $bundle = $this->createMock(BundleInterface::class); - $bundle->expects($this->any())->method('getName')->willReturn('BarBundle'); - $bundle->expects($this->any())->method('getPath')->willReturn(__DIR__.'/Fixtures/templates/BarBundle'); + $iterator = new TemplateIterator($this->createKernelMock(), [__DIR__.'/Fixtures/templates/Foo' => 'Foo'], __DIR__.'/DependencyInjection/Fixtures/templates'); - $kernel = $this->createMock(Kernel::class); - $kernel->expects($this->any())->method('getBundles')->willReturn([ - $bundle, - ]); - $iterator = new TemplateIterator($kernel, [__DIR__.'/Fixtures/templates/Foo' => 'Foo'], __DIR__.'/DependencyInjection/Fixtures/templates'); + $sorted = iterator_to_array($iterator); + sort($sorted); + $this->assertEquals( + [ + '@Bar/index.html.twig', + '@Bar/layout.html.twig', + '@Foo/index.html.twig', + '@Foo/not-twig.js', + 'layout.html.twig', + ], + $sorted + ); + } + + public function testGetIteratorWithFileNameFilter() + { + $iterator = new TemplateIterator($this->createKernelMock(), [__DIR__.'/Fixtures/templates/Foo' => 'Foo'], __DIR__.'/DependencyInjection/Fixtures/templates', ['*.twig']); $sorted = iterator_to_array($iterator); sort($sorted); @@ -41,4 +51,18 @@ public function testGetIterator() $sorted ); } + + private function createKernelMock(): Kernel + { + $bundle = $this->createMock(BundleInterface::class); + $bundle->expects($this->any())->method('getName')->willReturn('BarBundle'); + $bundle->expects($this->any())->method('getPath')->willReturn(__DIR__.'/Fixtures/templates/BarBundle'); + + $kernel = $this->createMock(Kernel::class); + $kernel->expects($this->any())->method('getBundles')->willReturn([ + $bundle, + ]); + + return $kernel; + } } diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 9812d62afb0a9..b7c2c723bcc6f 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -16,9 +16,10 @@ } ], "require": { - "php": ">=8.0.2", + "php": ">=8.1", "composer-runtime-api": ">=2.1", "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", "symfony/twig-bridge": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", @@ -28,7 +29,6 @@ "require-dev": { "symfony/asset": "^5.4|^6.0", "symfony/stopwatch": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "symfony/form": "^5.4|^6.0", @@ -37,10 +37,9 @@ "symfony/yaml": "^5.4|^6.0", "symfony/framework-bundle": "^5.4|^6.0", "symfony/web-link": "^5.4|^6.0", - "doctrine/annotations": "^1.10.4" + "doctrine/annotations": "^1.10.4|^2" }, "conflict": { - "symfony/dependency-injection": "<5.4", "symfony/framework-bundle": "<5.4", "symfony/translation": "<5.4" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 6b73f21ec2b41..3cdec828217b5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -81,7 +81,7 @@ public function panelAction(Request $request, string $token): Response } if (!$profile = $this->profiler->loadProfile($token)) { - return new Response($this->twig->render('@WebProfiler/Profiler/info.html.twig', ['about' => 'no_token', 'token' => $token, 'request' => $request]), 200, ['Content-Type' => 'text/html']); + return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/info.html.twig', ['about' => 'no_token', 'token' => $token, 'request' => $request]); } if (null === $panel) { @@ -104,7 +104,7 @@ public function panelAction(Request $request, string $token): Response throw new NotFoundHttpException(sprintf('Panel "%s" is not available for token "%s".', $panel, $token)); } - return new Response($this->twig->render($this->getTemplateManager()->getName($profile, $panel), [ + return $this->renderWithCspNonces($request, $this->getTemplateManager()->getName($profile, $panel), [ 'token' => $token, 'profile' => $profile, 'collector' => $profile->getCollector($panel), @@ -114,7 +114,7 @@ public function panelAction(Request $request, string $token): Response 'templates' => $this->getTemplateManager()->getNames($profile), 'is_ajax' => $request->isXmlHttpRequest(), 'profiler_markup_version' => 2, // 1 = original profiler, 2 = Symfony 2.8+ profiler - ]), 200, ['Content-Type' => 'text/html']); + ]); } /** @@ -146,7 +146,7 @@ public function toolbarAction(Request $request, string $token = null): Response $url = null; try { $url = $this->generator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL); - } catch (\Exception $e) { + } catch (\Exception) { // the profiler is not enabled } @@ -232,7 +232,7 @@ public function searchResultsAction(Request $request, string $token): Response $end = $request->query->get('end', null); $limit = $request->query->get('limit'); - return new Response($this->twig->render('@WebProfiler/Profiler/results.html.twig', [ + return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/results.html.twig', [ 'request' => $request, 'token' => $token, 'profile' => $profile, @@ -245,7 +245,7 @@ public function searchResultsAction(Request $request, string $token): Response 'end' => $end, 'limit' => $limit, 'panel' => null, - ]), 200, ['Content-Type' => 'text/html']); + ]); } /** @@ -359,11 +359,11 @@ public function openAction(Request $request): Response throw new NotFoundHttpException(sprintf('The file "%s" cannot be opened.', $file)); } - return new Response($this->twig->render('@WebProfiler/Profiler/open.html.twig', [ + return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/open.html.twig', [ 'filename' => $filename, 'file' => $file, 'line' => $line, - ]), 200, ['Content-Type' => 'text/html']); + ]); } protected function getTemplateManager(): TemplateManager diff --git a/src/Symfony/Bundle/WebProfilerBundle/LICENSE b/src/Symfony/Bundle/WebProfilerBundle/LICENSE index 88bf75bb4d6a2..008370457251e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/LICENSE +++ b/src/Symfony/Bundle/WebProfilerBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2022 Fabien Potencier +Copyright (c) 2004-2023 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 diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/ajax.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/ajax.html.twig index e4e7d6418e24c..3e89707507ffc 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/ajax.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/ajax.html.twig @@ -2,7 +2,7 @@ {% block toolbar %} {% set icon %} - {{ include('@WebProfiler/Icon/ajax.svg') }} + {{ source('@WebProfiler/Icon/ajax.svg') }} 0 {% endset %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/cache.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/cache.html.twig index 0c406e9442c1e..b2f06be8c5f3b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/cache.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/cache.html.twig @@ -3,7 +3,7 @@ {% block toolbar %} {% if collector.totals.calls > 0 %} {% set icon %} - {{ include('@WebProfiler/Icon/cache.svg') }} + {{ source('@WebProfiler/Icon/cache.svg') }} {{ collector.totals.calls }} in @@ -37,7 +37,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/cache.svg') }} + {{ source('@WebProfiler/Icon/cache.svg') }} Cache diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig index 85182fea2aad5..5f8cf89b2225e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig @@ -20,7 +20,7 @@ {% set icon %} - {{ include('@WebProfiler/Icon/symfony.svg') }} + {{ source('@WebProfiler/Icon/symfony.svg') }} {{ collector.symfonyState is defined ? collector.symfonyversion : 'n/a' }} {% endset %} @@ -108,7 +108,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/config.svg') }} + {{ source('@WebProfiler/Icon/config.svg') }} Configuration {% endblock %} @@ -191,17 +191,17 @@
- {{ include('@WebProfiler/Icon/' ~ (collector.haszendopcache ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.haszendopcache ? 'yes' : 'no') ~ '.svg') }} OPcache
- {{ include('@WebProfiler/Icon/' ~ (collector.hasapcu ? 'yes' : 'no-gray') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.hasapcu ? 'yes' : 'no-gray') ~ '.svg') }} APCu
- {{ include('@WebProfiler/Icon/' ~ (collector.hasxdebug ? 'yes' : 'no-gray') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.hasxdebug ? 'yes' : 'no-gray') ~ '.svg') }} Xdebug
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig index c0be48a377032..af4f8b5e73ef0 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig @@ -4,7 +4,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/event.svg') }} + {{ source('@WebProfiler/Icon/event.svg') }} Events {% endblock %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.html.twig index 1fe0f5d470723..e27200d7abdf7 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.html.twig @@ -12,7 +12,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/exception.svg') }} + {{ source('@WebProfiler/Icon/exception.svg') }} Exception {% if collector.hasexception %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig index db97100e49b37..bde82228fa42d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig @@ -6,7 +6,7 @@ {% if collector.data.nb_errors > 0 or collector.data.forms|length %} {% set status_color = collector.data.nb_errors ? 'red' %} {% set icon %} - {{ include('@WebProfiler/Icon/form.svg') }} + {{ source('@WebProfiler/Icon/form.svg') }} {{ collector.data.nb_errors ?: collector.data.forms|length }} @@ -29,7 +29,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/form.svg') }} + {{ source('@WebProfiler/Icon/form.svg') }} Forms {% if collector.data.nb_errors > 0 %} @@ -90,7 +90,8 @@ cursor: pointer; padding: 5px 7px 5px 22px; position: relative; - + overflow: hidden; + text-overflow: ellipsis; } .tree .toggle-button { /* provide a bigger clickable area than just 10x10px */ @@ -449,7 +450,7 @@ {% import _self as tree %} {% set has_error = data.errors is defined and data.errors|length > 0 %}
  • -
    +
    {% if has_error %}
    {{ data.errors|length }}
    {% endif %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/http_client.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/http_client.html.twig index 8496ef186dfd6..f409a2dc03fde 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/http_client.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/http_client.html.twig @@ -3,7 +3,7 @@ {% block toolbar %} {% if collector.requestCount %} {% set icon %} - {{ include('@WebProfiler/Icon/http-client.svg') }} + {{ source('@WebProfiler/Icon/http-client.svg') }} {% set status_color = '' %} {{ collector.requestCount }} {% endset %} @@ -25,7 +25,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/http-client.svg') }} + {{ source('@WebProfiler/Icon/http-client.svg') }} HTTP Client {% if collector.requestCount %} @@ -94,6 +94,11 @@ Profile {% endif %} + {% if trace.curlCommand is not null %} + + + + {% endif %} @@ -110,7 +115,7 @@ {{ trace.http_code }} - + {{ profiler_dump(trace.info, maxDepth=1) }} {% if profiler_token and profiler_link %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig index 7b1a35b748dd7..c8f787c2a62d8 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig @@ -6,7 +6,7 @@ {% if collector.counterrors or collector.countdeprecations or collector.countwarnings %} {% set icon %} {% set status_color = collector.counterrors ? 'red' : collector.countwarnings ? 'yellow' : 'none' %} - {{ include('@WebProfiler/Icon/logger.svg') }} + {{ source('@WebProfiler/Icon/logger.svg') }} {{ collector.counterrors ?: (collector.countdeprecations + collector.countwarnings) }} {% endset %} @@ -33,7 +33,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/logger.svg') }} + {{ source('@WebProfiler/Icon/logger.svg') }} Logs {% if collector.counterrors or collector.countdeprecations or collector.countwarnings %} @@ -83,14 +83,14 @@
    - {{ include('@WebProfiler/Icon/filter.svg') }} + {{ source('@WebProfiler/Icon/filter.svg') }} Level ({{ filters.priority|length - 1 }})
    - Select All - Select None + +
    {% for label, value in filters.priority %} @@ -104,14 +104,14 @@
    - {{ include('@WebProfiler/Icon/filter.svg') }} + {{ source('@WebProfiler/Icon/filter.svg') }} Channel ({{ filters.channel|length - 1 }})
    - Select All - Select None + +
    {% for value in filters.channel %} @@ -155,6 +155,10 @@ {{ log.type|lower }} {% endif %} + {% else %} + + {{ log.priorityName|lower }} + {% endif %} @@ -204,7 +208,7 @@ {% set context_id = 'context-compiler-' ~ loop.index %} - {{ class }} +
      @@ -243,16 +247,12 @@ {% if has_context %} {% set context_id = 'context-' ~ category ~ '-' ~ log_index %} - Show context + {% endif %} {% if has_trace %} {% set trace_id = 'trace-' ~ category ~ '-' ~ log_index %} - Show trace - -
      - {{ profiler_dump(log.context.exception.trace, maxDepth=1) }} -
      + {% endif %} {% if has_context %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/mailer.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/mailer.html.twig index fd92f10e408b2..1b898ad5397ec 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/mailer.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/mailer.html.twig @@ -5,7 +5,7 @@ {% if events.messages|length %} {% set icon %} - {% include('@WebProfiler/Icon/mailer.svg') %} + {{ source('@WebProfiler/Icon/mailer.svg') }} {{ events.messages|length }} {% endset %} @@ -65,7 +65,7 @@ {% set events = collector.events %} - {{ include('@WebProfiler/Icon/mailer.svg') }} + {{ source('@WebProfiler/Icon/mailer.svg') }} E-mails {% if events.messages|length > 0 %} @@ -129,6 +129,13 @@ To
      {{ (message.headers.get('to').bodyAsString() ?? '(empty)')|replace({'To:': ''}) }}
      + + {% if event.envelope.recipients|length > 0 %} + Recipients + {% for recipient in event.envelope.recipients %} +
      {{ recipient.address }}
      + {% endfor %} + {% endif %}
    Headers diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig index 1336a57a23398..4688272ef27ad 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig @@ -3,7 +3,7 @@ {% block toolbar %} {% set icon %} {% set status_color = (collector.memory / 1024 / 1024) > 50 ? 'yellow' %} - {{ include('@WebProfiler/Icon/memory.svg') }} + {{ source('@WebProfiler/Icon/memory.svg') }} {{ '%.1f'|format(collector.memory / 1024 / 1024) }} MiB {% endset %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/messenger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/messenger.html.twig index b48aaa82e5787..0d0f11457f408 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/messenger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/messenger.html.twig @@ -6,7 +6,7 @@ {% if collector.messages|length > 0 %} {% set status_color = collector.exceptionsCount ? 'red' %} {% set icon %} - {{ include('@WebProfiler/Icon/messenger.svg') }} + {{ source('@WebProfiler/Icon/messenger.svg') }} {{ collector.messages|length }} {% endset %} @@ -31,7 +31,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/messenger.svg') }} + {{ source('@WebProfiler/Icon/messenger.svg') }} Messages {% if collector.exceptionsCount > 0 %} @@ -119,8 +119,8 @@ exception {% endif %} - {{ include('@WebProfiler/images/icon-minus-square.svg') }} - {{ include('@WebProfiler/images/icon-plus-square.svg') }} + {{ source('@WebProfiler/images/icon-minus-square.svg') }} + {{ source('@WebProfiler/images/icon-plus-square.svg') }} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/notifier.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/notifier.html.twig index dd17fab989a6b..5c77585d489a9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/notifier.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/notifier.html.twig @@ -5,7 +5,7 @@ {% if events.messages|length %} {% set icon %} - {% include('@WebProfiler/Icon/notifier.svg') %} + {{ source('@WebProfiler/Icon/notifier.svg') }} {{ events.messages|length }} {% endset %} @@ -68,7 +68,7 @@ {% set events = collector.events %} - {{ include('@WebProfiler/Icon/notifier.svg') }} + {{ source('@WebProfiler/Icon/notifier.svg') }} Notifications {% if events.messages|length > 0 %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig index 18311c169fece..ec15223b0bc26 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig @@ -24,8 +24,8 @@ {% set icon %} {{ collector.statuscode }} {% if collector.route %} - {% if collector.redirect %}{{ include('@WebProfiler/Icon/redirect.svg') }}{% endif %} - {% if collector.forwardtoken %}{{ include('@WebProfiler/Icon/forward.svg') }}{% endif %} + {% if collector.redirect %}{{ source('@WebProfiler/Icon/redirect.svg') }}{% endif %} + {% if collector.forwardtoken %}{{ source('@WebProfiler/Icon/forward.svg') }}{% endif %} {{ 'GET' != collector.method ? collector.method }} @ {{ collector.route }} {% endif %} @@ -99,7 +99,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/request.svg') }} + {{ source('@WebProfiler/Icon/request.svg') }} Request / Response {% endblock %} @@ -265,7 +265,7 @@
    - {{ include('@WebProfiler/Icon/' ~ (collector.statelesscheck ? 'yes' : 'no') ~ '.svg') }} + {{ source('@WebProfiler/Icon/' ~ (collector.statelesscheck ? 'yes' : 'no') ~ '.svg') }} Stateless check enabled
    diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/router.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/router.html.twig index a1449c2b272b2..f8f8dd8733a46 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/router.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/router.html.twig @@ -4,7 +4,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/router.svg') }} + {{ source('@WebProfiler/Icon/router.svg') }} Routing {% endblock %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/serializer.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/serializer.html.twig new file mode 100644 index 0000000000000..a3050a50996e0 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/serializer.html.twig @@ -0,0 +1,232 @@ +{% extends '@WebProfiler/Profiler/layout.html.twig' %} + +{% import _self as helper %} + +{% block menu %} + + {{ include('@WebProfiler/Icon/serializer.svg') }} + Serializer + +{% endblock %} + +{% block panel %} +

    Serializer

    + {% if not collector.handledCount %} +
    +

    Nothing was handled by the serializer for this request.

    +
    + {% else %} +
    +
    + {{ collector.handledCount }} + Handled +
    + +
    + {{ '%.2f'|format(collector.totalTime * 1000) }} ms + Total time +
    +
    + +
    + {{ helper.render_serialize_tab(collector.data, true) }} + {{ helper.render_serialize_tab(collector.data, false) }} + + {{ helper.render_normalize_tab(collector.data, true) }} + {{ helper.render_normalize_tab(collector.data, false) }} + + {{ helper.render_encode_tab(collector.data, true) }} + {{ helper.render_encode_tab(collector.data, false) }} +
    + {% endif %} +{% endblock %} + +{% macro render_serialize_tab(collectorData, serialize) %} + {% set data = serialize ? collectorData.serialize : collectorData.deserialize %} + {% set cellPrefix = serialize ? 'serialize' : 'deserialize' %} + +
    +

    {{ serialize ? 'serialize' : 'deserialize' }} {{ data|length }}

    +
    + {% if not data|length %} +
    +

    Nothing was {{ serialize ? 'serialized' : 'deserialized' }}.

    +
    + {% else %} + + + + + + + + + + + + {% for item in data %} + + + + + + + + {% endfor %} + +
    DataContextNormalizerEncoderTime
    {{ helper.render_data_cell(item, loop.index, cellPrefix) }}{{ helper.render_context_cell(item, loop.index, cellPrefix) }}{{ helper.render_normalizer_cell(item, loop.index, cellPrefix) }}{{ helper.render_encoder_cell(item, loop.index, cellPrefix) }}{{ helper.render_time_cell(item) }}
    + {% endif %} +
    +
    +{% endmacro %} + +{% macro render_normalize_tab(collectorData, normalize) %} + {% set data = normalize ? collectorData.normalize : collectorData.denormalize %} + {% set cellPrefix = normalize ? 'normalize' : 'denormalize' %} + +
    +

    {{ normalize ? 'normalize' : 'denormalize' }} {{ data|length }}

    +
    + {% if not data|length %} +
    +

    Nothing was {{ normalize ? 'normalized' : 'denormalized' }}.

    +
    + {% else %} + + + + + + + + + + + {% for item in data %} + + + + + + + {% endfor %} + +
    DataContextNormalizerTime
    {{ helper.render_data_cell(item, loop.index, cellPrefix) }}{{ helper.render_context_cell(item, loop.index, cellPrefix) }}{{ helper.render_normalizer_cell(item, loop.index, cellPrefix) }}{{ helper.render_time_cell(item) }}
    + {% endif %} +
    +
    +{% endmacro %} + +{% macro render_encode_tab(collectorData, encode) %} + {% set data = encode ? collectorData.encode : collectorData.decode %} + {% set cellPrefix = encode ? 'encode' : 'decode' %} + +
    +

    {{ encode ? 'encode' : 'decode' }} {{ data|length }}

    +
    + {% if not data|length %} +
    +

    Nothing was {{ encode ? 'encoded' : 'decoded' }}.

    +
    + {% else %} + + + + + + + + + + + {% for item in data %} + + + + + + + {% endfor %} + +
    DataContextEncoderTime
    {{ helper.render_data_cell(item, loop.index, cellPrefix) }}{{ helper.render_context_cell(item, loop.index, cellPrefix) }}{{ helper.render_encoder_cell(item, loop.index, cellPrefix) }}{{ helper.render_time_cell(item) }}
    + {% endif %} +
    +
    +{% endmacro %} + +{% macro render_data_cell(item, index, method) %} + {% set data_id = 'data-' ~ method ~ '-' ~ index %} + + {{ item.dataType }} + +
    + Show contents +
    + {{ profiler_dump(item.data) }} +
    +
    +{% endmacro %} + +{% macro render_context_cell(item, index, method) %} + {% set context_id = 'context-' ~ method ~ '-' ~ index %} + + {% if item.type %} + Type: {{ item.type }} +
    Format: {{ item.format ? item.format : 'none' }}
    + {% else %} + Format: {{ item.format ? item.format : 'none' }} + {% endif %} + +
    + Show context +
    + {{ profiler_dump(item.context) }} +
    +
    +{% endmacro %} + +{% macro render_normalizer_cell(item, index, method) %} + {% set nested_normalizers_id = 'nested-normalizers-' ~ method ~ '-' ~ index %} + + {% if item.normalizer is defined %} + {{ item.normalizer.class }} ({{ '%.2f'|format(item.normalizer.time * 1000) }} ms) + {% endif %} + + {% if item.normalization|length > 1 %} +
    + Show nested normalizers +
    +
      + {% for normalizer in item.normalization %} +
    • x{{ normalizer.calls }} {{ normalizer.class }} ({{ '%.2f'|format(normalizer.time * 1000) }} ms)
    • + {% endfor %} +
    +
    +
    + {% endif %} +{% endmacro %} + +{% macro render_encoder_cell(item, index, method) %} + {% set nested_encoders_id = 'nested-encoders-' ~ method ~ '-' ~ index %} + + {% if item.encoder is defined %} + {{ item.encoder.class }} ({{ '%.2f'|format(item.encoder.time * 1000) }} ms) + {% endif %} + + {% if item.encoding|length > 1 %} +
    + Show nested encoders +
    +
      + {% for encoder in item.encoding %} +
    • x{{ encoder.calls }} {{ encoder.class }} ({{ '%.2f'|format(encoder.time * 1000) }} ms)
    • + {% endfor %} +
    +
    +
    + {% endif %} +{% endmacro %} + +{% macro render_time_cell(item) %} + {{ '%.2f'|format(item.time * 1000) }} ms +{% endmacro %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index 0ed3ddc09b512..dbc32962310b2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -9,7 +9,7 @@ {% set status_color = has_time_events and collector.duration > 1000 ? 'yellow' %} {% set icon %} - {{ include('@WebProfiler/Icon/time.svg') }} + {{ source('@WebProfiler/Icon/time.svg') }} {{ total_time }} ms {% endset %} @@ -30,7 +30,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/time.svg') }} + {{ source('@WebProfiler/Icon/time.svg') }} Performance {% endblock %} @@ -144,10 +144,10 @@ {% endblock %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig index a8a5c273656b5..e468ce2e82fe3 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig @@ -5,7 +5,7 @@ {% block toolbar %} {% if collector.messages|length %} {% set icon %} - {{ include('@WebProfiler/Icon/translation.svg') }} + {{ source('@WebProfiler/Icon/translation.svg') }} {% set status_color = collector.countMissings ? 'red' : collector.countFallbacks ? 'yellow' %} {% set error_count = collector.countMissings + collector.countFallbacks %} {{ error_count ?: collector.countDefines }} @@ -44,7 +44,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/translation.svg') }} + {{ source('@WebProfiler/Icon/translation.svg') }} Translation {% if collector.countMissings or collector.countFallbacks %} {% set error_count = collector.countMissings + collector.countFallbacks %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig index be84c19b1717c..0210ca012fed3 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig @@ -3,7 +3,7 @@ {% block toolbar %} {% set time = collector.templatecount ? '%0.0f'|format(collector.time) : 'n/a' %} {% set icon %} - {{ include('@WebProfiler/Icon/twig.svg') }} + {{ source('@WebProfiler/Icon/twig.svg') }} {{ time }} ms {% endset %} @@ -32,7 +32,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/twig.svg') }} + {{ source('@WebProfiler/Icon/twig.svg') }} Twig {% endblock %} @@ -88,7 +88,7 @@ {%- set file = collector.templatePaths[template]|default(false) -%} {%- set link = file ? file|file_link(1) : false -%} - {{ include('@WebProfiler/Icon/twig.svg') }} + {{ source('@WebProfiler/Icon/twig.svg') }} {% if link %} {{ template }}
    diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig index f3b7b7656e87c..0bb3ecf37ef6c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig @@ -4,7 +4,7 @@ {% if collector.violationsCount > 0 or collector.calls|length %} {% set status_color = collector.violationsCount ? 'red' %} {% set icon %} - {{ include('@WebProfiler/Icon/validator.svg') }} + {{ source('@WebProfiler/Icon/validator.svg') }} {{ collector.violationsCount ?: collector.calls|length }} @@ -27,7 +27,7 @@ {% block menu %} - {{ include('@WebProfiler/Icon/validator.svg') }} + {{ source('@WebProfiler/Icon/validator.svg') }} Validator {% if collector.violationsCount > 0 %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/serializer.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/serializer.svg new file mode 100644 index 0000000000000..332ed031cec08 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/serializer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base.html.twig index 0850414d8c4af..1a74431d898b5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base.html.twig @@ -8,13 +8,13 @@ {% block head %} - {% endblock %} -