From 85989c3678d243e229f929008ede8b2e24c0c3fa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 29 Dec 2020 14:49:11 +0100 Subject: [PATCH 001/101] keep valid submitted choices when additional choices are submitted --- .../FrameworkBundle/Resources/config/form.xml | 1 + .../Form/Extension/Core/Type/ChoiceType.php | 78 +++++++++++++++---- .../Extension/Core/Type/ChoiceTypeTest.php | 25 +++--- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 17598fa95815c..05a58c4c4cd2c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -69,6 +69,7 @@ + diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 4297460d34f4f..bd2985b313137 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -28,6 +28,7 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; @@ -35,18 +36,29 @@ use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ChoiceType extends AbstractType { private $choiceListFactory; + private $translator; - public function __construct(ChoiceListFactoryInterface $choiceListFactory = null) + /** + * @param TranslatorInterface $translator + */ + public function __construct(ChoiceListFactoryInterface $choiceListFactory = null, $translator = null) { $this->choiceListFactory = $choiceListFactory ?: new CachingFactoryDecorator( new PropertyAccessDecorator( new DefaultChoiceListFactory() ) ); + + if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be an instance of "%s", "%s" given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } + $this->translator = $translator; } /** @@ -54,6 +66,7 @@ public function __construct(ChoiceListFactoryInterface $choiceListFactory = null */ public function buildForm(FormBuilderInterface $builder, array $options) { + $unknownValues = []; $choiceList = $this->createChoiceList($options); $builder->setAttribute('choice_list', $choiceList); @@ -81,10 +94,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) $this->addSubForms($builder, $choiceListView->preferredChoices, $options); $this->addSubForms($builder, $choiceListView->choices, $options); + } + if ($options['expanded'] || $options['multiple']) { // Make sure that scalar, submitted values are converted to arrays // which can be submitted to the checkboxes/radio buttons - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { + $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($choiceList, $options, &$unknownValues) { $form = $event->getForm(); $data = $event->getData(); @@ -99,6 +114,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Convert the submitted data to a string, if scalar, before // casting it to an array if (!\is_array($data)) { + if ($options['multiple']) { + throw new TransformationFailedException('Expected an array.'); + } + $data = (array) (string) $data; } @@ -110,17 +129,26 @@ public function buildForm(FormBuilderInterface $builder, array $options) $unknownValues = $valueMap; // Reconstruct the data as mapping from child names to values - $data = []; - - /** @var FormInterface $child */ - foreach ($form as $child) { - $value = $child->getConfig()->getOption('value'); - - // Add the value to $data with the child's name as key - if (isset($valueMap[$value])) { - $data[$child->getName()] = $value; - unset($unknownValues[$value]); - continue; + $knownValues = []; + + if ($options['expanded']) { + /** @var FormInterface $child */ + foreach ($form as $child) { + $value = $child->getConfig()->getOption('value'); + + // Add the value to $data with the child's name as key + if (isset($valueMap[$value])) { + $knownValues[$child->getName()] = $value; + unset($unknownValues[$value]); + continue; + } + } + } else { + foreach ($data as $value) { + if ($choiceList->getChoicesForValues([$value])) { + $knownValues[] = $value; + unset($unknownValues[$value]); + } } } @@ -128,16 +156,34 @@ public function buildForm(FormBuilderInterface $builder, array $options) // field exists for it or not unset($unknownValues['']); - // Throw exception if unknown values were submitted - if (\count($unknownValues) > 0) { + // Throw exception if unknown values were submitted (multiple choices will be handled in a different event listener below) + if (\count($unknownValues) > 0 && !$options['multiple']) { throw new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues)))); } - $event->setData($data); + $event->setData($knownValues); }); } if ($options['multiple']) { + $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use (&$unknownValues) { + // Throw exception if unknown values were submitted + if (\count($unknownValues) > 0) { + $form = $event->getForm(); + + $clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : \gettype($form->getViewData()); + $messageTemplate = 'The value {{ value }} is not valid.'; + + if (null !== $this->translator) { + $message = $this->translator->trans($messageTemplate, ['{{ value }}' => $clientDataAsString], 'validators'); + } else { + $message = strtr($messageTemplate, ['{{ value }}' => $clientDataAsString]); + } + + $form->addError(new FormError($message, $messageTemplate, ['{{ value }}' => $clientDataAsString], null, new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues)))))); + } + }); + // * @param array $fieldValues Use this syntax: ['my_form[name]' => '...', 'my_form[email]' => '...'] * @param string $method The HTTP method used to submit the form - * @param array $serverParameters These values override the ones stored in $_SERVER (HTTP headers must include a HTTP_ prefix as PHP does) + * @param array $serverParameters These values override the ones stored in $_SERVER (HTTP headers must include an HTTP_ prefix as PHP does) */ public function submitForm(string $button, array $fieldValues = [], string $method = 'POST', array $serverParameters = []): Crawler { @@ -352,7 +352,7 @@ public function submitForm(string $button, array $fieldValues = [], string $meth * @param string $uri The URI to fetch * @param array $parameters The Request parameters * @param array $files The files - * @param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does) + * @param array $server The server parameters (HTTP headers are referenced with an HTTP_ prefix as PHP does) * @param string $content The raw body data * @param bool $changeHistory Whether to update the history or not (only used internally for back(), forward(), and reload()) * diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php index 77d1664c74bde..8bd47407fa391 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php @@ -18,7 +18,7 @@ use Symfony\Component\Config\Definition\PrototypedArrayNode; /** - * Dumps a XML reference configuration for the given configuration/node instance. + * Dumps an XML reference configuration for the given configuration/node instance. * * @author Wouter J */ diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php index 5932472ec68a3..e67a2a8ed78ec 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php @@ -31,7 +31,7 @@ public function process(ContainerBuilder $container) } if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) { if ($definition instanceof ChildDefinition && !class_exists($id)) { - throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); + throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); } $definition->setClass($id); } diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php index 132849439e478..3d16ad6f01c24 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php @@ -26,7 +26,7 @@ trait BindTrait * injected in the matching parameters (of the constructor, of methods * called and of controller actions). * - * @param string $nameOrFqcn A parameter name with its "$" prefix, or a FQCN + * @param string $nameOrFqcn A parameter name with its "$" prefix, or an FQCN * @param mixed $valueOrRef The value or reference to bind * * @return $this diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 13d02ebb7c211..4b10acd9c53d8 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -386,7 +386,7 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa } /** - * Parses a XML file to a \DOMDocument. + * Parses an XML file to a \DOMDocument. * * @throws InvalidArgumentException When loading of XML file returns error */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php index 69b9a1c2d3848..89e5fa2ea2abd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php @@ -86,7 +86,7 @@ public function testClassFoundChildDefinition() public function testAmbiguousChildDefinition() { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Service definition "App\Foo\Child" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.'); + $this->expectExceptionMessage('Service definition "App\Foo\Child" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.'); $container = new ContainerBuilder(); $container->register('App\Foo', null); $container->setDefinition('App\Foo\Child', new ChildDefinition('App\Foo')); diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index 731eb99343bf4..083391a0bbab5 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -14,7 +14,7 @@ /** * ChoiceFormField represents a choice form field. * - * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs. + * It is constructed from an HTML select tag, or an HTML checkbox, or radio inputs. * * @author Fabien Potencier */ diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php index ec323179eb46a..3b2123bd96d85 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php @@ -26,7 +26,7 @@ class DateTimeToHtml5LocalDateTimeTransformer extends BaseDateTimeTransformer * Transforms a \DateTime into a local date and time string. * * According to the HTML standard, the input string of a datetime-local - * input is a RFC3339 date followed by 'T', followed by a RFC3339 time. + * input is an RFC3339 date followed by 'T', followed by an RFC3339 time. * https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string * * @param \DateTime|\DateTimeInterface $dateTime A DateTime object diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 8c96195485fbb..dec5bbf6aca54 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -213,7 +213,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; - // Change the input to a HTML5 datetime input if + // Change the input to an HTML5 datetime input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 // * the html5 is set to true diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index f6cca908140b1..0b9a4ffab3694 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -189,7 +189,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; - // Change the input to a HTML5 date input if + // Change the input to an HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 // * the html5 is set to true diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index 58af6f1d45d5b..44acf3efb4aba 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -220,7 +220,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'with_seconds' => $options['with_seconds'], ]); - // Change the input to a HTML5 time input if + // Change the input to an HTML5 time input if // * the widget is set to "single_text" // * the html5 is set to true if ($options['html5'] && 'single_text' === $options['widget']) { diff --git a/src/Symfony/Component/HttpFoundation/HeaderUtils.php b/src/Symfony/Component/HttpFoundation/HeaderUtils.php index fddf2512c4b59..2bf2d6844688d 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderUtils.php +++ b/src/Symfony/Component/HttpFoundation/HeaderUtils.php @@ -146,7 +146,7 @@ public static function unquote(string $s): string } /** - * Generates a HTTP Content-Disposition field-value. + * Generates an HTTP Content-Disposition field-value. * * @param string $disposition One of "inline" or "attachment" * @param string $filename A unicode string diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 079000e655ef5..aec9177e7ee05 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1716,7 +1716,7 @@ public function getAcceptableContentTypes() } /** - * Returns true if the request is a XMLHttpRequest. + * Returns true if the request is an XMLHttpRequest. * * It works if your JavaScript library sets an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index b90dfd645d796..c777283b66512 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -806,7 +806,7 @@ public function getQueryStringNormalizationData() ['bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'], ['foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'], - // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). + // GET parameters, that are submitted from an HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. ['baz=Foo%20Baz&bar=Foo+Bar', 'bar=Foo%20Bar&baz=Foo%20Baz', 'normalizes spaces in both encodings "%20" and "+"'], diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 15a37cf58b4d6..b335a4f2077de 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -205,7 +205,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } /** - * Gets a HTTP kernel from the container. + * Gets an HTTP kernel from the container. * * @return HttpKernelInterface */ diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php index 91b758e9ac888..87f68cf324bed 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php @@ -150,7 +150,7 @@ public function execute() } /** - * Returns a LDAP search resource. If this query resulted in multiple searches, only the first + * Returns an LDAP search resource. If this query resulted in multiple searches, only the first * page will be returned. * * @return resource diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index e65fa5e042d19..98c6454e3669d 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -366,7 +366,7 @@ private function getDriver(): string } /** - * Provides a SQL function to get the current timestamp regarding the current connection's driver. + * Provides an SQL function to get the current timestamp regarding the current connection's driver. */ private function getCurrentTimestampStatement(): string { diff --git a/src/Symfony/Component/Mime/Header/ParameterizedHeader.php b/src/Symfony/Component/Mime/Header/ParameterizedHeader.php index 1d167b43b1659..2c078d14c328c 100644 --- a/src/Symfony/Component/Mime/Header/ParameterizedHeader.php +++ b/src/Symfony/Component/Mime/Header/ParameterizedHeader.php @@ -102,7 +102,7 @@ protected function toTokens(string $string = null): array } /** - * Render a RFC 2047 compliant header parameter from the $name and $value. + * Render an RFC 2047 compliant header parameter from the $name and $value. */ private function createParameter(string $name, string $value): string { diff --git a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php index 6a2e0970f93f7..8c66b688a95c4 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php +++ b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php @@ -66,7 +66,7 @@ public function loginFail(Request $request, \Exception $exception = null); * although this is not recommended. * * Instead, implementations should typically look for a request parameter - * (such as a HTTP POST parameter) that indicates the browser has explicitly + * (such as an HTTP POST parameter) that indicates the browser has explicitly * requested for the authentication to be remembered. */ public function loginSuccess(Request $request, Response $response, TokenInterface $token); diff --git a/src/Symfony/Component/Security/Http/SecurityEvents.php b/src/Symfony/Component/Security/Http/SecurityEvents.php index fbef93d6197aa..efeeb0a86a194 100644 --- a/src/Symfony/Component/Security/Http/SecurityEvents.php +++ b/src/Symfony/Component/Security/Http/SecurityEvents.php @@ -18,7 +18,7 @@ final class SecurityEvents * into your website. It is important to distinguish this action from * non-interactive authentication methods, such as: * - authentication based on your session. - * - authentication using a HTTP basic or HTTP digest header. + * - authentication using an HTTP basic or HTTP digest header. * * @Event("Symfony\Component\Security\Http\Event\InteractiveLoginEvent") */ diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php index cd329e91c6619..7d33ca0c92a2b 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php @@ -106,7 +106,7 @@ public function getMappedClasses() } /** - * Parses a XML File. + * Parses an XML File. * * @throws MappingException */ diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php index e96effbcdb3bb..426635edb523c 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -53,11 +53,11 @@ public function __construct(string $name = null, callable $directoryIteratorProv protected function configure() { $this - ->setDescription('Lints a XLIFF file and outputs encountered errors') + ->setDescription('Lints an XLIFF file and outputs encountered errors') ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->setHelp(<<%command.name% command lints a XLIFF file and outputs to STDOUT +The %command.name% command lints an XLIFF file and outputs to STDOUT the first encountered syntax error. You can validates XLIFF contents passed from STDIN: diff --git a/src/Symfony/Component/Translation/Loader/MoFileLoader.php b/src/Symfony/Component/Translation/Loader/MoFileLoader.php index 1f2e62ced69ef..accd023ab50c6 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -19,19 +19,19 @@ class MoFileLoader extends FileLoader { /** - * Magic used for validating the format of a MO file as well as + * Magic used for validating the format of an MO file as well as * detecting if the machine used to create that file was little endian. */ public const MO_LITTLE_ENDIAN_MAGIC = 0x950412de; /** - * Magic used for validating the format of a MO file as well as + * Magic used for validating the format of an MO file as well as * detecting if the machine used to create that file was big endian. */ public const MO_BIG_ENDIAN_MAGIC = 0xde120495; /** - * The size of the header of a MO file in bytes. + * The size of the header of an MO file in bytes. */ public const MO_HEADER_SIZE = 28; diff --git a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php index d80d96ec3b5ce..85a9d0e433e51 100644 --- a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php +++ b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php @@ -14,7 +14,7 @@ use Psr\Link\LinkInterface; /** - * Serializes a list of Link instances to a HTTP Link header. + * Serializes a list of Link instances to an HTTP Link header. * * @see https://tools.ietf.org/html/rfc5988 * From 52f02e529ae867bf6e24d9225fe20cb0ba6c2b33 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 14 Feb 2021 19:19:55 +0100 Subject: [PATCH 048/101] [Console] Fix PHP 8.1 null error for preg_match flag Since PHP 8.1, null is no longer accepted as $flags, default integer `0` value should be used instead. --- src/Symfony/Component/Console/Input/StringInput.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Input/StringInput.php b/src/Symfony/Component/Console/Input/StringInput.php index 5032b340a188d..d43187d28171a 100644 --- a/src/Symfony/Component/Console/Input/StringInput.php +++ b/src/Symfony/Component/Console/Input/StringInput.php @@ -52,12 +52,12 @@ private function tokenize($input) $length = \strlen($input); $cursor = 0; while ($cursor < $length) { - if (preg_match('/\s+/A', $input, $match, null, $cursor)) { - } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { + if (preg_match('/\s+/A', $input, $match, 0, $cursor)) { + } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) { $tokens[] = $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, \strlen($match[3]) - 2))); - } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { + } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) { $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2)); - } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { + } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, 0, $cursor)) { $tokens[] = stripcslashes($match[1]); } else { // should never happen From 419e2206f43a7068d16f23027f90954b3b413f64 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 14 Feb 2021 19:51:53 +0100 Subject: [PATCH 049/101] Fix PHP 8.1 null values Both `stripos` and `preg_match` will no longer accept `null` on PHP >= 8.1 --- src/Symfony/Component/HttpFoundation/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index fb09d62c006d6..4ab97aaf90538 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -1237,7 +1237,7 @@ public static function closeOutputBuffers(int $targetLevel, bool $flush): void */ protected function ensureIEOverSSLCompatibility(Request $request): void { - if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) && true === $request->isSecure()) { + if (false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && true === $request->isSecure()) { if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { $this->headers->remove('Cache-Control'); } From 1572491a8ab32bfe3927302aaa36bd3e4ea9e059 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 13 Feb 2021 14:25:19 +0100 Subject: [PATCH 050/101] use the right context for properties defined in traits --- .../Extractor/PhpDocExtractor.php | 12 ++++++- .../Tests/Extractor/PhpDocExtractorTest.php | 20 ++++++++++++ .../Tests/Fixtures/TraitUsage/DummyTrait.php | 32 +++++++++++++++++++ .../Fixtures/TraitUsage/DummyUsedInTrait.php | 16 ++++++++++ .../Fixtures/TraitUsage/DummyUsingTrait.php | 17 ++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyTrait.php create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsedInTrait.php create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsingTrait.php diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 176a00a2f8105..a701a011c68a4 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -201,7 +201,17 @@ private function getDocBlockFromProperty(string $class, string $property): ?DocB } try { - return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflectionProperty->getDeclaringClass())); + $reflector = $reflectionProperty->getDeclaringClass(); + + foreach ($reflector->getTraits() as $trait) { + if ($trait->hasProperty($property)) { + $reflector = $trait; + + break; + } + } + + return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)); } catch (\InvalidArgumentException $e) { return null; } catch (\RuntimeException $e) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index d352fa12b61f0..bd3d5287c263d 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -16,6 +16,9 @@ use phpDocumentor\Reflection\Types\Collection; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait; +use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait; use Symfony\Component\PropertyInfo\Type; /** @@ -273,6 +276,23 @@ public function testDocBlockFallback($property, $types) $this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DockBlockFallback', $property)); } + /** + * @dataProvider propertiesDefinedByTraitsProvider + */ + public function testPropertiesDefinedByTraits(string $property, Type $type) + { + $this->assertEquals([$type], $this->extractor->getTypes(DummyUsingTrait::class, $property)); + } + + public function propertiesDefinedByTraitsProvider(): array + { + return [ + ['propertyInTraitPrimitiveType', new Type(Type::BUILTIN_TYPE_STRING)], + ['propertyInTraitObjectSameNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyUsedInTrait::class)], + ['propertyInTraitObjectDifferentNamespace', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], + ]; + } + protected function isPhpDocumentorV5() { if (class_exists(InvalidTag::class)) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyTrait.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyTrait.php new file mode 100644 index 0000000000000..6284ebf10567f --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyTrait.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\PropertyInfo\Tests\Fixtures\TraitUsage; + +use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; + +trait DummyTrait +{ + /** + * @var string + */ + private $propertyInTraitPrimitiveType; + + /** + * @var DummyUsedInTrait + */ + private $propertyInTraitObjectSameNamespace; + + /** + * @var Dummy + */ + private $propertyInTraitObjectDifferentNamespace; +} diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsedInTrait.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsedInTrait.php new file mode 100644 index 0000000000000..b887f6654e06c --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsedInTrait.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage; + +class DummyUsedInTrait +{ +} diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsingTrait.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsingTrait.php new file mode 100644 index 0000000000000..bfd75a36f41c1 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/TraitUsage/DummyUsingTrait.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage; + +class DummyUsingTrait +{ + use DummyTrait; +} From b596568db93938432dd846acd2576555e5792cd8 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 15 Feb 2021 15:36:09 +0100 Subject: [PATCH 051/101] [Workflow] Re-add InvalidTokenConfigurationException for BC --- .../InvalidTokenConfigurationException.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php new file mode 100644 index 0000000000000..a70fd4c98ddff --- /dev/null +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Exception; + +/** + * Thrown by GuardListener when there is no token set, but guards are placed on a transition. + * + * @author Matt Johnson + */ +class InvalidTokenConfigurationException extends LogicException +{ +} From d106aa3f2dae9bc68f37fd872e39a15bf9c8e2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Fri, 12 Feb 2021 20:06:23 +0100 Subject: [PATCH 052/101] [Translation] Allow using dashes in locale when linting Xliff files --- .../Translation/Command/XliffLintCommand.php | 4 ++-- .../Tests/Command/XliffLintCommandTest.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php index e96effbcdb3bb..78b1784c97a7a 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -129,12 +129,12 @@ private function validate(string $content, string $file = null): array $document->loadXML($content); if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) { - $normalizedLocale = preg_quote(str_replace('-', '_', $targetLanguage), '/'); + $normalizedLocalePattern = sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/')); // strict file names require translation files to be named '____.locale.xlf' // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed // also, the regexp matching must be case-insensitive, as defined for 'target-language' values // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language - $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocale) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocale, $normalizedLocale); + $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern); if (0 === preg_match($expectedFilenamePattern, basename($file))) { $errors[] = [ diff --git a/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php b/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php index 4a3351f6ecac0..c1c545a67fb87 100644 --- a/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php +++ b/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php @@ -105,6 +105,17 @@ public function testLintTargetLanguageIsCaseInsensitive() $this->assertStringContainsString('[OK] All 1 XLIFF files contain valid syntax.', trim($tester->getDisplay())); } + public function testLintSucceedsWhenLocaleInFileAndInTargetLanguageNameUsesDashesInsteadOfUnderscores() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('note', 'en-GB', 'messages.en-GB.xlf'); + + $tester->execute(['filename' => $filename], ['decorated' => false]); + + $this->assertSame(0, $tester->getStatusCode()); + $this->assertStringContainsString('[OK] All 1 XLIFF files contain valid syntax.', trim($tester->getDisplay())); + } + public function testLintFileNotReadable() { $this->expectException(\RuntimeException::class); From 93fe4a213e289fd8ae0ca21730d17522400d0d3f Mon Sep 17 00:00:00 2001 From: Tigran Azatyan Date: Sun, 20 Dec 2020 18:49:10 +0400 Subject: [PATCH 053/101] Symfony Armenian Translations --- .../Resources/translations/validators.hy.xlf | 6 +- .../Resources/translations/security.hy.xlf | 75 +++++++++++++++++++ .../Resources/translations/validators.hy.xlf | 58 +++++++++----- 3 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Resources/translations/security.hy.xlf diff --git a/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf b/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf index 7550cb1b5818e..bdba3fe81448f 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf @@ -4,15 +4,15 @@ This form should not contain extra fields. - Այս ձևը չպետք է պարունակի լրացուցիչ տողեր. + Այս ձևը չպետք է պարունակի լրացուցիչ տողեր։ The uploaded file was too large. Please try to upload a smaller file. - Վերբեռնված ֆայլը չափազանց մեծ է: Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ. + Վերբեռնված ֆայլը չափազանց մեծ է. Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ։ The CSRF token is invalid. Please try to resubmit the form. - CSRF արժեքը անթույլատրելի է: Փորձեք նորից ուղարկել ձևը. + CSRF արժեքը անթույլատրելի է. Փորձեք նորից ուղարկել ձևը։ diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.hy.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.hy.xlf new file mode 100644 index 0000000000000..da63a0047c664 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.hy.xlf @@ -0,0 +1,75 @@ + + + + + + An authentication exception occurred. + Նույնականացման սխալ։ + + + Authentication credentials could not be found. + Նույնականացման տվյալները չեն գտնվել։ + + + Authentication request could not be processed due to a system problem. + Համակարգային սխալ՝ նույնականացման հացրման պրոցեսինգի ժամանակ։ + + + Invalid credentials. + Սխալ մուտքային տվյալներ + + + Cookie has already been used by someone else. + Cookie-ն արդեն օգտագործվում է ուրիշի կողմից։ + + + Not privileged to request the resource. + Ռեսուրսի հարցման համար չկա թույլատվություն։ + + + Invalid CSRF token. + Անվավեր CSRF թոքեն։ + + + No authentication provider found to support the authentication token. + Նույնականացման ոչ մի մատակարար չի գտնվել, որ աջակցի նույնականացման թոքենը։ + + + No session available, it either timed out or cookies are not enabled. + No session available, it either timed out or cookies are not enabled. + + + No token could be found. + Թոքենը չի գտնվել։ + + + Username could not be found. + Օգտանունը չի գտնվել։ + + + Account has expired. + Հաշիվը ժամկետանց է։ + + + Credentials have expired. + Մուտքային տվյալները ժամկետանց են։ + + + Account is disabled. + Հաշիվը դեկատիվացված է։ + + + Account is locked. + Հաշիվն արգելափակված է։ + + + Too many failed login attempts, please try again later. + Չափից շատ մուտքի փորձեր, խնդրում ենք փորձել մի փոքր ուշ + + + Invalid or expired login link. + Անվավեր կամ ժամկետանց մուտքի հղում։ + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf index b005518f35875..8147e5a477f8a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf @@ -4,11 +4,11 @@ This value should be false. - Արժեքը պետք է լինի սխալ։ + Արժեքը պետք է լինի կեղծ։ This value should be true. - Արժեքը պետք է լինի ճիշտ։ + Արժեքը պետք է լինի իրական։ This value should be of type {{ type }}. @@ -204,15 +204,15 @@ This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - Այս հավաքածուն պետք է պաուրակի {{ limit }} կամ ավելի տարրեր։|Այս հավելվածը պետք է պարունակի limit }} տարր կամ ավելին։|Այս հավաքածուն պետք է պարունակի {{ limit }} տարրերին կամ ավելի։ + Այս համախումբը պետք է պաուրակի {{ limit }} կամ ավելի տարրեր։|Այս հավելվածը պետք է պարունակի limit }} տարր կամ ավելին։|Այս համախումբը պետք է պարունակի {{ limit }} տարրերին կամ ավելի։ This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարր կամ քիչ։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։ + Այս համախումբը պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։|Այս համախումբը պետք է պաուրակի {{ limit }} տարր կամ քիչ։|Այս համախումբը պետք է պաուրակի {{ limit }} տարրեր կամ քիչ։ This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. - Այս հավաքածուն պետք է պաուրակի ուղիղ {{ limit }} տարր։|Այս հավաքածուն պետք է պաուրակի ուղիղ {{ limit }} տարրեր։|Այս հավաքածուն պետք է պաուրակի {{ limit }} տարրեր։ + Այս համախումբը պետք է պաուրակի ուղիղ {{ limit }} տարր։|Այս համախումբը պետք է պաուրակի ուղիղ {{ limit }} տարրեր։|Այս համախումբը պետք է պաուրակի {{ limit }} տարրեր։ Invalid card number. @@ -304,11 +304,11 @@ The host could not be resolved. - Հոսթի անունը հնարավոր չի պարզել: + Հոսթի անունը հնարավոր չի պարզել։ This value does not match the expected {{ charset }} charset. - Արժեքը չի համընկնում {{ charset }} կոդավորման հետ: + Արժեքը չի համընկնում {{ charset }} կոդավորման հետ։ This is not a valid Business Identifier Code (BIC). @@ -320,51 +320,71 @@ This is not a valid UUID. - Սա վավեր UUID չէ: + Սա վավեր UUID չէ։ This value should be a multiple of {{ compared_value }}. - Այս արժեքը պետք է լինի բազմակի {{ compared_value }}. + Այս արժեքը պետք է լինի բազմակի {{ compared_value }}։ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. - Բիզնեսի նույնականացման կոդը (BIC) կապված չէ IBAN- ի հետ {{ iban }}. + Բիզնեսի նույնականացման կոդը (BIC) կապված չէ IBAN- ի հետ {{ iban }}։ This value should be valid JSON. - Այս արժեքը պետք է լինի վավեր JSON: + Այս արժեքը պետք է լինի վավեր JSON։ This collection should contain only unique elements. - Այս հավաքածուն պետք է պարունակի միայն եզակի տարրեր: + Այս համախումբը պետք է պարունակի միայն եզակի տարրեր։ This value should be positive. - Այս արժեքը պետք է լինի դրական: + Այս արժեքը պետք է լինի դրական։ This value should be either positive or zero. - Այս արժեքը պետք է լինի դրական կամ զրոյական: + Այս արժեքը պետք է լինի դրական կամ զրոյական։ This value should be negative. - Այս արժեքը պետք է լինի բացասական: + Այս արժեքը պետք է լինի բացասական։ This value should be either negative or zero. - Այս արժեքը պետք է լինի բացասական կամ զրոյական: + Այս արժեքը պետք է լինի բացասական կամ զրոյական։ This value is not a valid timezone. - Այս արժեքը վավեր ժամանակի գոտի չէ: + Այս արժեքը վավեր ժամային գոտի չէ։ This password has been leaked in a data breach, it must not be used. Please use another password. - Այս գաղտնաբառն արտահոսվել է տվյալների խախտման մեջ, այն չպետք է օգտագործվի: Խնդրում ենք օգտագործել մեկ այլ գաղտնաբառ: + Գաղտնաբառը գտնվել է տվյալների արտահոսքում. այն չպետք է օգտագործվի: Խնդրում ենք օգտագործել մեկ այլ գաղտնաբառ։ This value should be between {{ min }} and {{ max }}. - Այս արժեքը պետք է լինի միջև {{ min }} և {{ max }}. + Այս արժեքը պետք է լինի {{ min }}-ի և {{ max }}-ի միջև։ + + + This value is not a valid hostname. + Այս հոստի անունը վավեր չէ։ + + + The number of elements in this collection should be a multiple of {{ compared_value }}․ + Այս համախմբի տարրերի քանակը պետք է հավասար լինի {{ compared_value }}-ի բազմապատիկներին։ + + + This value should satisfy at least one of the following constraints: + Այս արժեքը պետք է բավարարի հետևյալ սահմանափակումներից առնվազն մեկը։ + + + Each element of this collection should satisfy its own set of constraints. + Այս համախմբի յուրաքանչյուր տարր պետք է բավարարի իր սեփական սահմանափակումները։ + + + This value is not a valid International Securities Identification Number (ISIN). + Այս արժեքը արժեթղթերի նույնականացման միջազգային համարը վավեր չէ(ISIN)։ From 8530ada94dff817e732755106c3e9b5af9aafe73 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 16 Feb 2021 10:34:30 +0100 Subject: [PATCH 054/101] Ignore indirect deprecation triggered by doctrine/orm --- .appveyor.yml | 1 + .travis.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 41d9c8d45d701..5077eea33d60a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,6 +12,7 @@ init: - SET SYMFONY_DEPRECATIONS_HELPER=strict - SET ANSICON=121x90 (121x90) - SET SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1 + - SET SYMFONY_DEPRECATIONS_HELPER=max[indirect]=170 - REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f install: diff --git a/.travis.yml b/.travis.yml index fb3910f44b1a6..98d1c8d4a82fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,7 @@ before_install: export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data" export COMPOSER_UP='composer update --no-progress --ansi' export COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n' | sort) + export SYMFONY_DEPRECATIONS_HELPER=max[indirect]=170 nanoseconds () { local cmd="date" From cc00e0eb7897ced1ac54e2f806a8228dcfa30277 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Tue, 16 Feb 2021 08:35:30 +0100 Subject: [PATCH 055/101] [String] Check if function exists before declaring it --- .../Component/String/Resources/functions.php | 32 +++++++++++-------- .../Translation/Resources/functions.php | 14 ++++---- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Component/String/Resources/functions.php b/src/Symfony/Component/String/Resources/functions.php index a60e2ce08c096..c950894f3934d 100644 --- a/src/Symfony/Component/String/Resources/functions.php +++ b/src/Symfony/Component/String/Resources/functions.php @@ -11,22 +11,28 @@ namespace Symfony\Component\String; -function u(?string $string = ''): UnicodeString -{ - return new UnicodeString($string ?? ''); +if (!\function_exists(u::class)) { + function u(?string $string = ''): UnicodeString + { + return new UnicodeString($string ?? ''); + } } -function b(?string $string = ''): ByteString -{ - return new ByteString($string ?? ''); +if (!\function_exists(b::class)) { + function b(?string $string = ''): ByteString + { + return new ByteString($string ?? ''); + } } -/** - * @return UnicodeString|ByteString - */ -function s(?string $string = ''): AbstractString -{ - $string = $string ?? ''; +if (!\function_exists(s::class)) { + /** + * @return UnicodeString|ByteString + */ + function s(?string $string = ''): AbstractString + { + $string = $string ?? ''; - return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); + return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); + } } diff --git a/src/Symfony/Component/Translation/Resources/functions.php b/src/Symfony/Component/Translation/Resources/functions.php index 7ce806b7d1301..901d2f87efcdd 100644 --- a/src/Symfony/Component/Translation/Resources/functions.php +++ b/src/Symfony/Component/Translation/Resources/functions.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Translation; -/** - * @author Nate Wiebe - */ -function t(string $message, array $parameters = [], string $domain = null): TranslatableMessage -{ - return new TranslatableMessage($message, $parameters, $domain); +if (!\function_exists(t::class)) { + /** + * @author Nate Wiebe + */ + function t(string $message, array $parameters = [], string $domain = null): TranslatableMessage + { + return new TranslatableMessage($message, $parameters, $domain); + } } From 7946be2b951612366b31a7b2c222cf2aa10a8e9b Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 16 Feb 2021 12:01:18 +0100 Subject: [PATCH 056/101] [WebLink] Escape double quotes in attributes values --- src/Symfony/Component/WebLink/HttpHeaderSerializer.php | 4 ++-- .../Component/WebLink/Tests/HttpHeaderSerializerTest.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php index 85a9d0e433e51..2ecdff0905f67 100644 --- a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php +++ b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php @@ -39,14 +39,14 @@ public function serialize(iterable $links): ?string foreach ($link->getAttributes() as $key => $value) { if (\is_array($value)) { foreach ($value as $v) { - $attributesParts[] = sprintf('%s="%s"', $key, $v); + $attributesParts[] = sprintf('%s="%s"', $key, preg_replace('/(?assertNull($this->serializer->serialize([])); } + + public function testSerializeDoubleQuotesInAttributeValue() + { + $this->assertSame('; rel="alternate"; title="\"escape me\" \"already escaped\" \"\"\""', $this->serializer->serialize([ + (new Link('alternate', '/foo')) + ->withAttribute('title', '"escape me" \"already escaped\" ""\"'), + ])); + } } From 0e421004eb97c82e87c9dc34cfdab43a1146f825 Mon Sep 17 00:00:00 2001 From: Yendric Date: Sun, 14 Feb 2021 23:09:09 +0100 Subject: [PATCH 057/101] [Console] fix QuestionHelper::getHiddenResponse() not working with space in project directory name --- src/Symfony/Component/Console/Helper/QuestionHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index e7ea0055598d4..d211fcfd1e6ec 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -412,7 +412,7 @@ private function getHiddenResponse(OutputInterface $output, $inputStream, bool $ $exe = $tmpExe; } - $sExec = shell_exec($exe); + $sExec = shell_exec('"'.$exe.'"'); $value = $trimmable ? rtrim($sExec) : $sExec; $output->writeln(''); From e9f2ece991f721813c2be7a5883425b68392bbda Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 16 Feb 2021 11:56:12 +0100 Subject: [PATCH 058/101] fix resolving parent/self/static type annotations --- .../Extractor/PhpDocExtractor.php | 22 +++++++++++- .../Tests/Extractor/PhpDocExtractorTest.php | 34 +++++++++++++++++++ .../Extractor/ReflectionExtractorTest.php | 28 ++++++++++----- .../PropertyInfo/Tests/Fixtures/Dummy.php | 5 +++ .../Tests/Fixtures/ParentDummy.php | 10 ++++++ .../PropertyInfo/Tests/Fixtures/Php7Dummy.php | 2 +- .../Tests/Fixtures/Php7ParentDummy.php | 19 +++++++++++ .../PropertyInfo/Util/PhpDocTypeHelper.php | 4 +++ 8 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7ParentDummy.php diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index a701a011c68a4..25446deb1e7ec 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -142,11 +142,31 @@ public function getTypes($class, $property, array $context = []): ?array break; } + $parentClass = null; $types = []; /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ foreach ($docBlock->getTagsByName($tag) as $tag) { if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) { - $types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType())); + foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) { + switch ($type->getClassName()) { + case 'self': + case 'static': + $resolvedClass = $class; + break; + + case 'parent': + if (false !== $resolvedClass = $parentClass ?? $parentClass = get_parent_class($class)) { + break; + } + // no break + + default: + $types[] = $type; + continue 2; + } + + $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyType(), $type->getCollectionValueType()); + } } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index bd3d5287c263d..4e3ff39257537 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -17,6 +17,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsedInTrait; use Symfony\Component\PropertyInfo\Tests\Fixtures\TraitUsage\DummyUsingTrait; use Symfony\Component\PropertyInfo\Type; @@ -120,6 +121,7 @@ public function typesProvider() ['staticGetter', null, null, null], ['staticSetter', null, null, null], ['emptyVar', null, $this->isPhpDocumentorV5() ? 'This should not be removed.' : null, null], + ['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null], ]; } @@ -293,6 +295,38 @@ public function propertiesDefinedByTraitsProvider(): array ]; } + /** + * @dataProvider propertiesStaticTypeProvider + */ + public function testPropertiesStaticType(string $class, string $property, Type $type) + { + $this->assertEquals([$type], $this->extractor->getTypes($class, $property)); + } + + public function propertiesStaticTypeProvider(): array + { + return [ + [ParentDummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)], + [Dummy::class, 'propertyTypeStatic', new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class)], + ]; + } + + /** + * @dataProvider propertiesParentTypeProvider + */ + public function testPropertiesParentType(string $class, string $property, ?array $types) + { + $this->assertEquals($types, $this->extractor->getTypes($class, $property)); + } + + public function propertiesParentTypeProvider(): array + { + return [ + [ParentDummy::class, 'parentAnnotationNoParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'parent')]], + [Dummy::class, 'parentAnnotation', [new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]], + ]; + } + protected function isPhpDocumentorV5() { if (class_exists(InvalidTag::class)) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index 0a4f21da05bb3..18f8d4d018f02 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -20,6 +20,8 @@ use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyExtended2; use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy; use Symfony\Component\PropertyInfo\Type; /** @@ -57,12 +59,15 @@ public function testGetProperties() 'iteratorCollection', 'iteratorCollectionWithKey', 'nestedIterators', + 'parentAnnotation', 'foo', 'foo2', 'foo3', 'foo4', 'foo5', 'files', + 'propertyTypeStatic', + 'parentAnnotationNoParent', 'a', 'DOB', 'Id', @@ -105,12 +110,15 @@ public function testGetPropertiesWithCustomPrefixes() 'iteratorCollection', 'iteratorCollectionWithKey', 'nestedIterators', + 'parentAnnotation', 'foo', 'foo2', 'foo3', 'foo4', 'foo5', 'files', + 'propertyTypeStatic', + 'parentAnnotationNoParent', 'date', 'c', 'd', @@ -143,12 +151,15 @@ public function testGetPropertiesWithNoPrefixes() 'iteratorCollection', 'iteratorCollectionWithKey', 'nestedIterators', + 'parentAnnotation', 'foo', 'foo2', 'foo3', 'foo4', 'foo5', 'files', + 'propertyTypeStatic', + 'parentAnnotationNoParent', ], $noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy') ); @@ -184,20 +195,21 @@ public function typesProvider() /** * @dataProvider php7TypesProvider */ - public function testExtractPhp7Type($property, array $type = null) + public function testExtractPhp7Type(string $class, string $property, array $type = null) { - $this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy', $property, [])); + $this->assertEquals($type, $this->extractor->getTypes($class, $property, [])); } public function php7TypesProvider() { return [ - ['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]], - ['bar', [new Type(Type::BUILTIN_TYPE_INT)]], - ['baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]], - ['buz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy')]], - ['biz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'stdClass')]], - ['donotexist', null], + [Php7Dummy::class, 'foo', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]], + [Php7Dummy::class, 'bar', [new Type(Type::BUILTIN_TYPE_INT)]], + [Php7Dummy::class, 'baz', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]], + [Php7Dummy::class, 'buz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy')]], + [Php7Dummy::class, 'biz', [new Type(Type::BUILTIN_TYPE_OBJECT, false, Php7ParentDummy::class)]], + [Php7Dummy::class, 'donotexist', null], + [Php7ParentDummy::class, 'parent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \stdClass::class)]], ]; } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index bcec074438948..420cdddae9768 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -130,6 +130,11 @@ class Dummy extends ParentDummy */ public $nestedIterators; + /** + * @var parent + */ + public $parentAnnotation; + public static function getStatic() { } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php index 8d5c4fe107162..d698983254d75 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php @@ -48,6 +48,16 @@ class ParentDummy */ public $files; + /** + * @var static + */ + public $propertyTypeStatic; + + /** + * @var parent + */ + public $parentAnnotationNoParent; + /** * @return bool|null */ diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php index 5dcb4c565e768..a6c2d5f147400 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php @@ -14,7 +14,7 @@ /** * @author Kévin Dunglas */ -class Php7Dummy extends \stdClass +class Php7Dummy extends Php7ParentDummy { public function getFoo(): array { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7ParentDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7ParentDummy.php new file mode 100644 index 0000000000000..69574a749bfbf --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7ParentDummy.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +class Php7ParentDummy extends \stdClass +{ + public function getParent(): parent + { + } +} diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index 06b7489201217..41edd3e197948 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -160,6 +160,10 @@ private function getPhpTypeAndClass(string $docType): array return [$docType, null]; } + if (\in_array($docType, ['parent', 'self', 'static'], true)) { + return ['object', $docType]; + } + return ['object', substr($docType, 1)]; } } From 32cd77aecc2b60b1e0df180cab6dca9a0b031652 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 16 Feb 2021 14:22:25 +0100 Subject: [PATCH 059/101] fix taking error message from the correct violation --- .../Constraints/AtLeastOneOfValidator.php | 2 +- .../Constraints/AtLeastOneOfValidatorTest.php | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/AtLeastOneOfValidator.php b/src/Symfony/Component/Validator/Constraints/AtLeastOneOfValidator.php index 740313c76e22a..95558519d8510 100644 --- a/src/Symfony/Component/Validator/Constraints/AtLeastOneOfValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AtLeastOneOfValidator.php @@ -48,7 +48,7 @@ public function validate($value, Constraint $constraint) if ($item instanceof All || $item instanceof Collection) { $message .= $constraint->messageCollection; } else { - $message .= $violations->get(0)->getMessage(); + $message .= $violations->get(\count($violations) - 1)->getMessage(); } $messages[] = $message; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfValidatorTest.php index b4fbab5575bab..6be6a5d6f702c 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfValidatorTest.php @@ -206,6 +206,35 @@ public function hasMetadataFor($classOrObject): bool $this->assertCount(0, $violations); } + + public function testEmbeddedMessageTakenFromFailingConstraint() + { + $validator = Validation::createValidatorBuilder() + ->setMetadataFactory(new class() implements MetadataFactoryInterface { + public function getMetadataFor($classOrObject): MetadataInterface + { + return (new ClassMetadata(Data::class)) + ->addPropertyConstraint('foo', new NotNull(['message' => 'custom message foo'])) + ->addPropertyConstraint('bar', new AtLeastOneOf([ + new NotNull(['message' => 'custom message bar']), + ])) + ; + } + + public function hasMetadataFor($classOrObject): bool + { + return Data::class === $classOrObject; + } + }) + ->getValidator() + ; + + $violations = $validator->validate(new Data(), new Valid()); + + $this->assertCount(2, $violations); + $this->assertSame('custom message foo', $violations->get(0)->getMessage()); + $this->assertSame('This value should satisfy at least one of the following constraints: [1] custom message bar', $violations->get(1)->getMessage()); + } } class ExpressionConstraintNested @@ -217,3 +246,9 @@ public function getFoobar(): string return 'bar'; } } + +class Data +{ + public $foo; + public $bar; +} From 3a231c2030c1147bb8e534a5d766f695011c125c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 17 Feb 2021 14:10:06 +0100 Subject: [PATCH 060/101] install compatible versions of mongodb/mongodb only --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 98d1c8d4a82fe..ee0c4c815974d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -255,7 +255,7 @@ install: fi phpenv global $PHP rm vendor/composer/package-versions-deprecated -Rf - ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb ^1.9.0) + ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb) tfold 'composer update' $COMPOSER_UP tfold 'phpunit install' ./phpunit install if [[ $deps = high ]]; then From a89ced8eacd3b29e27c00609f34bf57040de09c9 Mon Sep 17 00:00:00 2001 From: bahram Date: Sat, 13 Feb 2021 22:42:31 +0330 Subject: [PATCH 061/101] [Intl] fix Locale::getFallback() throwing exception on long $locale --- src/Symfony/Component/Intl/Locale.php | 3 ++- src/Symfony/Component/Intl/Tests/LocaleTest.php | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Intl/Locale.php b/src/Symfony/Component/Intl/Locale.php index 0373844e76c51..3d07e42b13baa 100644 --- a/src/Symfony/Component/Intl/Locale.php +++ b/src/Symfony/Component/Intl/Locale.php @@ -68,7 +68,8 @@ public static function getDefaultFallback(): ?string public static function getFallback(string $locale): ?string { if (\function_exists('locale_parse')) { - $localeSubTags = locale_parse($locale); + $localeSubTags = locale_parse($locale) ?? ['language' => $locale]; + if (1 === \count($localeSubTags)) { if ('root' !== self::$defaultFallback && self::$defaultFallback === $localeSubTags['language']) { return 'root'; diff --git a/src/Symfony/Component/Intl/Tests/LocaleTest.php b/src/Symfony/Component/Intl/Tests/LocaleTest.php index fd998612a7eae..fce214242a47a 100644 --- a/src/Symfony/Component/Intl/Tests/LocaleTest.php +++ b/src/Symfony/Component/Intl/Tests/LocaleTest.php @@ -70,4 +70,16 @@ public function testDefaultRootFallback() Locale::setDefaultFallback($prev); } + + /** + * @requires function locale_parse + */ + public function testLongLocaleFallback() + { + $locale = 'LC_TYPE=fr_FR.UTF-8;LC_NUMERIC=C;LC_TIME=fr_FR.UTF-8;LC_COLLATE=fr_FR.UTF-8;'. + 'LC_MONETARY=fr_FR.UTF-8;LC_MESSAGES=fr_FR.UTF-8;LC_PAPER=fr_FR.UTF-8;LC_NAME=fr_FR.UTF-8;'. + 'LC_ADDRESS=fr_FR.UTF-8;LC_TELEPHONE=fr_FR.UTF-8;LC_MEASUREMENT=fr_FR.UTF-8;LC_IDENTIFICATION=fr_FR.UTF-8'; + + $this->assertNull(Locale::getFallback($locale)); + } } From 251ce8f92489cfb49f9a15c1c793b1befad01dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Schlu=CC=88ter?= Date: Thu, 18 Feb 2021 11:52:56 +0100 Subject: [PATCH 062/101] Add different header notations to tests --- .../Component/BrowserKit/Tests/HttpBrowserTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Symfony/Component/BrowserKit/Tests/HttpBrowserTest.php b/src/Symfony/Component/BrowserKit/Tests/HttpBrowserTest.php index 4cd44aff70eef..8125d1a77c919 100644 --- a/src/Symfony/Component/BrowserKit/Tests/HttpBrowserTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/HttpBrowserTest.php @@ -63,6 +63,18 @@ public function validContentTypes() ['POST', 'http://example.com/', [], [], ['CONTENT_TYPE' => 'application/json'], '["content"]'], ['POST', 'http://example.com/', ['headers' => $defaultHeaders + ['content-type' => 'application/json'], 'body' => '["content"]', 'max_redirects' => 0]], ]; + yield 'custom header with HTTP_ prefix' => [ + ['PUT', 'http://example.com/', [], [], ['HTTP_CONTENT_TYPE' => 'application/json'], '["content"]'], + ['PUT', 'http://example.com/', ['headers' => $defaultHeaders + ['content-type' => 'application/json'], 'body' => '["content"]', 'max_redirects' => 0]], + ]; + yield 'modify notation of custom header with HTTP_ prefix' => [ + ['PUT', 'http://example.com/', [], [], ['HTTP_Content-Type' => 'application/json'], '["content"]'], + ['PUT', 'http://example.com/', ['headers' => $defaultHeaders + ['content-type' => 'application/json'], 'body' => '["content"]', 'max_redirects' => 0]], + ]; + yield 'modify notation of custom header' => [ + ['PUT', 'http://example.com/', [], [], ['Content-Type' => 'application/json'], '["content"]'], + ['PUT', 'http://example.com/', ['headers' => $defaultHeaders + ['content-type' => 'application/json'], 'body' => '["content"]', 'max_redirects' => 0]], + ]; } public function testMultiPartRequestWithSingleFile() From ad6007299813b5449b89545ea2c4170a46051653 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 Feb 2021 18:12:37 +0100 Subject: [PATCH 063/101] [EventDispatcher] fix registering subscribers twice on edge-case --- .../DependencyInjection/RegisterListenersPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 6a333c97d3b00..4b236a5b439b7 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -149,7 +149,7 @@ public function process(ContainerBuilder $container) continue; } - $dispatcherDefinitions[] = $container->getDefinition($attributes['dispatcher']); + $dispatcherDefinitions[$attributes['dispatcher']] = $container->getDefinition($attributes['dispatcher']); } if (!$dispatcherDefinitions) { From 15f021f825b6f6affbe6720a7ea61a99486d3c8a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 Feb 2021 23:23:29 +0100 Subject: [PATCH 064/101] Stop using deprecated ArrayCache from Doctrine --- .../Bridge/Doctrine/Test/DoctrineTestHelper.php | 3 --- .../DependencyInjection/FrameworkExtension.php | 4 ++-- .../Resources/config/annotations.xml | 14 ++++++++++++-- .../DependencyInjection/FrameworkExtensionTest.php | 2 +- .../Component/Validator/ValidatorBuilder.php | 11 +++++++++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php b/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php index 2ad16dcd4de24..d3d25c17b275d 100644 --- a/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php +++ b/src/Symfony/Bridge/Doctrine/Test/DoctrineTestHelper.php @@ -12,7 +12,6 @@ namespace Symfony\Bridge\Doctrine\Test; use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Cache\ArrayCache; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; @@ -62,8 +61,6 @@ public static function createTestConfiguration() $config->setProxyDir(sys_get_temp_dir()); $config->setProxyNamespace('SymfonyTests\Doctrine'); $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); - $config->setQueryCacheImpl(new ArrayCache()); - $config->setMetadataCacheImpl(new ArrayCache()); return $config; } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 31a3f58b0bc34..9d46e259fd263 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1447,8 +1447,8 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde } $container - ->getDefinition('annotations.filesystem_cache') - ->replaceArgument(0, $cacheDir) + ->getDefinition('annotations.filesystem_cache_adapter') + ->replaceArgument(2, $cacheDir) ; $cacheService = 'annotations.filesystem_cache'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index 69947a35f8df4..2e56f1deb62f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -24,15 +24,25 @@ - + + + + + - + + + 0 + + + + %kernel.cache_dir%/annotations.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 7bc3edbfb859f..db26edcfedebf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -997,7 +997,7 @@ public function testAnnotations() $container->addCompilerPass(new TestAnnotationsPass()); $container->compile(); - $this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.filesystem_cache')->getArgument(0)); + $this->assertEquals($container->getParameter('kernel.cache_dir').'/annotations', $container->getDefinition('annotations.filesystem_cache_adapter')->getArgument(2)); $this->assertSame('annotations.filesystem_cache', (string) $container->getDefinition('annotation_reader')->getArgument(1)); } diff --git a/src/Symfony/Component/Validator/ValidatorBuilder.php b/src/Symfony/Component/Validator/ValidatorBuilder.php index 17e4fbd02490e..87267a45ac04b 100644 --- a/src/Symfony/Component/Validator/ValidatorBuilder.php +++ b/src/Symfony/Component/Validator/ValidatorBuilder.php @@ -15,7 +15,10 @@ use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Cache\ArrayCache; +use Doctrine\Common\Cache\CacheProvider; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\DoctrineProvider; use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; use Symfony\Component\Validator\Context\ExecutionContextFactory; use Symfony\Component\Validator\Exception\LogicException; @@ -197,11 +200,15 @@ public function enableAnnotationMapping(Reader $annotationReader = null) } if (null === $annotationReader) { - if (!class_exists(AnnotationReader::class) || !class_exists(ArrayCache::class)) { + if (!class_exists(AnnotationReader::class) || !class_exists(CacheProvider::class)) { throw new LogicException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.'); } - $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); + if (class_exists(ArrayAdapter::class)) { + $annotationReader = new CachedReader(new AnnotationReader(), new DoctrineProvider(new ArrayAdapter())); + } else { + $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); + } } $this->annotationReader = $annotationReader; From 279e71f5f36fc43e2d01cc25723da76822f49ce3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 19 Feb 2021 00:01:52 +0100 Subject: [PATCH 065/101] [VarDumper] relax test case --- .../Tests/Caster/RdKafkaCasterTest.php | 68 +------------------ 1 file changed, 1 insertion(+), 67 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php index 6b449b367c3e4..24b8f4288e15e 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php @@ -56,75 +56,9 @@ public function testDumpConf() $expectedDump = << Date: Fri, 19 Feb 2021 00:03:02 +0100 Subject: [PATCH 066/101] [VarDumper] relax test case --- .../Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php index 24b8f4288e15e..f68d2bb7135fd 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php @@ -114,7 +114,7 @@ public function testDumpTopicConf() $expectedDump = << Date: Fri, 19 Feb 2021 00:11:19 +0100 Subject: [PATCH 067/101] [VarDumper] relax test case --- .../Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php index f68d2bb7135fd..48db493396500 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php @@ -114,7 +114,7 @@ public function testDumpTopicConf() $expectedDump = << Date: Fri, 19 Feb 2021 10:48:50 +0100 Subject: [PATCH 068/101] cs fix --- .../Compiler/ResolveInstanceofConditionalsPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 92b48ed888946..37ad34954d3a4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -76,7 +76,7 @@ private function processDefinition(ContainerBuilder $container, string $id, Defi $reflectionClass = null; foreach ($conditionals as $interface => $instanceofDefs) { - if ($interface !== $class && !(null === $reflectionClass ? $reflectionClass = ($container->getReflectionClass($class, false) ?: false) : $reflectionClass)) { + if ($interface !== $class && !($reflectionClass ?? $reflectionClass = $container->getReflectionClass($class, false) ?: false)) { continue; } From d1c3e21effe4c8329bc904a51e6a689b4da12e9e Mon Sep 17 00:00:00 2001 From: Erik Saunier Date: Wed, 17 Feb 2021 14:06:36 +0100 Subject: [PATCH 069/101] Add Symfony Armenian Translations --- .../Resources/translations/validators.hy.xlf | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf b/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf index bdba3fe81448f..10ac326fb1600 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.hy.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF արժեքը անթույլատրելի է. Փորձեք նորից ուղարկել ձևը։ + + This value is not a valid HTML5 color. + Այս արժեքը վավեր HTML5 գույն չէ։ + + + Please enter a valid birthdate. + Խնդրում ենք մուտքագրել վավեր ծննդյան ամսաթիվ։ + + + The selected choice is invalid. + Ընտրված ընտրությունն անվավեր է։ + + + The collection is invalid. + Համախումբն անվավեր է։ + + + Please select a valid color. + Խնդրում ենք ընտրել վավեր գույն։ + + + Please select a valid country. + Խնդրում ենք ընտրել վավեր երկիր։ + + + Please select a valid currency. + Խնդրում ենք ընտրել վավեր արժույթ։ + + + Please choose a valid date interval. + Խնդրում ենք ընտրել ճիշտ ամսաթվերի միջակայք։ + + + Please enter a valid date and time. + Խնդրում ենք մուտքագրել վավեր ամսաթիվ և ժամ։ + + + Please enter a valid date. + Խնդրում ենք մուտքագրել վավեր ամսաթիվ։ + + + Please select a valid file. + Խնդրում ենք ընտրել վավեր ֆայլ։ + + + The hidden field is invalid. + Թաքնված դաշտը անվավեր է։ + + + Please enter an integer. + Խնդրում ենք մուտքագրել ամբողջ թիվ։ + + + Please select a valid language. + Խնդրում ենք ընտրել վավեր լեզու։ + + + Please select a valid locale. + Խնդրում ենք ընտրել վավեր տեղայնացում։ + + + Please enter a valid money amount. + Խնդրում ենք մուտքագրել վավեր գումար։ + + + Please enter a number. + Խնդրում ենք մուտքագրել համար։ + + + The password is invalid. + Գաղտնաբառն անվավեր է։ + + + Please enter a percentage value. + Խնդրում ենք մուտքագրել տոկոսային արժեք։ + + + The values do not match. + Արժեքները չեն համընկնում։ + + + Please enter a valid time. + Մուտքագրեք վավեր ժամանակ։ + + + Please select a valid timezone. + Խնդրում ենք ընտրել վավեր ժամային գոտի։ + + + Please enter a valid URL. + Խնդրում ենք մուտքագրել վավեր URL։ + + + Please enter a valid search term. + Խնդրում ենք մուտքագրել վավեր որոնման տերմին։ + + + Please provide a valid phone number. + Խնդրում ենք տրամադրել վավեր հեռախոսահամար։ + + + The checkbox has an invalid value. + Նշման վանդակը անվավեր արժեք ունի։ + + + Please enter a valid email address. + Խնդրում ենք մուտքագրել վավեր էլ-հասցե։ + + + Please select a valid option. + Խնդրում ենք ընտրել ճիշտ տարբերակ։ + + + Please select a valid range. + Խնդրում ենք ընտրել վավեր տիրույթ։ + + + Please enter a valid week. + Մուտքագրեք վավեր շաբաթ։ + From e4911554e38968b2cc30ba2c87414b077869e08e Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 19 Feb 2021 17:17:21 -0500 Subject: [PATCH 070/101] [Form] Ignoring invalid forms from delete_empty behavior in CollectionType --- .../Core/EventListener/ResizeFormListener.php | 4 ++++ .../EventListener/ResizeFormListenerTest.php | 6 ++--- .../Core/Type/CollectionTypeTest.php | 23 +++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index d978117552d90..813456b95e2a6 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -132,6 +132,10 @@ public function onSubmit(FormEvent $event) $previousData = $form->getData(); /** @var FormInterface $child */ foreach ($form as $name => $child) { + if (!$child->isValid() || !$child->isSynchronized()) { + continue; + } + $isNew = !isset($previousData[$name]); $isEmpty = \is_callable($this->deleteEmpty) ? ($this->deleteEmpty)($child->getData()) : $child->isEmpty(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 5e0fc84f02d70..ac59919e7fec7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -255,7 +255,7 @@ public function testOnSubmitDeleteEmptyNotCompoundEntriesIfAllowDelete() $data = [0 => 'first', 1 => '']; foreach ($data as $child => $dat) { - $this->form->get($child)->setData($dat); + $this->form->get($child)->submit($dat); } $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', [], false, true, true); @@ -282,11 +282,11 @@ public function testOnSubmitDeleteEmptyCompoundEntriesIfAllowDelete() $data = ['0' => ['name' => 'John'], '1' => ['name' => '']]; foreach ($data as $child => $dat) { - $this->form->get($child)->setData($dat); + $this->form->get($child)->submit($dat); } $event = new FormEvent($this->form, $data); $callback = function ($data) { - return '' === $data['name']; + return null === $data['name']; }; $listener = new ResizeFormListener('text', [], false, true, $callback); $listener->onSubmit($event); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php index e98a0c17443f1..b66ca07488578 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Form; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\AuthorType; @@ -211,6 +212,28 @@ public function testResizedDownIfSubmittedWithCompoundEmptyDataAndDeleteEmpty() $this->assertEquals([new Author('s_first', 's_last')], $form->getData()); } + public function testNotDeleteEmptyIfInvalid() + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'entry_type' => ChoiceType::class, + 'entry_options' => [ + 'choices' => ['a', 'b'], + ], + 'allow_add' => true, + 'allow_delete' => true, + 'delete_empty' => true, + ]); + + $form->submit(['a', 'x', '']); + + $this->assertSame(['a'], $form->getData()); + $this->assertCount(2, $form); + $this->assertTrue($form->has('1')); + $this->assertFalse($form[1]->isValid()); + $this->assertNull($form[1]->getData()); + $this->assertSame('x', $form[1]->getViewData()); + } + public function testNotResizedIfSubmittedWithExtraData() { $form = $this->factory->create(static::TESTED_TYPE, null, [ From 9bb4b3106d33c58e7954c4757a34169629c97c2c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 22 Feb 2021 12:06:44 +0100 Subject: [PATCH 071/101] [Cache] fix setting items' metadata on commit() --- .../Component/Cache/Adapter/AbstractTagAwareAdapter.php | 1 + src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php | 1 + .../Cache/Tests/Adapter/FilesystemTagAwareAdapterTest.php | 1 - src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php | 1 - .../Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php | 1 - .../Cache/Tests/{Traits => Adapter}/PdoPruneableTrait.php | 2 +- .../Cache/Tests/Adapter/PredisTagAwareAdapterTest.php | 1 - .../Cache/Tests/Adapter/PredisTagAwareClusterAdapterTest.php | 1 - .../Cache/Tests/Adapter/RedisTagAwareAdapterTest.php | 1 - .../Cache/Tests/Adapter/RedisTagAwareArrayAdapterTest.php | 1 - .../Cache/Tests/Adapter/RedisTagAwareClusterAdapterTest.php | 1 - .../Component/Cache/Tests/Adapter/TagAwareAdapterTest.php | 1 - .../Cache/Tests/{Traits => Adapter}/TagAwareTestTrait.php | 4 +++- src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php | 2 +- src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php | 2 +- 15 files changed, 8 insertions(+), 13 deletions(-) rename src/Symfony/Component/Cache/Tests/{Traits => Adapter}/PdoPruneableTrait.php (95%) rename src/Symfony/Component/Cache/Tests/{Traits => Adapter}/TagAwareTestTrait.php (96%) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php index d5c6aae572bb4..106d8821b862c 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php @@ -110,6 +110,7 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix, $defaultLifet } $byLifetime[$ttl][$getId($key)] = $value; + $item->metadata = $item->newMetadata; } return $byLifetime; diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 9d5fefa4fb40b..9a37596865e6c 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -83,6 +83,7 @@ static function ($deferred) { $tagsByKey = []; foreach ($deferred as $key => $item) { $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; + $item->metadata = $item->newMetadata; } return $tagsByKey; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTagAwareAdapterTest.php index a9f3407eae6da..393210e16e74e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemTagAwareAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\FilesystemTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; /** * @group time-sensitive diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php index dbd93bdd71f03..3540155685e81 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php index 0e45324c0c12e..5c5f60a51bd67 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php @@ -14,7 +14,6 @@ use Doctrine\DBAL\DriverManager; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive diff --git a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoPruneableTrait.php similarity index 95% rename from src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php rename to src/Symfony/Component/Cache/Tests/Adapter/PdoPruneableTrait.php index baca2df8b3ba9..23f977fd6ee5b 100644 --- a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoPruneableTrait.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Cache\Tests\Traits; +namespace Symfony\Component\Cache\Tests\Adapter; trait PdoPruneableTrait { diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareAdapterTest.php index c072be952f1a4..6cffbde7926f1 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; /** * @group integration diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareClusterAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareClusterAdapterTest.php index 9b05edd9154f0..21120d606ac18 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareClusterAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PredisTagAwareClusterAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; /** * @group integration diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareAdapterTest.php index 0e73e81e87043..5c82016be2adb 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; use Symfony\Component\Cache\Traits\RedisProxy; /** diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareArrayAdapterTest.php index 5527789d79a53..3ec500a9010e9 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareArrayAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; /** * @group integration diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareClusterAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareClusterAdapterTest.php index e527223fd7de8..50f078c04d4b0 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareClusterAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisTagAwareClusterAdapterTest.php @@ -13,7 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; use Symfony\Component\Cache\Traits\RedisClusterProxy; /** diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php index ba2636cfe2fdc..d2f6b2877fcb6 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php @@ -19,7 +19,6 @@ use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\TagAwareAdapter; use Symfony\Component\Cache\Tests\Fixtures\PrunableAdapter; -use Symfony\Component\Cache\Tests\Traits\TagAwareTestTrait; /** * @group time-sensitive diff --git a/src/Symfony/Component/Cache/Tests/Traits/TagAwareTestTrait.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareTestTrait.php similarity index 96% rename from src/Symfony/Component/Cache/Tests/Traits/TagAwareTestTrait.php rename to src/Symfony/Component/Cache/Tests/Adapter/TagAwareTestTrait.php index f0ad55720d0c0..2f9b56027cb9a 100644 --- a/src/Symfony/Component/Cache/Tests/Traits/TagAwareTestTrait.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareTestTrait.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Cache\Tests\Traits; +namespace Symfony\Component\Cache\Tests\Adapter; use Symfony\Component\Cache\CacheItem; @@ -150,7 +150,9 @@ public function testGetMetadata() $pool = $this->createCachePool(); $i = $pool->getItem('k'); + $this->assertSame([], $i->getMetadata()); $pool->save($i->tag('foo')); + $this->assertSame(['foo' => 'foo'], $i->getMetadata()[CacheItem::METADATA_TAGS]); $i = $pool->getItem('k'); $this->assertSame(['foo' => 'foo'], $i->getMetadata()[CacheItem::METADATA_TAGS]); diff --git a/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php index 204211f06be2d..cf0ba1e52c011 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php @@ -13,7 +13,7 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; +use Symfony\Component\Cache\Tests\Adapter\PdoPruneableTrait; /** * @group time-sensitive diff --git a/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php index 1629959b43434..e35ab567340d5 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php @@ -14,7 +14,7 @@ use Doctrine\DBAL\DriverManager; use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; +use Symfony\Component\Cache\Tests\Adapter\PdoPruneableTrait; /** * @group time-sensitive From 27bba684d88951f7475af027731b3701c1574197 Mon Sep 17 00:00:00 2001 From: Nicolas LHommet Date: Thu, 18 Feb 2021 17:20:50 +0100 Subject: [PATCH 072/101] [Routing] fix conflict with param named class in attribute --- .../Routing/Loader/AnnotationFileLoader.php | 7 +- .../Fixtures/Attributes/FooAttributes.php | 16 +++++ ...tributesClassParamAfterCommaController.php | 18 +++++ ...esClassParamAfterParenthesisController.php | 18 +++++ ...esClassParamInlineAfterCommaController.php | 12 ++++ ...sParamInlineAfterParenthesisController.php | 12 ++++ ...sParamInlineQuotedAfterCommaController.php | 12 ++++ ...InlineQuotedAfterParenthesisController.php | 12 ++++ ...esClassParamQuotedAfterCommaController.php | 17 +++++ ...sParamQuotedAfterParenthesisController.php | 17 +++++ .../Tests/Loader/AnnotationFileLoaderTest.php | 68 +++++++++++++++++++ 11 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/Attributes/FooAttributes.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterCommaController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterParenthesisController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterCommaController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterParenthesisController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterCommaController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterParenthesisController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterCommaController.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterParenthesisController.php diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php index 8f9af3a8f76d5..cd262f1ad1ebb 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -97,12 +97,10 @@ protected function findClass($file) $nsTokens = [\T_NS_SEPARATOR => true, \T_STRING => true]; if (\defined('T_NAME_QUALIFIED')) { - $nsTokens[T_NAME_QUALIFIED] = true; + $nsTokens[\T_NAME_QUALIFIED] = true; } - for ($i = 0; isset($tokens[$i]); ++$i) { $token = $tokens[$i]; - if (!isset($token[1])) { continue; } @@ -124,6 +122,9 @@ protected function findClass($file) $skipClassToken = false; for ($j = $i - 1; $j > 0; --$j) { if (!isset($tokens[$j][1])) { + if ('(' === $tokens[$j] || ',' === $tokens[$j]) { + $skipClassToken = true; + } break; } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/Attributes/FooAttributes.php b/src/Symfony/Component/Routing/Tests/Fixtures/Attributes/FooAttributes.php new file mode 100644 index 0000000000000..9edd0ece2e3c5 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/Attributes/FooAttributes.php @@ -0,0 +1,16 @@ +class = $class; + $this->foo = $foo; + } +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterCommaController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterCommaController.php new file mode 100644 index 0000000000000..3fdf55f30c373 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterCommaController.php @@ -0,0 +1,18 @@ + ['foo','bar'], + 'foo' + ], + class: User::class +)] +class AttributesClassParamAfterCommaController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterParenthesisController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterParenthesisController.php new file mode 100644 index 0000000000000..06edcabf6d278 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamAfterParenthesisController.php @@ -0,0 +1,18 @@ + ['foo','bar'], + 'foo' + ] +)] +class AttributesClassParamAfterParenthesisController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterCommaController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterCommaController.php new file mode 100644 index 0000000000000..4b47967f139a3 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterCommaController.php @@ -0,0 +1,12 @@ + ['foo','bar'],'foo'],class: User::class)] +class AttributesClassParamInlineAfterCommaController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterParenthesisController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterParenthesisController.php new file mode 100644 index 0000000000000..876cdc33f73bc --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineAfterParenthesisController.php @@ -0,0 +1,12 @@ + ['foo','bar'],'foo'])] +class AttributesClassParamInlineAfterParenthesisController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterCommaController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterCommaController.php new file mode 100644 index 0000000000000..471efd305aa62 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterCommaController.php @@ -0,0 +1,12 @@ + ['foo','bar'],'foo'],class: 'Symfony\Component\Security\Core\User\User')] +class AttributesClassParamInlineQuotedAfterCommaController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterParenthesisController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterParenthesisController.php new file mode 100644 index 0000000000000..dc0ea7a82096a --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterParenthesisController.php @@ -0,0 +1,12 @@ + ['foo','bar'],'foo'])] +class AttributesClassParamInlineQuotedAfterParenthesisController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterCommaController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterCommaController.php new file mode 100644 index 0000000000000..1d82cd1c61216 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterCommaController.php @@ -0,0 +1,17 @@ + ['foo','bar'], + 'foo' + ], + class: 'Symfony\Component\Security\Core\User\User' +)] +class AttributesClassParamQuotedAfterCommaController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterParenthesisController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterParenthesisController.php new file mode 100644 index 0000000000000..b1456c758a027 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterParenthesisController.php @@ -0,0 +1,17 @@ + ['foo','bar'], + 'foo' + ] +)] +class AttributesClassParamQuotedAfterParenthesisController +{ + +} diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php index ff2dd53909aa5..ee66ef1804ed3 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -85,4 +85,72 @@ public function testSupports() $this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified'); $this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified'); } + + /** + * @requires PHP 8 + */ + public function testLoadAttributesClassAfterComma() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamAfterCommaController.php'); + } + + public function testLoadAttributesInlineClassAfterComma() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamInlineAfterCommaController.php'); + } + + /** + * @requires PHP 8 + */ + public function testLoadAttributesQuotedClassAfterComma() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterCommaController.php'); + } + + public function testLoadAttributesInlineQuotedClassAfterComma() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterCommaController.php'); + } + + /** + * @requires PHP 8 + */ + public function testLoadAttributesClassAfterParenthesis() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamAfterParenthesisController.php'); + } + + public function testLoadAttributesInlineClassAfterParenthesis() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamInlineAfterParenthesisController.php'); + } + + /** + * @requires PHP 8 + */ + public function testLoadAttributesQuotedClassAfterParenthesis() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamQuotedAfterParenthesisController.php'); + } + + public function testLoadAttributesInlineQuotedClassAfterParenthesis() + { + $this->reader->expects($this->once())->method('getClassAnnotation'); + + $this->loader->load(__DIR__.'/../Fixtures/AttributesFixtures/AttributesClassParamInlineQuotedAfterParenthesisController.php'); + } } From f8e10094a43f01478040593bad111387d93145cf Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 21 Feb 2021 20:10:16 +0100 Subject: [PATCH 073/101] Switched to non-null defaults in exception constructors --- .../FrameworkBundle/Routing/DelegatingLoader.php | 2 +- .../FileLoaderImportCircularReferenceException.php | 2 +- .../Config/Exception/FileLoaderLoadException.php | 12 ++++++------ .../Component/Config/Loader/DelegatingLoader.php | 2 +- src/Symfony/Component/Config/Loader/FileLoader.php | 2 +- src/Symfony/Component/Config/Loader/Loader.php | 2 +- .../Tests/Exception/LoaderLoadExceptionTest.php | 10 +++++----- .../Console/Exception/CommandNotFoundException.php | 10 +++++----- .../Exception/AccessDeniedHttpException.php | 8 ++++---- .../HttpKernel/Exception/BadRequestHttpException.php | 8 ++++---- .../HttpKernel/Exception/ConflictHttpException.php | 8 ++++---- .../HttpKernel/Exception/GoneHttpException.php | 8 ++++---- .../Component/HttpKernel/Exception/HttpException.php | 2 +- .../Exception/LengthRequiredHttpException.php | 8 ++++---- .../Exception/MethodNotAllowedHttpException.php | 10 +++++----- .../Exception/NotAcceptableHttpException.php | 8 ++++---- .../HttpKernel/Exception/NotFoundHttpException.php | 8 ++++---- .../Exception/PreconditionFailedHttpException.php | 8 ++++---- .../Exception/PreconditionRequiredHttpException.php | 8 ++++---- .../Exception/ServiceUnavailableHttpException.php | 10 +++++----- .../Exception/TooManyRequestsHttpException.php | 10 +++++----- .../Exception/UnauthorizedHttpException.php | 10 +++++----- .../Exception/UnprocessableEntityHttpException.php | 8 ++++---- .../Exception/UnsupportedMediaTypeHttpException.php | 8 ++++---- .../Exception/AccessDeniedHttpExceptionTest.php | 3 ++- .../Tests/Exception/BadRequestHttpExceptionTest.php | 3 ++- .../Tests/Exception/ConflictHttpExceptionTest.php | 3 ++- .../Tests/Exception/GoneHttpExceptionTest.php | 3 ++- .../HttpKernel/Tests/Exception/HttpExceptionTest.php | 6 +++--- .../Exception/LengthRequiredHttpExceptionTest.php | 3 ++- .../Exception/MethodNotAllowedHttpExceptionTest.php | 5 +++-- .../Exception/NotAcceptableHttpExceptionTest.php | 3 ++- .../Tests/Exception/NotFoundHttpExceptionTest.php | 3 ++- .../PreconditionFailedHttpExceptionTest.php | 3 ++- .../PreconditionRequiredHttpExceptionTest.php | 3 ++- .../ServiceUnavailableHttpExceptionTest.php | 5 +++-- .../Exception/TooManyRequestsHttpExceptionTest.php | 5 +++-- .../Exception/UnauthorizedHttpExceptionTest.php | 5 +++-- .../UnprocessableEntityHttpExceptionTest.php | 3 ++- .../UnsupportedMediaTypeHttpExceptionTest.php | 3 ++- .../Mailer/Exception/HttpTransportException.php | 2 +- .../Routing/Exception/MethodNotAllowedException.php | 7 +++++-- .../Component/Routing/RouteCollectionBuilder.php | 4 ++-- .../Component/Yaml/Exception/ParseException.php | 1 - 44 files changed, 131 insertions(+), 114 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php index 5a2ba7dba1949..47ca299e54f4b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php @@ -77,7 +77,7 @@ public function load($resource, $type = null) // - this handles the case and prevents the second fatal error // by triggering an exception beforehand. - throw new LoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, 0, null, $type); } $this->loading = true; diff --git a/src/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php b/src/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php index 8c5e736524c75..aa27f9869b7e2 100644 --- a/src/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php +++ b/src/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php @@ -18,7 +18,7 @@ */ class FileLoaderImportCircularReferenceException extends LoaderLoadException { - public function __construct(array $resources, int $code = null, \Throwable $previous = null) + public function __construct(array $resources, ?int $code = 0, \Throwable $previous = null) { $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); diff --git a/src/Symfony/Component/Config/Exception/FileLoaderLoadException.php b/src/Symfony/Component/Config/Exception/FileLoaderLoadException.php index 16beec5930c82..e53106a11aa0f 100644 --- a/src/Symfony/Component/Config/Exception/FileLoaderLoadException.php +++ b/src/Symfony/Component/Config/Exception/FileLoaderLoadException.php @@ -21,13 +21,13 @@ class FileLoaderLoadException extends \Exception { /** - * @param string $resource The resource that could not be imported - * @param string $sourceResource The original resource importing the new resource - * @param int $code The error code - * @param \Throwable $previous A previous exception - * @param string $type The type of resource + * @param string $resource The resource that could not be imported + * @param string|null $sourceResource The original resource importing the new resource + * @param int|null $code The error code + * @param \Throwable|null $previous A previous exception + * @param string|null $type The type of resource */ - public function __construct(string $resource, string $sourceResource = null, int $code = null, \Throwable $previous = null, string $type = null) + public function __construct(string $resource, string $sourceResource = null, ?int $code = 0, \Throwable $previous = null, string $type = null) { $message = ''; if ($previous) { diff --git a/src/Symfony/Component/Config/Loader/DelegatingLoader.php b/src/Symfony/Component/Config/Loader/DelegatingLoader.php index e40e57d7af6aa..fd5c8e957049b 100644 --- a/src/Symfony/Component/Config/Loader/DelegatingLoader.php +++ b/src/Symfony/Component/Config/Loader/DelegatingLoader.php @@ -34,7 +34,7 @@ public function __construct(LoaderResolverInterface $resolver) public function load($resource, $type = null) { if (false === $loader = $this->resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, 0, null, $type); } return $loader->load($resource, $type); diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index 1ca59665a41f8..b7c2491b5b023 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -177,7 +177,7 @@ private function doImport($resource, string $type = null, bool $ignoreErrors = f throw $e; } - throw new LoaderLoadException($resource, $sourceResource, null, $e, $type); + throw new LoaderLoadException($resource, $sourceResource, 0, $e, $type); } } diff --git a/src/Symfony/Component/Config/Loader/Loader.php b/src/Symfony/Component/Config/Loader/Loader.php index 698ab40afbf3d..a83088e432da9 100644 --- a/src/Symfony/Component/Config/Loader/Loader.php +++ b/src/Symfony/Component/Config/Loader/Loader.php @@ -70,7 +70,7 @@ public function resolve($resource, $type = null) $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); if (false === $loader) { - throw new LoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, 0, null, $type); } return $loader; diff --git a/src/Symfony/Component/Config/Tests/Exception/LoaderLoadExceptionTest.php b/src/Symfony/Component/Config/Tests/Exception/LoaderLoadExceptionTest.php index 60650c3daf5e4..67c40edd2c333 100644 --- a/src/Symfony/Component/Config/Tests/Exception/LoaderLoadExceptionTest.php +++ b/src/Symfony/Component/Config/Tests/Exception/LoaderLoadExceptionTest.php @@ -24,13 +24,13 @@ public function testMessageCannotLoadResource() public function testMessageCannotLoadResourceWithType() { - $exception = new LoaderLoadException('resource', null, null, null, 'foobar'); + $exception = new LoaderLoadException('resource', null, 0, null, 'foobar'); $this->assertEquals('Cannot load resource "resource". Make sure there is a loader supporting the "foobar" type.', $exception->getMessage()); } public function testMessageCannotLoadResourceWithAnnotationType() { - $exception = new LoaderLoadException('resource', null, null, null, 'annotation'); + $exception = new LoaderLoadException('resource', null, 0, null, 'annotation'); $this->assertEquals('Cannot load resource "resource". Make sure annotations are installed and enabled.', $exception->getMessage()); } @@ -56,7 +56,7 @@ public function testMessageHasPreviousErrorWithDotAndUnableToLoad() $exception = new LoaderLoadException( 'resource', null, - null, + 0, new \Exception('There was a previous error with an ending dot.') ); $this->assertEquals( @@ -70,7 +70,7 @@ public function testMessageHasPreviousErrorWithoutDotAndUnableToLoad() $exception = new LoaderLoadException( 'resource', null, - null, + 0, new \Exception('There was a previous error with no ending dot') ); $this->assertEquals( @@ -84,7 +84,7 @@ public function testMessageHasPreviousErrorAndUnableToLoadBundle() $exception = new LoaderLoadException( '@resource', null, - null, + 0, new \Exception('There was a previous error with an ending dot.') ); $this->assertEquals( diff --git a/src/Symfony/Component/Console/Exception/CommandNotFoundException.php b/src/Symfony/Component/Console/Exception/CommandNotFoundException.php index 69d5cb996a084..590a71c779642 100644 --- a/src/Symfony/Component/Console/Exception/CommandNotFoundException.php +++ b/src/Symfony/Component/Console/Exception/CommandNotFoundException.php @@ -21,10 +21,10 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce private $alternatives; /** - * @param string $message Exception message to throw - * @param array $alternatives List of similar defined names - * @param int $code Exception code - * @param \Throwable $previous Previous exception used for the exception chaining + * @param string $message Exception message to throw + * @param string[] $alternatives List of similar defined names + * @param int $code Exception code + * @param \Throwable|null $previous Previous exception used for the exception chaining */ public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) { @@ -34,7 +34,7 @@ public function __construct(string $message, array $alternatives = [], int $code } /** - * @return array A list of similar defined names + * @return string[] A list of similar defined names */ public function getAlternatives() { diff --git a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php index 65e5f8c7866a5..f0c81111db543 100644 --- a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php @@ -18,11 +18,11 @@ class AccessDeniedHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(403, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php index 7de91054b4731..8eccce1e163e7 100644 --- a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php @@ -17,11 +17,11 @@ class BadRequestHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(400, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php index ebb86ba6e9e1e..72b8aa1274fe2 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php @@ -17,11 +17,11 @@ class ConflictHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(409, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php index aea283a961cc5..6bba8159a2dce 100644 --- a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php @@ -17,11 +17,11 @@ class GoneHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(410, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/HttpException.php b/src/Symfony/Component/HttpKernel/Exception/HttpException.php index d822cd5d49a77..f3c0c3362f949 100644 --- a/src/Symfony/Component/HttpKernel/Exception/HttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/HttpException.php @@ -21,7 +21,7 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface private $statusCode; private $headers; - public function __construct(int $statusCode, string $message = null, \Throwable $previous = null, array $headers = [], ?int $code = 0) + public function __construct(int $statusCode, ?string $message = '', \Throwable $previous = null, array $headers = [], ?int $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers; diff --git a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php index 44fb770b60c89..92f9c74daf5e1 100644 --- a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php @@ -17,11 +17,11 @@ class LengthRequiredHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(411, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php index c15e46ffc3406..665ae355b47a2 100644 --- a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php @@ -17,12 +17,12 @@ class MethodNotAllowedHttpException extends HttpException { /** - * @param array $allow An array of allowed methods - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string[] $allow An array of allowed methods + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int|null $code The internal exception code */ - public function __construct(array $allow, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + public function __construct(array $allow, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) { $headers['Allow'] = strtoupper(implode(', ', $allow)); diff --git a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php index c5f5324b1a655..a985e86b9b02d 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php @@ -17,11 +17,11 @@ class NotAcceptableHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(406, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php index 146b908a1e45d..3be305ee9ea5b 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php @@ -17,11 +17,11 @@ class NotFoundHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(404, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php index e878b10ad355e..bdedea143d2e7 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php @@ -17,11 +17,11 @@ class PreconditionFailedHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(412, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php index a6cb2f09a758e..bc26804830012 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php @@ -19,11 +19,11 @@ class PreconditionRequiredHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(428, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php index c786ccf5f7fa7..1fb793dbf0b31 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php @@ -17,12 +17,12 @@ class ServiceUnavailableHttpException extends HttpException { /** - * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int|null $code The internal exception code */ - public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) { if ($retryAfter) { $headers['Retry-After'] = $retryAfter; diff --git a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php index b709f1a2f1e68..e1e47d048b248 100644 --- a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php @@ -19,12 +19,12 @@ class TooManyRequestsHttpException extends HttpException { /** - * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int|null $code The internal exception code */ - public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) { if ($retryAfter) { $headers['Retry-After'] = $retryAfter; diff --git a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php index fb86c1ea95367..ddb48f116fb52 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php @@ -17,12 +17,12 @@ class UnauthorizedHttpException extends HttpException { /** - * @param string $challenge WWW-Authenticate challenge string - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string $challenge WWW-Authenticate challenge string + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int|null $code The internal exception code */ - public function __construct(string $challenge, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + public function __construct(string $challenge, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) { $headers['WWW-Authenticate'] = $challenge; diff --git a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php index 93d4bcef69158..237340a574d79 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php @@ -17,11 +17,11 @@ class UnprocessableEntityHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(422, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php index 7cda3a62028d5..74ddbfccbc9f3 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php @@ -17,11 +17,11 @@ class UnsupportedMediaTypeHttpException extends HttpException { /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code + * @param string|null $message The internal exception message + * @param \Throwable|null $previous The previous exception + * @param int $code The internal exception code */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(415, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/AccessDeniedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/AccessDeniedHttpExceptionTest.php index 3a34cc47bce72..6fa356e70d277 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/AccessDeniedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/AccessDeniedHttpExceptionTest.php @@ -3,10 +3,11 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; class AccessDeniedHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new AccessDeniedHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/BadRequestHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/BadRequestHttpExceptionTest.php index 462fd9cb1dbc3..231b406a9d0f1 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/BadRequestHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/BadRequestHttpExceptionTest.php @@ -3,10 +3,11 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; class BadRequestHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new BadRequestHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/ConflictHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/ConflictHttpExceptionTest.php index 760600a10fc32..c923df2ce93b9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/ConflictHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/ConflictHttpExceptionTest.php @@ -3,10 +3,11 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; use Symfony\Component\HttpKernel\Exception\ConflictHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; class ConflictHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new ConflictHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/GoneHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/GoneHttpExceptionTest.php index 30dafe4922751..dd84acac36cbb 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/GoneHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/GoneHttpExceptionTest.php @@ -3,10 +3,11 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; use Symfony\Component\HttpKernel\Exception\GoneHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; class GoneHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new GoneHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/HttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/HttpExceptionTest.php index a9431f4b5a722..827f0fce3c766 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/HttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/HttpExceptionTest.php @@ -32,7 +32,7 @@ public function testHeadersDefault() */ public function testHeadersConstructor($headers) { - $exception = new HttpException(200, null, null, $headers); + $exception = new HttpException(200, '', null, $headers); $this->assertSame($headers, $exception->getHeaders()); } @@ -50,11 +50,11 @@ public function testThrowableIsAllowedForPrevious() { $previous = new class('Error of PHP 7+') extends \Error { }; - $exception = $this->createException(null, $previous); + $exception = $this->createException('', $previous); $this->assertSame($previous, $exception->getPrevious()); } - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new HttpException(200, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/LengthRequiredHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/LengthRequiredHttpExceptionTest.php index 8676d67238c14..dd74c81aaf41c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/LengthRequiredHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/LengthRequiredHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException; class LengthRequiredHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new LengthRequiredHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php index efb0b50cafd00..8f657420ea0fe 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php @@ -2,6 +2,7 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; class MethodNotAllowedHttpExceptionTest extends HttpExceptionTest @@ -18,7 +19,7 @@ public function testWithHeaderConstruct() 'Cache-Control' => 'public, s-maxage=1200', ]; - $exception = new MethodNotAllowedHttpException(['get'], null, null, null, $headers); + $exception = new MethodNotAllowedHttpException(['get'], '', null, 0, $headers); $headers['Allow'] = 'GET'; @@ -35,7 +36,7 @@ public function testHeadersSetter($headers) $this->assertSame($headers, $exception->getHeaders()); } - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new MethodNotAllowedHttpException(['get'], $message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/NotAcceptableHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/NotAcceptableHttpExceptionTest.php index 021c69e28954b..6d163faa4790d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/NotAcceptableHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/NotAcceptableHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; class NotAcceptableHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new NotAcceptableHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/NotFoundHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/NotFoundHttpExceptionTest.php index 0bf369b1a0ce4..cce9f697dd4ea 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/NotFoundHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/NotFoundHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class NotFoundHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new NotFoundHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php index 04d79c499d037..b75c560d9baae 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException; class PreconditionFailedHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new PreconditionFailedHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php index 82076617a8779..2b9c6777ba0ff 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException; class PreconditionRequiredHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new PreconditionRequiredHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php index fac197c852e3e..771e9492d03a1 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php @@ -2,6 +2,7 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; class ServiceUnavailableHttpExceptionTest extends HttpExceptionTest @@ -18,7 +19,7 @@ public function testWithHeaderConstruct() 'Cache-Control' => 'public, s-maxage=1337', ]; - $exception = new ServiceUnavailableHttpException(1337, null, null, null, $headers); + $exception = new ServiceUnavailableHttpException(1337, '', null, 0, $headers); $headers['Retry-After'] = 1337; @@ -35,7 +36,7 @@ public function testHeadersSetter($headers) $this->assertSame($headers, $exception->getHeaders()); } - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new ServiceUnavailableHttpException(null, $message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php index 8b59e9894adb5..7c2490b22ec81 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php @@ -2,6 +2,7 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; class TooManyRequestsHttpExceptionTest extends HttpExceptionTest @@ -18,7 +19,7 @@ public function testWithHeaderConstruct() 'Cache-Control' => 'public, s-maxage=69', ]; - $exception = new TooManyRequestsHttpException(69, null, null, null, $headers); + $exception = new TooManyRequestsHttpException(69, '', null, 0, $headers); $headers['Retry-After'] = 69; @@ -35,7 +36,7 @@ public function testHeadersSetter($headers) $this->assertSame($headers, $exception->getHeaders()); } - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new TooManyRequestsHttpException(null, $message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php index 92d427b6e4a9e..bd01079798fdc 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php @@ -2,6 +2,7 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class UnauthorizedHttpExceptionTest extends HttpExceptionTest @@ -18,7 +19,7 @@ public function testWithHeaderConstruct() 'Cache-Control' => 'public, s-maxage=1200', ]; - $exception = new UnauthorizedHttpException('Challenge', null, null, null, $headers); + $exception = new UnauthorizedHttpException('Challenge', '', null, 0, $headers); $headers['WWW-Authenticate'] = 'Challenge'; @@ -35,7 +36,7 @@ public function testHeadersSetter($headers) $this->assertSame($headers, $exception->getHeaders()); } - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new UnauthorizedHttpException('Challenge', $message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php index ffa4e177ee526..b538a041dd9ed 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; class UnprocessableEntityHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new UnprocessableEntityHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php index fa28bbd19b410..4eeb3fa144257 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel\Tests\Exception; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; class UnsupportedMediaTypeHttpExceptionTest extends HttpExceptionTest { - protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + protected function createException(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []): HttpException { return new UnsupportedMediaTypeHttpException($message, $previous, $code, $headers); } diff --git a/src/Symfony/Component/Mailer/Exception/HttpTransportException.php b/src/Symfony/Component/Mailer/Exception/HttpTransportException.php index f672acc6f12b7..3428b70e07eae 100644 --- a/src/Symfony/Component/Mailer/Exception/HttpTransportException.php +++ b/src/Symfony/Component/Mailer/Exception/HttpTransportException.php @@ -20,7 +20,7 @@ class HttpTransportException extends TransportException { private $response; - public function __construct(string $message = null, ResponseInterface $response, int $code = 0, \Throwable $previous = null) + public function __construct(?string $message, ResponseInterface $response, int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); diff --git a/src/Symfony/Component/Routing/Exception/MethodNotAllowedException.php b/src/Symfony/Component/Routing/Exception/MethodNotAllowedException.php index b897081bd5d84..8a437140352cf 100644 --- a/src/Symfony/Component/Routing/Exception/MethodNotAllowedException.php +++ b/src/Symfony/Component/Routing/Exception/MethodNotAllowedException.php @@ -22,7 +22,10 @@ class MethodNotAllowedException extends \RuntimeException implements ExceptionIn { protected $allowedMethods = []; - public function __construct(array $allowedMethods, string $message = null, int $code = 0, \Throwable $previous = null) + /** + * @param string[] $allowedMethods + */ + public function __construct(array $allowedMethods, ?string $message = '', int $code = 0, \Throwable $previous = null) { $this->allowedMethods = array_map('strtoupper', $allowedMethods); @@ -32,7 +35,7 @@ public function __construct(array $allowedMethods, string $message = null, int $ /** * Gets the allowed HTTP methods. * - * @return array + * @return string[] */ public function getAllowedMethods() { diff --git a/src/Symfony/Component/Routing/RouteCollectionBuilder.php b/src/Symfony/Component/Routing/RouteCollectionBuilder.php index 92cf7e7938843..02740262b6e50 100644 --- a/src/Symfony/Component/Routing/RouteCollectionBuilder.php +++ b/src/Symfony/Component/Routing/RouteCollectionBuilder.php @@ -362,11 +362,11 @@ private function load($resource, string $type = null): array } if (null === $resolver = $this->loader->getResolver()) { - throw new LoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, 0, null, $type); } if (false === $loader = $resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, 0, null, $type); } $collections = $loader->load($resource, $type); diff --git a/src/Symfony/Component/Yaml/Exception/ParseException.php b/src/Symfony/Component/Yaml/Exception/ParseException.php index f0324607725fa..c75066da2d4f5 100644 --- a/src/Symfony/Component/Yaml/Exception/ParseException.php +++ b/src/Symfony/Component/Yaml/Exception/ParseException.php @@ -28,7 +28,6 @@ class ParseException extends RuntimeException * @param int $parsedLine The line where the error occurred * @param string|null $snippet The snippet of code near the problem * @param string|null $parsedFile The file name where the error occurred - * @param \Exception|null $previous The previous exception */ public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Throwable $previous = null) { From ac45be2580a53871d9daaac2665ecea8f0a75097 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Vares Date: Mon, 22 Feb 2021 09:25:14 +0100 Subject: [PATCH 074/101] In calls to mb_ functions, silently transform arg into string In PHP8, a number of functions who were accepting null arguments will only accept string ones. In the polyfill, mb_* functions are declared with a trict type checking of "string". Therefore, we deprecate the use of non string arguments, so that it won't break when either using the polyfill, or future php8 versions. --- src/Symfony/Component/Console/Helper/Helper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 0ddddf6bc5023..0521aaf7d2933 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -47,6 +47,8 @@ public function getHelperSet() */ public static function strlen($string) { + $string = (string) $string; + if (false === $encoding = mb_detect_encoding($string, null, true)) { return \strlen($string); } @@ -65,6 +67,8 @@ public static function strlen($string) */ public static function substr($string, $from, $length = null) { + $string = (string) $string; + if (false === $encoding = mb_detect_encoding($string, null, true)) { return substr($string, $from, $length); } From 3288897e0faefb11d164f75edb3816057664eab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Isaert?= Date: Mon, 21 Dec 2020 17:26:32 +0100 Subject: [PATCH 075/101] [Cache] Fix Redis TLS scheme `rediss` for Redis connection --- .../Cache/Tests/Adapter/RedisAdapterTest.php | 38 ++++++++++--------- .../Component/Cache/Traits/RedisTrait.php | 32 ++++++++++++---- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php index 514a0e92e1ba0..b54a5acc84260 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php @@ -36,36 +36,46 @@ public function createCachePool(int $defaultLifetime = 0): CacheItemPoolInterfac return $adapter; } - /** - * @dataProvider provideValidSchemes - */ - public function testCreateConnection(string $dsnScheme) + public function testCreateConnection() { - $redis = RedisAdapter::createConnection($dsnScheme.':?host[h1]&host[h2]&host[/foo:]'); + $redis = RedisAdapter::createConnection('redis:?host[h1]&host[h2]&host[/foo:]'); $this->assertInstanceOf(\RedisArray::class, $redis); $this->assertSame(['h1:6379', 'h2:6379', '/foo'], $redis->_hosts()); @$redis = null; // some versions of phpredis connect on destruct, let's silence the warning $redisHost = getenv('REDIS_HOST'); - $redis = RedisAdapter::createConnection($dsnScheme.'://'.$redisHost); + $redis = RedisAdapter::createConnection('redis://'.$redisHost); $this->assertInstanceOf(\Redis::class, $redis); $this->assertTrue($redis->isConnected()); $this->assertSame(0, $redis->getDbNum()); - $redis = RedisAdapter::createConnection($dsnScheme.'://'.$redisHost.'/2'); + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/2'); $this->assertSame(2, $redis->getDbNum()); - $redis = RedisAdapter::createConnection($dsnScheme.'://'.$redisHost, ['timeout' => 3]); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['timeout' => 3]); $this->assertEquals(3, $redis->getTimeout()); - $redis = RedisAdapter::createConnection($dsnScheme.'://'.$redisHost.'?timeout=4'); + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'?timeout=4'); $this->assertEquals(4, $redis->getTimeout()); - $redis = RedisAdapter::createConnection($dsnScheme.'://'.$redisHost, ['read_timeout' => 5]); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); $this->assertEquals(5, $redis->getReadTimeout()); } + public function testCreateTlsConnection() + { + $redis = RedisAdapter::createConnection('rediss:?host[h1]&host[h2]&host[/foo:]'); + $this->assertInstanceOf(\RedisArray::class, $redis); + $this->assertSame(['tls://h1:6379', 'tls://h2:6379', '/foo'], $redis->_hosts()); + @$redis = null; // some versions of phpredis connect on destruct, let's silence the warning + + $redisHost = getenv('REDIS_HOST'); + + $redis = RedisAdapter::createConnection('rediss://'.$redisHost.'?lazy=1'); + $this->assertInstanceOf(RedisProxy::class, $redis); + } + /** * @dataProvider provideFailedCreateConnection */ @@ -95,14 +105,6 @@ public function testInvalidCreateConnection(string $dsn) RedisAdapter::createConnection($dsn); } - public function provideValidSchemes(): array - { - return [ - ['redis'], - ['rediss'], - ]; - } - public function provideInvalidCreateConnection(): array { return [ diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index d48dd24b577b9..bf2ca1073b5df 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -118,6 +118,9 @@ public static function createConnection($dsn, array $options = []) $query = $hosts = []; + $tls = 'rediss' === $scheme; + $tcpScheme = $tls ? 'tls' : 'tcp'; + if (isset($params['query'])) { parse_str($params['query'], $query); @@ -130,9 +133,9 @@ public static function createConnection($dsn, array $options = []) parse_str($parameters, $parameters); } if (false === $i = strrpos($host, ':')) { - $hosts[$host] = ['scheme' => 'tcp', 'host' => $host, 'port' => 6379] + $parameters; + $hosts[$host] = ['scheme' => $tcpScheme, 'host' => $host, 'port' => 6379] + $parameters; } elseif ($port = (int) substr($host, 1 + $i)) { - $hosts[$host] = ['scheme' => 'tcp', 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; + $hosts[$host] = ['scheme' => $tcpScheme, 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; } else { $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters; } @@ -148,7 +151,7 @@ public static function createConnection($dsn, array $options = []) } if (isset($params['host'])) { - array_unshift($hosts, ['scheme' => 'tcp', 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); + array_unshift($hosts, ['scheme' => $tcpScheme, 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); } else { array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]); } @@ -174,9 +177,16 @@ public static function createConnection($dsn, array $options = []) $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; $redis = new $class(); - $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts) { + $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) { + $host = $hosts[0]['host'] ?? $hosts[0]['path']; + $port = $hosts[0]['port'] ?? null; + + if (isset($hosts[0]['host']) && $tls) { + $host = 'tls://'.$host; + } + try { - @$redis->{$connect}($hosts[0]['host'] ?? $hosts[0]['path'], $hosts[0]['port'] ?? null, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']); + @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); $isConnected = $redis->isConnected(); @@ -210,7 +220,11 @@ public static function createConnection($dsn, array $options = []) } } elseif (is_a($class, \RedisArray::class, true)) { foreach ($hosts as $i => $host) { - $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; + switch ($host['scheme']) { + case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; + case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; + default: $hosts[$i] = $host['path']; + } } $params['lazy_connect'] = $params['lazy'] ?? true; $params['connect_timeout'] = $params['timeout']; @@ -227,7 +241,11 @@ public static function createConnection($dsn, array $options = []) } elseif (is_a($class, \RedisCluster::class, true)) { $initializer = static function () use ($class, $params, $dsn, $hosts) { foreach ($hosts as $i => $host) { - $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; + switch ($host['scheme']) { + case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; + case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; + default: $hosts[$i] = $host['path']; + } } try { From 8e1d3285ed1a6e65f3323d04e3d2b3c151254dec Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 22 Feb 2021 22:11:34 +0100 Subject: [PATCH 076/101] Adding templates for Belarusian --- .../Resources/translations/validators.be.xlf | 120 ++++++++++++++++++ .../Resources/translations/security.be.xlf | 8 ++ .../Resources/translations/validators.be.xlf | 24 ++++ 3 files changed, 152 insertions(+) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.be.xlf b/src/Symfony/Component/Form/Resources/translations/validators.be.xlf index 004ba594b3875..042722eba89eb 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.be.xlf @@ -14,6 +14,126 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF-токен не сапраўдны. Калі ласка, паспрабуйце яшчэ раз адправіць форму. + + This value is not a valid HTML5 color. + This value is not a valid HTML5 color. + + + Please enter a valid birthdate. + Please enter a valid birthdate. + + + The selected choice is invalid. + The selected choice is invalid. + + + The collection is invalid. + The collection is invalid. + + + Please select a valid color. + Please select a valid color. + + + Please select a valid country. + Please select a valid country. + + + Please select a valid currency. + Please select a valid currency. + + + Please choose a valid date interval. + Please choose a valid date interval. + + + Please enter a valid date and time. + Please enter a valid date and time. + + + Please enter a valid date. + Please enter a valid date. + + + Please select a valid file. + Please select a valid file. + + + The hidden field is invalid. + The hidden field is invalid. + + + Please enter an integer. + Please enter an integer. + + + Please select a valid language. + Please select a valid language. + + + Please select a valid locale. + Please select a valid locale. + + + Please enter a valid money amount. + Please enter a valid money amount. + + + Please enter a number. + Please enter a number. + + + The password is invalid. + The password is invalid. + + + Please enter a percentage value. + Please enter a percentage value. + + + The values do not match. + The values do not match. + + + Please enter a valid time. + Please enter a valid time. + + + Please select a valid timezone. + Please select a valid timezone. + + + Please enter a valid URL. + Please enter a valid URL. + + + Please enter a valid search term. + Please enter a valid search term. + + + Please provide a valid phone number. + Please provide a valid phone number. + + + The checkbox has an invalid value. + The checkbox has an invalid value. + + + Please enter a valid email address. + Please enter a valid email address. + + + Please select a valid option. + Please select a valid option. + + + Please select a valid range. + Please select a valid range. + + + Please enter a valid week. + Please enter a valid week. + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf index c3cd7911e55cb..216df88ed2561 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf @@ -62,6 +62,14 @@ Account is locked. Акаўнт заблакіраван. + + Too many failed login attempts, please try again later. + Too many failed login attempts, please try again later. + + + Invalid or expired login link. + Invalid or expired login link. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf index ab3845ee20153..e12c53c36e8b0 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf @@ -362,6 +362,30 @@ This password has been leaked in a data breach, it must not be used. Please use another password. Гэты пароль быў выкрадзены ў выніку ўзлому дадзеных, таму яго нельга выкарыстоўваць. Калі ласка, выкарыстоўвайце іншы пароль. + + This value should be between {{ min }} and {{ max }}. + This value should be between {{ min }} and {{ max }}. + + + This value is not a valid hostname. + This value is not a valid hostname. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + The number of elements in this collection should be a multiple of {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + This value should satisfy at least one of the following constraints: + + + Each element of this collection should satisfy its own set of constraints. + Each element of this collection should satisfy its own set of constraints. + + + This value is not a valid International Securities Identification Number (ISIN). + This value is not a valid International Securities Identification Number (ISIN). + From 56194a45354d99b110a41a69aa523fa45a680a06 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 23 Feb 2021 11:03:30 +0100 Subject: [PATCH 077/101] Move github templates at the org level --- .github/CODE_OF_CONDUCT.md | 8 ------- .github/ISSUE_TEMPLATE/1_Bug_report.md | 21 ------------------- .github/ISSUE_TEMPLATE/2_Feature_request.md | 12 ----------- .github/ISSUE_TEMPLATE/3_Support_question.md | 11 ---------- .../ISSUE_TEMPLATE/4_Documentation_issue.md | 10 --------- .github/SECURITY.md | 10 --------- 6 files changed, 72 deletions(-) delete mode 100644 .github/CODE_OF_CONDUCT.md delete mode 100644 .github/ISSUE_TEMPLATE/1_Bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/2_Feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/3_Support_question.md delete mode 100644 .github/ISSUE_TEMPLATE/4_Documentation_issue.md delete mode 100644 .github/SECURITY.md diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md deleted file mode 100644 index 16e2603b76a1d..0000000000000 --- a/.github/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,8 +0,0 @@ -# Code of Conduct - -This project follows a [Code of Conduct][code_of_conduct] in order to ensure an open and welcoming environment. -Please read the full text for understanding the accepted and unaccepted behavior. -Please read also the [reporting guidelines][guidelines], in case you encountered or witnessed any misbehavior. - -[code_of_conduct]: https://symfony.com/doc/current/contributing/code_of_conduct/index.html -[guidelines]: https://symfony.com/doc/current/contributing/code_of_conduct/reporting_guidelines.html diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md deleted file mode 100644 index 4a64e16edf0a5..0000000000000 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: 🐛 Bug Report -about: Report errors and problems - ---- - -**Symfony version(s) affected**: x.y.z - -**Description** - - -**How to reproduce** - - -**Possible Solution** - - -**Additional context** - diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.md b/.github/ISSUE_TEMPLATE/2_Feature_request.md deleted file mode 100644 index 335321e413607..0000000000000 --- a/.github/ISSUE_TEMPLATE/2_Feature_request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: 🚀 Feature Request -about: RFC and ideas for new features and improvements - ---- - -**Description** - - -**Example** - diff --git a/.github/ISSUE_TEMPLATE/3_Support_question.md b/.github/ISSUE_TEMPLATE/3_Support_question.md deleted file mode 100644 index 9480710c15655..0000000000000 --- a/.github/ISSUE_TEMPLATE/3_Support_question.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: ⛔ Support Question -about: See https://symfony.com/support for questions about using Symfony and its components - ---- - -We use GitHub issues only to discuss about Symfony bugs and new features. For -this kind of questions about using Symfony or third-party bundles, please use -any of the support alternatives shown in https://symfony.com/support - -Thanks! diff --git a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md b/.github/ISSUE_TEMPLATE/4_Documentation_issue.md deleted file mode 100644 index 0855c3c5f1e12..0000000000000 --- a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: ⛔ Documentation Issue -about: See https://github.com/symfony/symfony-docs/issues for documentation issues - ---- - -Symfony Documentation has its own dedicated repository. Please open your -documentation-related issue at https://github.com/symfony/symfony-docs/issues - -Thanks! diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index 60990950bf039..0000000000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,10 +0,0 @@ -Security Policy -=============== - -If you found any issues that might have security implications, -please send a report to security[at]symfony.com -DO NOT PUBLISH SECURITY REPORTS PUBLICLY. - -The full [Security Policy][1] is described in the official documentation. - - [1]: https://symfony.com/security From 95fdd90491e689c6d71d78e80dc0206796b3bb11 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Tue, 23 Feb 2021 16:46:11 +0100 Subject: [PATCH 078/101] Allow x-forwarded-prefix trusted header. --- .../FrameworkBundle/DependencyInjection/Configuration.php | 2 +- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 7399f6fab20d4..a0efab6b5ba64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -97,7 +97,7 @@ public function getConfigTreeBuilder() ->enumPrototype() ->values([ 'forwarded', - 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', + 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix', ]) ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ac69dfd525805..c6cd60cc32fb1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -2305,6 +2305,7 @@ private function resolveTrustedHeaders(array $headers): int case 'x-forwarded-host': $trustedHeaders |= Request::HEADER_X_FORWARDED_HOST; break; case 'x-forwarded-proto': $trustedHeaders |= Request::HEADER_X_FORWARDED_PROTO; break; case 'x-forwarded-port': $trustedHeaders |= Request::HEADER_X_FORWARDED_PORT; break; + case 'x-forwarded-prefix': $trustedHeaders |= Request::HEADER_X_FORWARDED_PREFIX; break; } } From 2e865ac05707294955c4e0df6d1903497903152c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 24 Feb 2021 00:58:19 +0100 Subject: [PATCH 079/101] Switched to non-null defaults in exception constructors --- .../Config/Exception/LoaderLoadException.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Config/Exception/LoaderLoadException.php b/src/Symfony/Component/Config/Exception/LoaderLoadException.php index dcec3201bdb20..86886058668a6 100644 --- a/src/Symfony/Component/Config/Exception/LoaderLoadException.php +++ b/src/Symfony/Component/Config/Exception/LoaderLoadException.php @@ -19,13 +19,13 @@ class LoaderLoadException extends \Exception { /** - * @param string $resource The resource that could not be imported - * @param string $sourceResource The original resource importing the new resource - * @param int $code The error code - * @param \Throwable $previous A previous exception - * @param string $type The type of resource + * @param string $resource The resource that could not be imported + * @param string|null $sourceResource The original resource importing the new resource + * @param int|null $code The error code + * @param \Throwable|null $previous A previous exception + * @param string|null $type The type of resource */ - public function __construct(string $resource, string $sourceResource = null, int $code = null, \Throwable $previous = null, string $type = null) + public function __construct(string $resource, string $sourceResource = null, ?int $code = 0, \Throwable $previous = null, string $type = null) { $message = ''; if ($previous) { From 8d3078dd351e8ea16222c72083db9ff28ab33e36 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 23 Feb 2021 23:49:04 +0100 Subject: [PATCH 080/101] [Security] #[CurrentUser] argument should resolve to null when it is anonymous --- .../Security/Http/Controller/UserValueResolver.php | 9 +++------ .../Http/Tests/Controller/UserValueResolverTest.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php b/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php index 396b430ac99a1..4b469edf8b10e 100644 --- a/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php +++ b/src/Symfony/Component/Security/Http/Controller/UserValueResolver.php @@ -35,12 +35,9 @@ public function __construct(TokenStorageInterface $tokenStorage) public function supports(Request $request, ArgumentMetadata $argument): bool { - if ($argument->getAttribute() instanceof CurrentUser) { - return true; - } - - // only security user implementations are supported - if (UserInterface::class !== $argument->getType()) { + // with the attribute, the type can be any UserInterface implementation + // otherwise, the type must be UserInterface + if (UserInterface::class !== $argument->getType() && !$argument->getAttribute() instanceof CurrentUser) { return false; } diff --git a/src/Symfony/Component/Security/Http/Tests/Controller/UserValueResolverTest.php b/src/Symfony/Component/Security/Http/Tests/Controller/UserValueResolverTest.php index b95aa465c3433..ca3197e5e4f9a 100644 --- a/src/Symfony/Component/Security/Http/Tests/Controller/UserValueResolverTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Controller/UserValueResolverTest.php @@ -83,6 +83,17 @@ public function testResolveWithAttribute() $this->assertSame([$user], iterator_to_array($resolver->resolve(Request::create('/'), $metadata))); } + public function testResolveWithAttributeAndNoUser() + { + $tokenStorage = new TokenStorage(); + $tokenStorage->setToken(new UsernamePasswordToken('username', 'password', 'provider')); + + $resolver = new UserValueResolver($tokenStorage); + $metadata = new ArgumentMetadata('foo', null, false, false, null, false, new CurrentUser()); + + $this->assertFalse($resolver->supports(Request::create('/'), $metadata)); + } + public function testIntegration() { $user = $this->createMock(UserInterface::class); From 97058559cc99f1b05ef89c62a070deebea9899dc Mon Sep 17 00:00:00 2001 From: Marie Minasyan Date: Tue, 23 Feb 2021 19:21:01 +0100 Subject: [PATCH 081/101] [Translation] Make `name` attribute optional in xliff2 Do not set a fake `name` attribute on `unit` element from xliff2 to allow using `source` attribute and avoid missing translation error --- .../Component/Translation/Dumper/XliffFileDumper.php | 8 ++++---- .../Translation/Tests/Dumper/XliffFileDumperTest.php | 1 + .../Translation/Tests/fixtures/resources-2.0-clean.xlf | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 72d9c6e9f3913..63f30a5b64590 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -150,11 +150,11 @@ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ? foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); - $name = $source; - if (\strlen($source) > 80) { - $name = substr(md5($source), -7); + + if (\strlen($source) <= 80) { + $translation->setAttribute('name', $source); } - $translation->setAttribute('name', $name); + $metadata = $messages->getMetadata($source, $domain); // Add notes section diff --git a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php index 6377132f7009b..cb995553b557d 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -43,6 +43,7 @@ public function testFormatCatalogueXliff2() 'foo' => 'bar', 'key' => '', 'key.with.cdata' => ' & ', + 'translation.key.that.is.longer.than.eighty.characters.should.not.have.name.attribute' => 'value', ]); $catalogue->setMetadata('key', ['target-attributes' => ['order' => 1]]); diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf index efa69b27ffb5a..ccc5ef7a72bd0 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf @@ -19,5 +19,11 @@ & ]]> + + + translation.key.that.is.longer.than.eighty.characters.should.not.have.name.attribute + value + + From b2970456bff65ca3c86d7cdfafb657726a113a2d Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 25 Feb 2021 12:20:45 +0100 Subject: [PATCH 082/101] [TwigBridge] Install symfony/intl to run tests on Travis --- src/Symfony/Bridge/Twig/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 72ebca58f49c3..6878052543bac 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -29,6 +29,7 @@ "symfony/form": "^4.4.17", "symfony/http-foundation": "^4.3|^5.0", "symfony/http-kernel": "^4.4", + "symfony/intl": "^4.4|^5.0", "symfony/mime": "^4.3|^5.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "^3.4|^4.0|^5.0", From c5ed24d8cb0f218776dc36a2a3faa3d12b2307d0 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Tue, 16 Feb 2021 08:30:58 +0100 Subject: [PATCH 083/101] Adding a Github action to run Psalm --- .github/psalm/cache/.gitignore | 2 + .github/psalm/psalm.baseline.xml | 3 + .github/workflows/psalm.yml | 97 ++++++++++++++++++++++++++++++++ psalm.xml | 20 +++++++ 4 files changed, 122 insertions(+) create mode 100644 .github/psalm/cache/.gitignore create mode 100644 .github/psalm/psalm.baseline.xml create mode 100644 .github/workflows/psalm.yml create mode 100644 psalm.xml diff --git a/.github/psalm/cache/.gitignore b/.github/psalm/cache/.gitignore new file mode 100644 index 0000000000000..d6b7ef32c8478 --- /dev/null +++ b/.github/psalm/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/.github/psalm/psalm.baseline.xml b/.github/psalm/psalm.baseline.xml new file mode 100644 index 0000000000000..f74693accd46f --- /dev/null +++ b/.github/psalm/psalm.baseline.xml @@ -0,0 +1,3 @@ + + + diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 0000000000000..3910d569d606f --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,97 @@ +name: Static analysis + +on: + pull_request: ~ + +jobs: + psalm: + name: Psalm + runs-on: Ubuntu-20.04 + + steps: + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + extensions: "json,memcached,mongodb,redis,xsl,ldap,dom" + ini-values: "memory_limit=-1" + coverage: none + + - name: Checkout PR + uses: actions/checkout@v2 + with: + path: pr + + - name: Checkout base + uses: actions/checkout@v2 + with: + ref: ${{ github.base_ref }} + path: base + + - name: Configure composer + run: | + cd base + COMPOSER_HOME="$(composer config home)" + ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" + echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV + + - name: Determine composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: composer-${{ github.base_ref }} + restore-keys: composer- + + - name: Install Psalm + run: | + composer require psalm/phar + cp ./vendor/bin/psalm.phar base/psalm.phar + cp ./vendor/bin/psalm.phar pr/psalm.phar + + - name: Install dependencies for base + run: | + cd base + echo "::group::modify composer.json" + sed -i -re 's/"replace": \{/"replace": \{"symfony\/phpunit-bridge": "self.version",/' composer.json + composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher + echo "::endgroup::" + echo "::group::composer update" + composer update --no-progress --ansi + echo "::endgroup::" + + - name: Generate Psalm baseline + run: | + cd base + ./psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress + + - name: Copy baseline + run: | + cp base/.github/psalm/psalm.baseline.xml pr/.github/psalm/psalm.baseline.xml + + - name: Install dependencies for PR + run: | + cd pr + echo "::group::modify composer.json" + sed -i -re 's/"replace": \{/"replace": \{"symfony\/phpunit-bridge": "self.version",/' composer.json + composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher + echo "::endgroup::" + echo "::group::composer update" + composer update --no-progress --ansi + echo "::endgroup::" + + - name: Cache Psalm + uses: actions/cache@v2 + with: + path: pr/.github/psalm/cache/ + key: psalm-${{ github.base_ref }} + restore-keys: psalm- + + - name: Psalm + run: | + cd pr + ./psalm.phar --version + ./psalm.phar --output-format=github --no-progress diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000000000..3f12f1331c272 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + From d5a05f1b30fa5aa3d1a06f30c87dd5fdb3c7c451 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Thu, 25 Feb 2021 17:35:56 +0100 Subject: [PATCH 084/101] Make sure the Psalm review CI job is working --- .github/workflows/psalm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 3910d569d606f..11027c374e4fd 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -56,7 +56,7 @@ jobs: run: | cd base echo "::group::modify composer.json" - sed -i -re 's/"replace": \{/"replace": \{"symfony\/phpunit-bridge": "self.version",/' composer.json + composer remove symfony/phpunit-bridge --no-interaction --no-update composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher echo "::endgroup::" echo "::group::composer update" @@ -76,7 +76,7 @@ jobs: run: | cd pr echo "::group::modify composer.json" - sed -i -re 's/"replace": \{/"replace": \{"symfony\/phpunit-bridge": "self.version",/' composer.json + composer remove symfony/phpunit-bridge --no-interaction --no-update composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher echo "::endgroup::" echo "::group::composer update" From e82918cd6000343150ae6bb49edbf21d53baab7e Mon Sep 17 00:00:00 2001 From: tamcy Date: Fri, 19 Feb 2021 12:13:03 +0800 Subject: [PATCH 085/101] [HttpKernel] Configure `session.cookie_secure` earlier --- .../Session/Storage/NativeSessionStorage.php | 3 +++ .../HttpKernel/EventListener/SessionListener.php | 16 +++++++++++++--- .../Tests/EventListener/SessionListenerTest.php | 8 ++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index e1da95509e1e6..8288d3c22d063 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -389,6 +389,9 @@ public function setOptions(array $options) $this->emulateSameSite = $value; continue; } + if ('cookie_secure' === $key && 'auto' === $value) { + continue; + } ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } diff --git a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php index a53ade797cdac..6cff47b88d62b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php @@ -14,6 +14,7 @@ use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** * Sets the session in the request. @@ -33,10 +34,12 @@ public function __construct(ContainerInterface $container) $this->container = $container; } - protected function getSession(): ?SessionInterface + public function onKernelRequest(GetResponseEvent $event) { - if (!$this->container->has('session')) { - return null; + parent::onKernelRequest($event); + + if (!$event->isMasterRequest() || !$this->container->has('session')) { + return; } if ($this->container->has('session_storage') @@ -46,6 +49,13 @@ protected function getSession(): ?SessionInterface ) { $storage->setOptions(['cookie_secure' => true]); } + } + + protected function getSession(): ?SessionInterface + { + if (!$this->container->has('session')) { + return null; + } return $this->container->get('session'); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index de1069606b6b6..e0dba81683ee9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -59,7 +59,7 @@ public function testSessionIsSet() $listener = new SessionListener($container); $event = $this->createMock(RequestEvent::class); - $event->expects($this->once())->method('isMasterRequest')->willReturn(true); + $event->expects($this->exactly(2))->method('isMasterRequest')->willReturn(true); $event->expects($this->once())->method('getRequest')->willReturn($request); $listener->onKernelRequest($event); @@ -203,12 +203,16 @@ public function testGetSessionIsCalledOnce() $listener = new SessionListener($container); $listener->onKernelRequest($event); + // storage->setOptions() should have been called already + $container->set('session_storage', null); + $sessionStorage = null; + $subRequest = $masterRequest->duplicate(); // at this point both master and subrequest have a closure to build the session $masterRequest->getSession(); - // calling the factory on the subRequest should not trigger a second call to storage->sesOptions() + // calling the factory on the subRequest should not trigger a second call to storage->setOptions() $subRequest->getSession(); } } From 5854d55aefc23cf3d54e7e052a62d6d1c5b70f9d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 25 Feb 2021 18:36:22 +0100 Subject: [PATCH 086/101] fix merge --- .../EventListener/SessionListener.php | 4 ++-- .../Tests/Firewall/LogoutListenerTest.php | 14 ++++++------- .../Tests/Firewall/RememberMeListenerTest.php | 20 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php index 93bbb2f117b2f..2635788b1cf7b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php @@ -14,7 +14,7 @@ use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; /** * Sets the session in the request. @@ -34,7 +34,7 @@ public function __construct(ContainerInterface $container, bool $debug = false) parent::__construct($container, $debug); } - public function onKernelRequest(GetResponseEvent $event) + public function onKernelRequest(RequestEvent $event) { parent::onKernelRequest($event); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php index e8cc999a7c7cd..effccd6a8c705 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php @@ -36,7 +36,7 @@ public function testHandleUnmatchedPath() $dispatcher = $this->getEventDispatcher(); [$listener, , $httpUtils, $options] = $this->getListener($dispatcher); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $logoutEventDispatched = false; $dispatcher->addListener(LogoutEvent::class, function (LogoutEvent $event) use (&$logoutEventDispatched) { @@ -60,7 +60,7 @@ public function testHandleMatchedPathWithCsrfValidation() [$listener, $tokenStorage, $httpUtils, $options] = $this->getListener($dispatcher, $tokenManager); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $request->query->set('_csrf_token', 'token'); @@ -98,7 +98,7 @@ public function testHandleMatchedPathWithoutCsrfValidation() $dispatcher = $this->getEventDispatcher(); [$listener, $tokenStorage, $httpUtils, $options] = $this->getListener($dispatcher); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') @@ -131,7 +131,7 @@ public function testNoResponseSet() [$listener, , $httpUtils, $options] = $this->getListener(); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') @@ -148,7 +148,7 @@ public function testCsrfValidationFails() [$listener, , $httpUtils, $options] = $this->getListener(null, $tokenManager); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $request->query->set('_csrf_token', 'token'); @@ -179,7 +179,7 @@ public function testLegacyLogoutHandlers() $token = $this->getToken(); $tokenStorage->expects($this->any())->method('getToken')->willReturn($token); - [$event, $request] = $this->getGetResponseEvent(); + [$event, $request] = $this->getRequestEvent(); $httpUtils->expects($this->once()) ->method('checkRequestPath') @@ -208,7 +208,7 @@ private function getTokenStorage() return $this->createMock(TokenStorageInterface::class); } - private function getGetResponseEvent() + private function getRequestEvent() { $event = $this->createMock(RequestEvent::class); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php index 88648c301ab5d..2ae8abc230775 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php @@ -46,7 +46,7 @@ public function testOnCoreSecurityDoesNotTryToPopulateNonEmptyTokenStorage() ->method('setToken') ; - $this->assertNull($listener($this->getGetResponseEvent())); + $this->assertNull($listener($this->getRequestEvent())); } public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() @@ -65,7 +65,7 @@ public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() ->willReturn(null) ; - $event = $this->getGetResponseEvent(); + $event = $this->getRequestEvent(); $this->assertNull($listener($event)); } @@ -100,7 +100,7 @@ public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenti ->willThrowException($exception) ; - $event = $this->getGetResponseEvent($request); + $event = $this->getRequestEvent($request); $listener($event); } @@ -135,7 +135,7 @@ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExcepti ->willThrowException($exception) ; - $event = $this->getGetResponseEvent(); + $event = $this->getRequestEvent(); $listener($event); } @@ -167,7 +167,7 @@ public function testOnCoreSecurityAuthenticationExceptionDuringAutoLoginTriggers ->method('authenticate') ; - $event = $this->getGetResponseEvent(); + $event = $this->getRequestEvent(); $listener($event); } @@ -201,7 +201,7 @@ public function testOnCoreSecurity() ->willReturn($token) ; - $event = $this->getGetResponseEvent(); + $event = $this->getRequestEvent(); $listener($event); } @@ -245,7 +245,7 @@ public function testSessionStrategy() $request = new Request(); $request->setSession($session); - $event = $this->getGetResponseEvent($request); + $event = $this->getRequestEvent($request); $sessionStrategy ->expects($this->once()) @@ -299,7 +299,7 @@ public function testSessionIsMigratedByDefault() $request = new Request(); $request->setSession($session); - $event = $this->getGetResponseEvent($request); + $event = $this->getRequestEvent($request); $listener($event); } @@ -333,7 +333,7 @@ public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherI ->willReturn($token) ; - $event = $this->getGetResponseEvent(); + $event = $this->getRequestEvent(); $dispatcher ->expects($this->once()) @@ -347,7 +347,7 @@ public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherI $listener($event); } - protected function getGetResponseEvent(Request $request = null): RequestEvent + protected function getRequestEvent(Request $request = null): RequestEvent { $request = $request ?? new Request(); From 8dada95cbf28bfa9404c6ea884eae8d9b0a319b2 Mon Sep 17 00:00:00 2001 From: Pierrick VIGNAND Date: Thu, 18 Feb 2021 14:41:11 +0100 Subject: [PATCH 087/101] fix: MockResponse total_time should not be simulated when provided --- .../HttpClient/Response/MockResponse.php | 8 ++++---- .../Tests/Response/MockResponseTest.php | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpClient/Response/MockResponse.php b/src/Symfony/Component/HttpClient/Response/MockResponse.php index 0f359f30b3265..8f5803202c1bf 100644 --- a/src/Symfony/Component/HttpClient/Response/MockResponse.php +++ b/src/Symfony/Component/HttpClient/Response/MockResponse.php @@ -211,8 +211,8 @@ private static function writeRequest(self $response, array $options, ResponseInt $response->info['size_upload'] = 0.0; } - // simulate "total_time" if it is set - if (isset($response->info['total_time'])) { + // simulate "total_time" if it is not set + if (!isset($response->info['total_time'])) { $response->info['total_time'] = microtime(true) - $response->info['start_time']; } @@ -260,7 +260,7 @@ private static function readResponse(self $response, array $options, ResponseInt 'http_code' => $response->info['http_code'], ] + $info + $response->info; - if (isset($response->info['total_time'])) { + if (!isset($response->info['total_time'])) { $response->info['total_time'] = microtime(true) - $response->info['start_time']; } @@ -287,7 +287,7 @@ private static function readResponse(self $response, array $options, ResponseInt $offset = \strlen($body); } - if (isset($response->info['total_time'])) { + if (!isset($response->info['total_time'])) { $response->info['total_time'] = microtime(true) - $response->info['start_time']; } diff --git a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php index b4a4a22083eb7..2f389bcc80c79 100644 --- a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php +++ b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php @@ -11,6 +11,24 @@ */ class MockResponseTest extends TestCase { + public function testTotalTimeShouldBeSimulatedWhenNotProvided() + { + $response = new MockResponse('body'); + $response = MockResponse::fromRequest('GET', 'https://example.com/file.txt', [], $response); + + $this->assertNotNull($response->getInfo('total_time')); + $this->assertGreaterThan(0.0, $response->getInfo('total_time')); + } + + public function testTotalTimeShouldNotBeSimulatedWhenProvided() + { + $totalTime = 4.2; + $response = new MockResponse('body', ['total_time' => $totalTime]); + $response = MockResponse::fromRequest('GET', 'https://example.com/file.txt', [], $response); + + $this->assertEquals($totalTime, $response->getInfo('total_time')); + } + public function testToArray() { $data = ['color' => 'orange', 'size' => 42]; From 3fb74abe627076904a77267ca42731a8d15e85c0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 25 Feb 2021 20:32:02 +0100 Subject: [PATCH 088/101] Speedup psalm --- .github/psalm/{cache => }/.gitignore | 0 .github/workflows/intl-data-tests.yml | 87 ++++++----- .github/workflows/phpunit-bridge.yml | 43 +++--- .github/workflows/psalm.yml | 85 +++------- .github/workflows/tests.yml | 213 ++++++++++++-------------- 5 files changed, 192 insertions(+), 236 deletions(-) rename .github/psalm/{cache => }/.gitignore (100%) diff --git a/.github/psalm/cache/.gitignore b/.github/psalm/.gitignore similarity index 100% rename from .github/psalm/cache/.gitignore rename to .github/psalm/.gitignore diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 17e26dad0d1ec..0925858432268 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -1,47 +1,50 @@ name: Intl data tests on: - push: - paths: - - 'src/Symfony/Component/Intl/Resources/data/**' - pull_request: - paths: - - 'src/Symfony/Component/Intl/Resources/data/**' + push: + paths: + - 'src/Symfony/Component/Intl/Resources/data/**' + pull_request: + paths: + - 'src/Symfony/Component/Intl/Resources/data/**' -jobs: +defaults: + run: + shell: bash - tests: - name: Tests (intl-data) - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Define the ICU version - run: | - SYMFONY_ICU_VERSION=$(php -r 'require "src/Symfony/Component/Intl/Intl.php"; echo Symfony\Component\Intl\Intl::getIcuStubVersion();') - echo "SYMFONY_ICU_VERSION=$SYMFONY_ICU_VERSION" >> $GITHUB_ENV - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - extensions: "zip,intl-${{env.SYMFONY_ICU_VERSION}}" - ini-values: "memory_limit=-1" - php-version: "7.4" - - - name: Install dependencies - run: | - echo "::group::composer update" - composer update --no-progress --no-suggest --ansi - echo "::endgroup::" - echo "::group::install phpunit" - ./phpunit install - echo "::endgroup::" - - - name: Report the ICU version - run: icu-config --version && php -i | grep 'ICU version' - - - name: Run intl-data tests - run: ./phpunit --group intl-data -v +jobs: + tests: + name: Tests (intl-data) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Define the ICU version + run: | + SYMFONY_ICU_VERSION=$(php -r 'require "src/Symfony/Component/Intl/Intl.php"; echo Symfony\Component\Intl\Intl::getIcuStubVersion();') + echo "SYMFONY_ICU_VERSION=$SYMFONY_ICU_VERSION" >> $GITHUB_ENV + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + extensions: "zip,intl-${{env.SYMFONY_ICU_VERSION}}" + ini-values: "memory_limit=-1" + php-version: "7.4" + + - name: Install dependencies + run: | + echo "::group::composer update" + composer update --no-progress --no-suggest --ansi + echo "::endgroup::" + echo "::group::install phpunit" + ./phpunit install + echo "::endgroup::" + + - name: Report the ICU version + run: icu-config --version && php -i | grep 'ICU version' + + - name: Run intl-data tests + run: ./phpunit --group intl-data -v diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index bdda65de1b6f5..8fa97980ff0f8 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -1,28 +1,31 @@ name: PhpUnitBridge on: - push: - paths: - - 'src/Symfony/Bridge/PhpUnit/**' - pull_request: - paths: - - 'src/Symfony/Bridge/PhpUnit/**' + push: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' + pull_request: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' -jobs: +defaults: + run: + shell: bash - lint: - name: Lint - runs-on: ubuntu-latest +jobs: + lint: + name: Lint + runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 + steps: + - name: Checkout + uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - php-version: "5.5" + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + php-version: "5.5" - - name: Lint - run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e ForV6 -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {} + - name: Lint + run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e ForV6 -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {} diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 11027c374e4fd..4c15203380059 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -3,6 +3,10 @@ name: Static analysis on: pull_request: ~ +defaults: + run: + shell: bash + jobs: psalm: name: Psalm @@ -17,81 +21,38 @@ jobs: ini-values: "memory_limit=-1" coverage: none - - name: Checkout PR + - name: Checkout target branch uses: actions/checkout@v2 with: - path: pr + ref: ${{ github.base_ref }} - - name: Checkout base + - name: Checkout PR uses: actions/checkout@v2 - with: - ref: ${{ github.base_ref }} - path: base - name: Configure composer run: | - cd base - COMPOSER_HOME="$(composer config home)" - ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" - echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV - - - name: Determine composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: composer-${{ github.base_ref }} - restore-keys: composer- + COMPOSER_HOME="$(composer config home)" + ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" + echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV - name: Install Psalm run: | - composer require psalm/phar - cp ./vendor/bin/psalm.phar base/psalm.phar - cp ./vendor/bin/psalm.phar pr/psalm.phar - - - name: Install dependencies for base - run: | - cd base - echo "::group::modify composer.json" - composer remove symfony/phpunit-bridge --no-interaction --no-update - composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher - echo "::endgroup::" - echo "::group::composer update" - composer update --no-progress --ansi - echo "::endgroup::" + echo "::group::modify composer.json" + composer remove --no-update --no-interaction symfony/phpunit-bridge + composer require --no-update psalm/phar phpunit/phpunit php-http/discovery psr/event-dispatcher + echo "::endgroup::" + echo "::group::composer update" + composer update --no-progress --ansi + git checkout composer.json + echo "::endgroup::" + ./vendor/bin/psalm.phar --version - name: Generate Psalm baseline run: | - cd base - ./psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress - - - name: Copy baseline - run: | - cp base/.github/psalm/psalm.baseline.xml pr/.github/psalm/psalm.baseline.xml - - - name: Install dependencies for PR - run: | - cd pr - echo "::group::modify composer.json" - composer remove symfony/phpunit-bridge --no-interaction --no-update - composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher - echo "::endgroup::" - echo "::group::composer update" - composer update --no-progress --ansi - echo "::endgroup::" - - - name: Cache Psalm - uses: actions/cache@v2 - with: - path: pr/.github/psalm/cache/ - key: psalm-${{ github.base_ref }} - restore-keys: psalm- + git checkout -m ${{ github.base_ref }} + ./vendor/bin/psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress + git checkout -m FETCH_HEAD - name: Psalm run: | - cd pr - ./psalm.phar --version - ./psalm.phar --output-format=github --no-progress + ./vendor/bin/psalm.phar --output-format=github --no-progress diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9ef0b10c04ee9..5e187c78f7fec 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,127 +1,116 @@ name: Tests on: - push: - pull_request: + push: + pull_request: jobs: - integration: - name: Integration - runs-on: ubuntu-latest + integration: + name: Integration + runs-on: ubuntu-latest - strategy: - matrix: - php: ['7.1', '7.4'] + strategy: + matrix: + php: ['7.1', '7.4'] - services: - ldap: - image: bitnami/openldap - ports: - - 3389:3389 - env: - LDAP_ADMIN_USERNAME: admin - LDAP_ADMIN_PASSWORD: symfony - LDAP_ROOT: dc=symfony,dc=com - LDAP_PORT_NUMBER: 3389 - LDAP_USERS: a - LDAP_PASSWORDS: a - redis: - image: redis:6.0.0 - ports: - - 6379:6379 - redis-cluster: - image: grokzen/redis-cluster:5.0.4 - ports: - - 7000:7000 - - 7001:7001 - - 7002:7002 - - 7003:7003 - - 7004:7004 - - 7005:7005 - - 7006:7006 - env: - STANDALONE: 1 - redis-sentinel: - image: bitnami/redis-sentinel:6.0 - ports: - - 26379:26379 - env: - REDIS_MASTER_HOST: redis - REDIS_MASTER_SET: redis_sentinel - REDIS_SENTINEL_QUORUM: 1 - memcached: - image: memcached:1.6.5 - ports: - - 11211:11211 - rabbitmq: - image: rabbitmq:3.8.3 - ports: - - 5672:5672 + services: + ldap: + image: bitnami/openldap + ports: + - 3389:3389 + env: + LDAP_ADMIN_USERNAME: admin + LDAP_ADMIN_PASSWORD: symfony + LDAP_ROOT: dc=symfony,dc=com + LDAP_PORT_NUMBER: 3389 + LDAP_USERS: a + LDAP_PASSWORDS: a + redis: + image: redis:6.0.0 + ports: + - 6379:6379 + redis-cluster: + image: grokzen/redis-cluster:5.0.4 + ports: + - 7000:7000 + - 7001:7001 + - 7002:7002 + - 7003:7003 + - 7004:7004 + - 7005:7005 + - 7006:7006 + env: + STANDALONE: 1 + redis-sentinel: + image: bitnami/redis-sentinel:6.0 + ports: + - 26379:26379 + env: + REDIS_MASTER_HOST: redis + REDIS_MASTER_SET: redis_sentinel + REDIS_SENTINEL_QUORUM: 1 + memcached: + image: memcached:1.6.5 + ports: + - 11211:11211 + rabbitmq: + image: rabbitmq:3.8.3 + ports: + - 5672:5672 - steps: - - name: Checkout - uses: actions/checkout@v2 + steps: + - name: Checkout + uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - extensions: "memcached,redis,xsl,ldap" - ini-values: "memory_limit=-1" - php-version: "${{ matrix.php }}" + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + extensions: "memcached,redis,xsl,ldap" + ini-values: "memory_limit=-1" + php-version: "${{ matrix.php }}" - - name: Load fixtures - uses: docker://bitnami/openldap - with: - entrypoint: /bin/bash - args: -c "(/opt/bitnami/openldap/bin/ldapwhoami -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony||sleep 5) && /opt/bitnami/openldap/bin/ldapadd -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif && /opt/bitnami/openldap/bin/ldapdelete -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony cn=a,ou=users,dc=symfony,dc=com" + - name: Load fixtures + uses: docker://bitnami/openldap + with: + entrypoint: /bin/bash + args: -c "(/opt/bitnami/openldap/bin/ldapwhoami -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony||sleep 5) && /opt/bitnami/openldap/bin/ldapadd -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif && /opt/bitnami/openldap/bin/ldapdelete -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony cn=a,ou=users,dc=symfony,dc=com" - - name: Configure composer - run: | - COMPOSER_HOME="$(composer config home)" - composer self-update - ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" - echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV + - name: Configure composer + run: | + COMPOSER_HOME="$(composer config home)" + composer self-update + ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" + echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV - - name: Determine composer cache directory - id: composer-cache - run: echo "::set-output name=directory::$(composer config cache-dir)" + - name: Install dependencies + run: | + echo "::group::composer update" + composer update --no-progress --ansi + echo "::endgroup::" + echo "::group::install phpunit" + ./phpunit install + echo "::endgroup::" - - name: Cache composer dependencies - uses: actions/cache@v1 - with: - path: ${{ steps.composer-cache.outputs.directory }} - key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ matrix.php }}-composer- + - name: Run tests + run: ./phpunit --group integration -v + env: + REDIS_HOST: localhost + REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005' + REDIS_SENTINEL_HOSTS: 'localhost:26379' + REDIS_SENTINEL_SERVICE: redis_sentinel + MESSENGER_REDIS_DSN: redis://127.0.0.1:7006/messages + MESSENGER_AMQP_DSN: amqp://localhost/%2f/messages + MEMCACHED_HOST: localhost + LDAP_HOST: localhost + LDAP_PORT: 3389 - - name: Install dependencies - run: | - echo "::group::composer update" - composer update --no-progress --ansi - echo "::endgroup::" - echo "::group::install phpunit" - ./phpunit install - echo "::endgroup::" - - - name: Run tests - run: ./phpunit --group integration -v - env: - REDIS_HOST: localhost - REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005' - REDIS_SENTINEL_HOSTS: 'localhost:26379' - REDIS_SENTINEL_SERVICE: redis_sentinel - MESSENGER_REDIS_DSN: redis://127.0.0.1:7006/messages - MESSENGER_AMQP_DSN: amqp://localhost/%2f/messages - MEMCACHED_HOST: localhost - LDAP_HOST: localhost - LDAP_PORT: 3389 - - - name: Run HTTP push tests - if: matrix.php == '7.4' - 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 /usr/local/bin/vulcain:/usr/local/bin/vulcain -w /app php:7.4-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push - sudo rm -rf .phpunit - [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit + - name: Run HTTP push tests + if: matrix.php == '7.4' + 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 /usr/local/bin/vulcain:/usr/local/bin/vulcain -w /app php:7.4-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push + sudo rm -rf .phpunit + [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit From 2ae5c33c80601041941217967ca1260328d062b3 Mon Sep 17 00:00:00 2001 From: DemigodCode <36764562+DemigodCode@users.noreply.github.com> Date: Thu, 25 Feb 2021 02:07:32 +0100 Subject: [PATCH 089/101] [Cache] Add server-commands support for Predis Replication Environments --- .../Component/Cache/Adapter/RedisTagAwareAdapter.php | 10 +++++++++- src/Symfony/Component/Cache/Traits/RedisTrait.php | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php index ed20bd2308978..9409c346fb817 100644 --- a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php @@ -13,6 +13,7 @@ use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\PredisCluster; +use Predis\Connection\Aggregate\ReplicationInterface; use Predis\Response\Status; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Exception\LogicException; @@ -278,7 +279,14 @@ private function getRedisEvictionPolicy(): string return $this->redisEvictionPolicy; } - foreach ($this->getHosts() as $host) { + $hosts = $this->getHosts(); + $host = reset($hosts); + if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { + // Predis supports info command only on the master in replication environments + $hosts = [$host->getClientFor('master')]; + } + + foreach ($hosts as $host) { $info = $host->info('Memory'); $info = $info['Memory'] ?? $info; diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index bf2ca1073b5df..9098df9465f9d 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -13,6 +13,7 @@ use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\RedisCluster; +use Predis\Connection\Aggregate\ReplicationInterface; use Predis\Response\Status; use Symfony\Component\Cache\Exception\CacheException; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -367,7 +368,14 @@ protected function doClear($namespace) $evalArgs = [[$namespace], 0]; } - foreach ($this->getHosts() as $host) { + $hosts = $this->getHosts(); + $host = reset($hosts); + if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { + // Predis supports info command only on the master in replication environments + $hosts = [$host->getClientFor('master')]; + } + + foreach ($hosts as $host) { if (!isset($namespace[0])) { $cleared = $host->flushDb() && $cleared; continue; From 1a26ed43e7c9cf05bebcc6113bd41aba455a23e6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Feb 2021 11:19:16 +0100 Subject: [PATCH 090/101] improve exception message if symfony/security-csrf is missing --- src/Symfony/Component/Form/FormRenderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 64e7cf3746561..3aec936fd95a5 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -59,7 +59,7 @@ public function setTheme(FormView $view, $themes, $useDefaultThemes = true) public function renderCsrfToken($tokenId) { if (null === $this->csrfTokenManager) { - throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().'); + throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct(). Try running "composer require symfony/security-csrf".'); } return $this->csrfTokenManager->getToken($tokenId)->getValue(); From c31670866972e0889ec622d726953476a5201502 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Feb 2021 13:01:23 +0100 Subject: [PATCH 091/101] zero parts can be omitted in date interval input --- .../Serializer/Normalizer/DateIntervalNormalizer.php | 2 +- .../Tests/Normalizer/DateIntervalNormalizerTest.php | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php index 21abe49bb14db..74d43a74bda9b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php @@ -105,7 +105,7 @@ public function denormalize($data, $type, $format = null, array $context = []) $dateIntervalFormat = substr($dateIntervalFormat, 2); break; } - $valuePattern = '/^'.$signPattern.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?P<$1>\d+)$2', $dateIntervalFormat).'$/'; + $valuePattern = '/^'.$signPattern.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?:(?P<$1>\d+)$2)?', preg_replace('/(T.*)$/', '($1)?', $dateIntervalFormat)).'$/'; if (!preg_match($valuePattern, $data)) { throw new UnexpectedValueException(sprintf('Value "%s" contains intervals not accepted by format "%s".', $data, $dateIntervalFormat)); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php index beb1288e4470c..6badbb07dd0bd 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php @@ -124,6 +124,14 @@ public function testLegacyDenormalizeUsingFormatPassedInConstructor($format, $in $this->doTestDenormalizeUsingFormatPassedInConstructor($format, $input, $output, true); } + public function testDenormalizeIntervalsWithOmittedPartsBeingZero() + { + $normalizer = new DateIntervalNormalizer(); + + $this->assertDateIntervalEquals($this->getInterval('P3Y2M4DT0H0M0S'), $normalizer->denormalize('P3Y2M4D', \DateInterval::class)); + $this->assertDateIntervalEquals($this->getInterval('P0Y0M0DT12H34M0S'), $normalizer->denormalize('PT12H34M', \DateInterval::class)); + } + private function doTestDenormalizeUsingFormatPassedInConstructor($format, $input, $output, bool $legacy = false) { $normalizer = $legacy ? new DateIntervalNormalizer($format) : new DateIntervalNormalizer([DateIntervalNormalizer::FORMAT_KEY => $format]); From 4721097cab1681cf9bc49f2961e9d1cb9d4ad9d2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 26 Feb 2021 14:50:45 +0100 Subject: [PATCH 092/101] deal with indented heredoc/nowdoc tokens --- .../Translation/Extractor/PhpExtractor.php | 13 ++++++++++++ .../Tests/Extractor/PhpExtractorTest.php | 21 +++++++++++++++++++ .../extractor-7.3/translation.html.php | 13 ++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/extractor-7.3/translation.html.php diff --git a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php index 88811418ca643..32389c677cacd 100644 --- a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php +++ b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php @@ -178,6 +178,19 @@ private function getValue(\Iterator $tokenIterator) } break; case \T_END_HEREDOC: + if ($indentation = strspn($t[1], ' ')) { + $docPartWithLineBreaks = $docPart; + $docPart = ''; + + foreach (preg_split('~(\r\n|\n|\r)~', $docPartWithLineBreaks, -1, \PREG_SPLIT_DELIM_CAPTURE) as $str) { + if (\in_array($str, ["\r\n", "\n", "\r"], true)) { + $docPart .= $str; + } else { + $docPart .= substr($str, $indentation); + } + } + } + $message .= PhpStringTokenParser::parseDocString($docToken, $docPart); $docToken = ''; $docPart = ''; diff --git a/src/Symfony/Component/Translation/Tests/Extractor/PhpExtractorTest.php b/src/Symfony/Component/Translation/Tests/Extractor/PhpExtractorTest.php index a6d7c5001cff7..5a693977da6e4 100644 --- a/src/Symfony/Component/Translation/Tests/Extractor/PhpExtractorTest.php +++ b/src/Symfony/Component/Translation/Tests/Extractor/PhpExtractorTest.php @@ -75,6 +75,27 @@ public function testExtraction($resource) $this->assertEquals(['sources' => [$filename.':43']], $catalogue->getMetadata('other-domain-test-no-params-short-array', 'not_messages')); } + /** + * @requires PHP 7.3 + */ + public function testExtractionFromIndentedHeredocNowdoc() + { + $catalogue = new MessageCatalogue('en'); + + $extractor = new PhpExtractor(); + $extractor->setPrefix('prefix'); + $extractor->extract(__DIR__.'/../fixtures/extractor-7.3/translation.html.php', $catalogue); + + $expectedCatalogue = [ + 'messages' => [ + "heredoc\nindented\n further" => "prefixheredoc\nindented\n further", + "nowdoc\nindented\n further" => "prefixnowdoc\nindented\n further", + ], + ]; + + $this->assertEquals($expectedCatalogue, $catalogue->all()); + } + public function resourcesProvider() { $directory = __DIR__.'/../fixtures/extractor/'; diff --git a/src/Symfony/Component/Translation/Tests/fixtures/extractor-7.3/translation.html.php b/src/Symfony/Component/Translation/Tests/fixtures/extractor-7.3/translation.html.php new file mode 100644 index 0000000000000..35ffe8812ed66 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/fixtures/extractor-7.3/translation.html.php @@ -0,0 +1,13 @@ +This template is used for translation message extraction tests +trans(<< +trans(<<<'EOF' + nowdoc + indented + further + EOF +); ?> From 3c47e03e92177ff3c889fefeeaf68a1b102b438d Mon Sep 17 00:00:00 2001 From: Nyholm Date: Tue, 2 Mar 2021 10:27:35 +0100 Subject: [PATCH 093/101] Specify that we run CI on Ubuntu-20.04 --- .github/workflows/intl-data-tests.yml | 2 +- .github/workflows/phpunit-bridge.yml | 2 +- .github/workflows/tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 0925858432268..0ca0322281448 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -15,7 +15,7 @@ defaults: jobs: tests: name: Tests (intl-data) - runs-on: ubuntu-latest + runs-on: Ubuntu-20.04 steps: - name: Checkout diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 8fa97980ff0f8..b503ce48d8a17 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -15,7 +15,7 @@ defaults: jobs: lint: name: Lint - runs-on: ubuntu-latest + runs-on: Ubuntu-20.04 steps: - name: Checkout diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5e187c78f7fec..603c05bff80d7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: integration: name: Integration - runs-on: ubuntu-latest + runs-on: Ubuntu-20.04 strategy: matrix: From bd6930effe9bdf4674cd1a00dc677bd585537efa Mon Sep 17 00:00:00 2001 From: Nyholm Date: Tue, 2 Mar 2021 12:28:15 +0100 Subject: [PATCH 094/101] [Messenger][SQS] Document missing option --- .../Messenger/Bridge/AmazonSqs/Transport/Connection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php index 68e41b5eff7f7..8925572459171 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php @@ -94,6 +94,7 @@ public function __destruct() * * wait_time: long polling duration in seconds (Default: 20) * * poll_timeout: amount of seconds the transport should wait for new message * * visibility_timeout: amount of seconds the message won't be visible + * * sslmode: Can be "disable" to use http for a custom endpoint * * auto_setup: Whether the queue should be created automatically during send / get (Default: true) */ public static function fromDsn(string $dsn, array $options = [], HttpClientInterface $client = null): self From 4b70db1e8533c4f4de65f560475d8a1836c05a33 Mon Sep 17 00:00:00 2001 From: Junaid Farooq Date: Tue, 2 Mar 2021 10:49:57 +0530 Subject: [PATCH 095/101] [Security] Remove unnecessary inherited doc annotation --- .../Component/Security/Core/User/User.php | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Security/Core/User/User.php b/src/Symfony/Component/Security/Core/User/User.php index 5429baa0cd01b..fa5cfb524e374 100644 --- a/src/Symfony/Component/Security/Core/User/User.php +++ b/src/Symfony/Component/Security/Core/User/User.php @@ -83,7 +83,14 @@ public function getUsername(): string } /** - * {@inheritdoc} + * Checks whether the user's account has expired. + * + * Internally, if this method returns false, the authentication system + * will throw an AccountExpiredException and prevent login. + * + * @return bool true if the user's account is non expired, false otherwise + * + * @see AccountExpiredException */ public function isAccountNonExpired(): bool { @@ -91,7 +98,14 @@ public function isAccountNonExpired(): bool } /** - * {@inheritdoc} + * Checks whether the user is locked. + * + * Internally, if this method returns false, the authentication system + * will throw a LockedException and prevent login. + * + * @return bool true if the user is not locked, false otherwise + * + * @see LockedException */ public function isAccountNonLocked(): bool { @@ -99,7 +113,14 @@ public function isAccountNonLocked(): bool } /** - * {@inheritdoc} + * Checks whether the user's credentials (password) has expired. + * + * Internally, if this method returns false, the authentication system + * will throw a CredentialsExpiredException and prevent login. + * + * @return bool true if the user's credentials are non expired, false otherwise + * + * @see CredentialsExpiredException */ public function isCredentialsNonExpired(): bool { @@ -107,7 +128,14 @@ public function isCredentialsNonExpired(): bool } /** - * {@inheritdoc} + * Checks whether the user is enabled. + * + * Internally, if this method returns false, the authentication system + * will throw a DisabledException and prevent login. + * + * @return bool true if the user is enabled, false otherwise + * + * @see DisabledException */ public function isEnabled(): bool { From a9de390676996fbebdce6be1e9754b7f2d4e62ab Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 3 Mar 2021 13:08:43 +0100 Subject: [PATCH 096/101] fix parsing calls of methods named "method" --- .../Component/DependencyInjection/Loader/YamlFileLoader.php | 2 +- .../DependencyInjection/Tests/Fixtures/yaml/alt_call.yaml | 2 ++ .../DependencyInjection/Tests/Loader/YamlFileLoaderTest.php | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 1133254c6ce40..e9b09cc2eb67d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -471,7 +471,7 @@ private function parseDefinition(string $id, $service, string $file, array $defa throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in "%s"?', $id, $k, $file)); } - if (isset($call['method'])) { + if (isset($call['method']) && \is_string($call['method'])) { $method = $call['method']; $args = $call['arguments'] ?? []; $returnsClone = $call['returns_clone'] ?? false; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/alt_call.yaml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/alt_call.yaml index 26cf9e628c6fd..fb7f3440ded3c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/alt_call.yaml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/alt_call.yaml @@ -3,3 +3,5 @@ services: calls: - foo: [1, 2, 3] - bar: !returns_clone [1, 2, 3] + - method: + - url diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 2e15f615fb5e1..b20302cf977ba 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -968,6 +968,7 @@ public function testAlternativeMethodCalls() $expected = [ ['foo', [1, 2, 3]], ['bar', [1, 2, 3], true], + ['method', ['url']], ]; $this->assertSame($expected, $container->getDefinition('foo')->getMethodCalls()); From 1b84d5d23b1b88804f8eb189031eec28585d202f Mon Sep 17 00:00:00 2001 From: OxanaKozlova Date: Wed, 24 Feb 2021 15:36:10 +0300 Subject: [PATCH 097/101] Add translation for Belarusian --- .../Resources/translations/validators.be.xlf | 60 +++++++++---------- .../Resources/translations/security.be.xlf | 4 +- .../Resources/translations/validators.be.xlf | 12 ++-- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.be.xlf b/src/Symfony/Component/Form/Resources/translations/validators.be.xlf index 042722eba89eb..0513ca1dc9f7f 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.be.xlf @@ -16,123 +16,123 @@ This value is not a valid HTML5 color. - This value is not a valid HTML5 color. + Значэнне не з'яўляецца карэктным HTML5 колерам. Please enter a valid birthdate. - Please enter a valid birthdate. + Калі ласка, увядзіце карэктную дату нараджэння. The selected choice is invalid. - The selected choice is invalid. + Выбраны варыянт некарэктны. The collection is invalid. - The collection is invalid. + Калекцыя некарэктна. Please select a valid color. - Please select a valid color. + Калі ласка, выберыце карэктны колер. Please select a valid country. - Please select a valid country. + Калі ласка, выберыце карэктную краіну. Please select a valid currency. - Please select a valid currency. + Калі ласка, выберыце карэктную валюту. Please choose a valid date interval. - Please choose a valid date interval. + Калі ласка, выберыце карэктны інтэрвал дат. Please enter a valid date and time. - Please enter a valid date and time. + Калі ласка, увядзіце карэктныя дату і час. Please enter a valid date. - Please enter a valid date. + Калі ласка, увядзіце карэктную дату. Please select a valid file. - Please select a valid file. + Калі ласка, выберыце карэктны файл. The hidden field is invalid. - The hidden field is invalid. + Значэнне схаванага поля некарэктна. Please enter an integer. - Please enter an integer. + Калі ласка, увядзіце цэлы лік. Please select a valid language. - Please select a valid language. + Калі ласка, выберыце карэктную мову. Please select a valid locale. - Please select a valid locale. + Калі ласка, выберыце карэктную лакаль. Please enter a valid money amount. - Please enter a valid money amount. + Калі ласка, увядзіце карэктную колькасць грошай. Please enter a number. - Please enter a number. + Калі ласка, увядзіце нумар. The password is invalid. - The password is invalid. + Няправільны пароль. Please enter a percentage value. - Please enter a percentage value. + Калі ласка, увядзіце працэнтнае значэнне. The values do not match. - The values do not match. + Значэнні не супадаюць. Please enter a valid time. - Please enter a valid time. + Калі ласка, увядзіце карэктны час. Please select a valid timezone. - Please select a valid timezone. + Калі ласка, выберыце карэктны гадзінны пояс. Please enter a valid URL. - Please enter a valid URL. + Калі ласка, увядзіце карэктны URL. Please enter a valid search term. - Please enter a valid search term. + Калі ласка, увядзіце карэктны пошукавы запыт. Please provide a valid phone number. - Please provide a valid phone number. + Калі ласка, увядзіце карэктны нумар тэлефона. The checkbox has an invalid value. - The checkbox has an invalid value. + Флажок мае некарэктнае значэнне. Please enter a valid email address. - Please enter a valid email address. + Калі ласка, увядзіце карэктны адрас электроннай пошты. Please select a valid option. - Please select a valid option. + Калі ласка, выберыце карэктны варыянт. Please select a valid range. - Please select a valid range. + Калі ласка, выберыце карэктны дыяпазон. Please enter a valid week. - Please enter a valid week. + Калі ласка, увядзіце карэктны тыдзень. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf index 216df88ed2561..b24a5c421acfa 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf @@ -64,11 +64,11 @@ Too many failed login attempts, please try again later. - Too many failed login attempts, please try again later. + Зашмат няўдалых спроб уваходу, калі ласка, паспрабуйце пазней. Invalid or expired login link. - Invalid or expired login link. + Спасылка для ўваходу несапраўдная або пратэрмінаваная. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf index e12c53c36e8b0..5f9988ef3cdbe 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf @@ -364,27 +364,27 @@ This value should be between {{ min }} and {{ max }}. - This value should be between {{ min }} and {{ max }}. + Значэнне павінна быць паміж {{min}} і {{max}}. This value is not a valid hostname. - This value is not a valid hostname. + Значэнне не з'яўляецца карэктным імем хаста. The number of elements in this collection should be a multiple of {{ compared_value }}. - The number of elements in this collection should be a multiple of {{ compared_value }}. + Колькасць элементаў у гэтай калекцыі павінна быць кратным {{compared_value}}. This value should satisfy at least one of the following constraints: - This value should satisfy at least one of the following constraints: + Значэнне павінна задавальняць як мінімум аднаму з наступных абмежаванняў: Each element of this collection should satisfy its own set of constraints. - Each element of this collection should satisfy its own set of constraints. + Кожны элемент гэтай калекцыі павінен задавальняць свайму ўласнаму набору абмежаванняў. This value is not a valid International Securities Identification Number (ISIN). - This value is not a valid International Securities Identification Number (ISIN). + Значэнне не з'яўляецца карэктным міжнародным ідэнтыфікацыйным нумарам каштоўных папер (ISIN). From e67ef5bbfff768733f299f24f908ac9486a56fb3 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 3 Mar 2021 23:49:57 +0100 Subject: [PATCH 098/101] [Validator] Fix return types --- src/Symfony/Component/Validator/Constraint.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 7cd3a68b869f6..2683c68360fdb 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -25,7 +25,7 @@ * * Constraint instances are immutable and serializable. * - * @property array $groups The groups that the constraint belongs to + * @property string[] $groups The groups that the constraint belongs to * * @author Bernhard Schussek */ @@ -246,7 +246,7 @@ public function getDefaultOption() * * Override this method if you want to define required options. * - * @return array + * @return string[] * * @see __construct() */ @@ -276,7 +276,7 @@ public function validatedBy() * This method should return one or more of the constants * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT. * - * @return string|array One or more constant values + * @return string|string[] One or more constant values */ public function getTargets() { From 3371e1cf39a8ea2cff975d2241ce0263a7b82e2d Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 1 Mar 2021 17:26:03 +0100 Subject: [PATCH 099/101] [Messenger] Doctrine setup with migrations --- .../Tests/Transport/PostgreSqlConnectionTest.php | 14 +++++++++++++- .../Doctrine/Transport/PostgreSqlConnection.php | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/PostgreSqlConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/PostgreSqlConnectionTest.php index fe1f2c130529e..7b17e41af8d68 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/PostgreSqlConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/PostgreSqlConnectionTest.php @@ -49,7 +49,19 @@ public function testGetExtraSetupSql() $table = new Table('queue_table'); $table->addOption('_symfony_messenger_table_name', 'queue_table'); - $this->assertStringContainsString('CREATE TRIGGER', implode("\n", $connection->getExtraSetupSqlForTable($table))); + $sql = implode("\n", $connection->getExtraSetupSqlForTable($table)); + + /* + * We need to start a transaction for the following commands to work properly: + * doctrine:schema:create + * messenger:setup-transports + * doctrine:migrations:diff and doctrine:migrations:migrate + */ + $this->assertStringContainsString('BEGIN;', $sql); + $this->assertStringContainsString('CREATE TRIGGER', $sql); + + // We MUST NOT commit, that will mess with the PDO in PHP 8 + $this->assertStringNotContainsString('COMMIT;', $sql); } public function testGetExtraSetupSqlWrongTable() diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php index 4490c7521f366..eede0d9262502 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/PostgreSqlConnection.php @@ -87,7 +87,7 @@ public function setup(): void { parent::setup(); - $this->executeStatement('BEGIN;'.implode("\n", $this->getTriggerSql()).'COMMIT;'); + $this->executeStatement(implode("\n", $this->getTriggerSql())); } /** @@ -109,6 +109,7 @@ public function getExtraSetupSqlForTable(Table $createdTable): array private function getTriggerSql(): array { return [ + 'BEGIN;', sprintf('LOCK TABLE %s;', $this->configuration['table_name']), // create trigger function sprintf(<<<'SQL' From 392584945d450c992622500a7199672485024d31 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 4 Mar 2021 19:05:47 +0100 Subject: [PATCH 100/101] Update CHANGELOG for 5.2.4 --- CHANGELOG-5.2.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG-5.2.md b/CHANGELOG-5.2.md index 7fe615b1fcca4..b77697fd01f15 100644 --- a/CHANGELOG-5.2.md +++ b/CHANGELOG-5.2.md @@ -7,6 +7,56 @@ in 5.2 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/v5.2.0...v5.2.1 +* 5.2.4 (2021-03-04) + + * bug #40336 [Messenger] Doctrine setup with migrations (Nyholm) + * bug #40318 [Translation] deal with indented heredoc/nowdoc tokens (xabbuh) + * bug #40350 [DependencyInjection] fix parsing calls of methods named "method" (xabbuh) + * bug #40316 [Serializer] zero parts can be omitted in date interval input (xabbuh) + * bug #40239 MockResponse total_time should not be simulated when provided (Pierrick VIGNAND) + * bug #40299 [Cache] Add server-commands support for Predis Replication Environments (DemigodCode) + * bug #40231 [HttpKernel] Configure `session.cookie_secure` earlier (tamcy) + * bug #40283 [Translation] Make `name` attribute optional in xliff2 (MarieMinasyan) + * bug #40286 [Security] #[CurrentUser] arguments should resolve to null for "anon." (chalasr) + * bug #40281 [FrameworkBundle] Allow x-forwarded-prefix trusted header in config (drupol) + * bug #39599 [Cache] Fix Redis TLS scheme `rediss` for Redis connection (misaert) + * bug #40244 [Routing] fix conflict with param named class in attribute (nlhommet) + * bug #40273 [Cache] fix setting items' metadata on commit() (nicolas-grekas) + * bug #40258 [Form] Ignoring invalid forms from delete_empty behavior in CollectionType (yceruto) + * bug #40246 [EventDispatcher] fix registering subscribers twice on edge-case (nicolas-grekas) + * bug #40162 [Intl] fix Locale::getFallback() throwing exception on long $locale (AmirHo3ein13) + * bug #40211 [Validator] fix taking error message from the correct violation (xabbuh) + * bug #40208 [PropertyInfo] fix resolving self to name of the analyzed class (xabbuh) + * bug #40209 [WebLink] Escape double quotes in attributes values (fancyweb) + * bug #40192 [Console] fix QuestionHelper::getHiddenResponse() not working with space in project directory name (Yendric) + * bug #40203 [String] Check if function exists before declaring it (Nyholm) + * bug #40175 [PropertyInfo]  use the right context for properties defined in traits (xabbuh) + * bug #40172 [Translation] Allow using dashes in locale when linting Xliff files (localheinz) + * bug #39671 [Worflow] Fixed GuardListener when using the new Security system (lyrixx) + * bug #40187 [Console] Fix PHP 8.1 null error for preg_match flag (kylekatarnls) + * bug #39659 [Form] keep valid submitted choices when additional choices are submitted (xabbuh) + * bug #40188 [HttpFoundation] Fix PHP 8.1 null values (kylekatarnls) + * bug #40167 [DependencyInjection] Definition::removeMethodCall should remove all matching calls (ruudk) + * bug #40160 [PropertyInfo] fix extracting mixed type-hinted property types (xabbuh) + * bug #40040 [Finder] Use a lazyIterator to close files descriptors when no longer used (jderusse) + * bug #40141 [RateLimiter] Fix sliding_window misbehaving with stale records (xesxen) + * bug #40135 [FrameworkBundle] Fix freshness checks with boolean parameters on routes (HypeMC) + * bug #40138 [FrameworkBundle] fix registering "annotations.cache" on the "container.hot_path" (nicolas-grekas) + * bug #40137 [Form] forward the label_html option to expanded choice fields (xabbuh) + * bug #40116 [FrameworkBundle][Translator] scan directories for translations sequentially (xabbuh) + * bug #40124 [Form] merge translation parameters with value configured for parent form (xabbuh) + * bug #40104 [HttpKernel] [Kernel] Silence failed deprecations logs writes (fancyweb) + * bug #40098 [DependencyInjection] fix tracking of changes to vendor/ dirs (nicolas-grekas) + * bug #39980 [Mailer][Mime] Update inline part names with newly generated ContentId (ddegentesh) + * bug #40043 [HttpFoundation] Setting `REQUEST_TIME_FLOAT` when constructing a Request object (ctasada) + * bug #40050 [FrameworkBundle][Translator] Fixed updating catalogue metadata from Intl domain (yceruto) + * bug #40080 Fix Request with DNS issue not retried (jderusse) + * bug #40089 [SecurityBundle] role_names variable instead of roles (wickedOne) + * bug #40042 [Doctrine] Restore priority for EventSubscribers (jderusse) + * bug #40066 [ErrorHandler] fix parsing return types in DebugClassLoader (nicolas-grekas) + * bug #40065 [ErrorHandler] fix handling messages with null bytes from anonymous classes (nicolas-grekas) + * bug #40067 [PhpUnitBridge] fix reporting deprecations when they come from DebugClassLoader (nicolas-grekas) + * 5.2.3 (2021-02-03) * bug #39954 [Mailer][Mime] Fix case-sensitive handling of header names (piku235) From ff8cb872d340497a245ebb9288d79ef236bcdca2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 4 Mar 2021 19:05:55 +0100 Subject: [PATCH 101/101] Update VERSION for 5.2.4 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 1ff31b5593851..7c8b33d77c6bc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - public const VERSION = '5.2.4-DEV'; + public const VERSION = '5.2.4'; public const VERSION_ID = 50204; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 2; public const RELEASE_VERSION = 4; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '07/2021'; public const END_OF_LIFE = '07/2021';