From 85989c3678d243e229f929008ede8b2e24c0c3fa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 29 Dec 2020 14:49:11 +0100 Subject: [PATCH 1/7] keep valid submitted choices when additional choices are submitted --- .../FrameworkBundle/Resources/config/form.xml | 1 + .../Form/Extension/Core/Type/ChoiceType.php | 74 +++++++++++++++---- .../Extension/Core/Type/ChoiceTypeTest.php | 25 ++++--- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 17598fa958..05a58c4c4c 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 4297460d34..bd2985b313 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\ChoicesToValuesTransfo 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\Form\FormView; 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 @@ class ChoiceType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { + $unknownValues = []; $choiceList = $this->createChoiceList($options); $builder->setAttribute('choice_list', $choiceList); @@ -81,10 +94,12 @@ class ChoiceType extends AbstractType $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 @@ class ChoiceType extends AbstractType // 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 @@ class ChoiceType extends AbstractType $unknownValues = $valueMap; // Reconstruct the data as mapping from child names to values - $data = []; + $knownValues = []; - /** @var FormInterface $child */ - foreach ($form as $child) { - $value = $child->getConfig()->getOption('value'); + 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])) { - $data[$child->getName()] = $value; - unset($unknownValues[$value]); - continue; + // 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 @@ class ChoiceType extends AbstractType // 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 @@ abstract class Client * @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 77d1664c74..8bd47407fa 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\NodeInterface; 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 5932472ec6..e67a2a8ed7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php @@ -31,7 +31,7 @@ class ResolveClassPass implements CompilerPassInterface } 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 132849439e..3d16ad6f01 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 13d02ebb7c..4b10acd9c5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -386,7 +386,7 @@ class XmlFileLoader extends FileLoader } /** - * 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 69b9a1c2d3..89e5fa2ea2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php @@ -86,7 +86,7 @@ class ResolveClassPassTest extends TestCase 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 731eb99343..083391a0bb 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -14,7 +14,7 @@ namespace Symfony\Component\DomCrawler\Field; /** * 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 ec323179eb..3b2123bd96 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 8c96195485..dec5bbf6ac 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 @@ class DateTimeType extends AbstractType { $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 f6cca90814..0b9a4ffab3 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 @@ class DateType extends AbstractType { $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 58af6f1d45..44acf3efb4 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 @@ class TimeType extends AbstractType '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 fddf2512c4..2bf2d68446 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderUtils.php +++ b/src/Symfony/Component/HttpFoundation/HeaderUtils.php @@ -146,7 +146,7 @@ class HeaderUtils } /** - * 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 079000e655..aec9177e7e 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1716,7 +1716,7 @@ class Request } /** - * 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 b90dfd645d..c777283b66 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -806,7 +806,7 @@ class RequestTest extends TestCase ['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 15a37cf58b..b335a4f207 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -205,7 +205,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } /** - * 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 91b758e9ac..87f68cf324 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php @@ -150,7 +150,7 @@ class Query extends AbstractQuery } /** - * 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 e65fa5e042..98c6454e36 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -366,7 +366,7 @@ class PdoStore implements StoreInterface } /** - * 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 1d167b43b1..2c078d14c3 100644 --- a/src/Symfony/Component/Mime/Header/ParameterizedHeader.php +++ b/src/Symfony/Component/Mime/Header/ParameterizedHeader.php @@ -102,7 +102,7 @@ final class ParameterizedHeader extends UnstructuredHeader } /** - * 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 6a2e0970f9..8c66b688a9 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php +++ b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php @@ -66,7 +66,7 @@ interface RememberMeServicesInterface * 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 fbef93d619..efeeb0a86a 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 cd329e91c6..7d33ca0c92 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php @@ -106,7 +106,7 @@ class XmlFileLoader extends FileLoader } /** - * 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 e96effbcdb..426635edb5 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -53,11 +53,11 @@ class XliffLintCommand extends Command 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 1f2e62ced6..accd023ab5 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -19,19 +19,19 @@ use Symfony\Component\Translation\Exception\InvalidResourceException; 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 d80d96ec3b..85a9d0e433 100644 --- a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php +++ b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php @@ -14,7 +14,7 @@ namespace Symfony\Component\WebLink; 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 6/7] [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 5032b340a1..d43187d281 100644 --- a/src/Symfony/Component/Console/Input/StringInput.php +++ b/src/Symfony/Component/Console/Input/StringInput.php @@ -52,12 +52,12 @@ class StringInput extends ArgvInput $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 7/7] 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 fb09d62c00..4ab97aaf90 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -1237,7 +1237,7 @@ class Response */ 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'); }