diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index 39511c15c6..866feb6e1a 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -47,7 +47,10 @@ abstract class BaseNode implements NodeInterface */ public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) { - if (false !== strpos($name = (string) $name, $pathSeparator)) { + if (null === $name) { + $name = ''; + } + if (false !== strpos($name, $pathSeparator)) { throw new \InvalidArgumentException('The name must not contain "'.$pathSeparator.'".'); } diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index a771a43cd2..948a68f6b8 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -41,7 +41,7 @@ abstract class NodeDefinition implements NodeParentInterface public function __construct(?string $name, NodeParentInterface $parent = null) { $this->parent = $parent; - $this->name = $name; + $this->name = $name ?? ''; } /** diff --git a/src/Symfony/Component/Config/Resource/GlobResource.php b/src/Symfony/Component/Config/Resource/GlobResource.php index fce8f6e206..e33cafc6e0 100644 --- a/src/Symfony/Component/Config/Resource/GlobResource.php +++ b/src/Symfony/Component/Config/Resource/GlobResource.php @@ -39,7 +39,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface * * @throws \InvalidArgumentException */ - public function __construct(?string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) + public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) { $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false); $this->pattern = $pattern; diff --git a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php index b59ace46f9..0b2e3fb6b9 100644 --- a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php @@ -71,6 +71,7 @@ class FileLoaderTest extends TestCase public function testImportWithGlobLikeResource() { $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock(); + $locatorMock->expects($this->once())->method('locate')->willReturn(''); $loader = new TestFileLoader($locatorMock); $this->assertSame('[foo]', $loader->import('[foo]')); @@ -79,6 +80,7 @@ class FileLoaderTest extends TestCase public function testImportWithNoGlobMatch() { $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock(); + $locatorMock->expects($this->once())->method('locate')->willReturn(''); $loader = new TestFileLoader($locatorMock); $this->assertNull($loader->import('./*.abc')); diff --git a/src/Symfony/Component/DomCrawler/AbstractUriElement.php b/src/Symfony/Component/DomCrawler/AbstractUriElement.php index 1ef51df59b..ead9dca25b 100644 --- a/src/Symfony/Component/DomCrawler/AbstractUriElement.php +++ b/src/Symfony/Component/DomCrawler/AbstractUriElement.php @@ -24,7 +24,7 @@ abstract class AbstractUriElement protected $node; /** - * @var string The method to use for the element + * @var string|null The method to use for the element */ protected $method; @@ -36,7 +36,7 @@ abstract class AbstractUriElement /** * @param \DOMElement $node A \DOMElement instance * @param string $currentUri The URI of the page where the link is embedded (or the base href) - * @param string $method The method to use for the link (GET by default) + * @param string|null $method The method to use for the link (GET by default) * * @throws \InvalidArgumentException if the node is not a link */ @@ -70,7 +70,7 @@ abstract class AbstractUriElement */ public function getMethod() { - return $this->method; + return $this->method ?? 'GET'; } /** diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index ca3cf80fde..755eccbd1a 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -137,7 +137,7 @@ class FormValidator extends ConstraintValidator // Mark the form with an error if it contains extra fields if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) { $this->context->setConstraint($formConstraint); - $this->context->buildViolation($config->getOption('extra_fields_message')) + $this->context->buildViolation($config->getOption('extra_fields_message', '')) ->setParameter('{{ extra_fields }}', '"'.implode('", "', array_keys($form->getExtraData())).'"') ->setInvalidValue($form->getExtraData()) ->setCode(Form::NO_SUCH_FIELD_ERROR) diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index aba3b0fae2..e041e40ff0 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -146,7 +146,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac private $lockSetData = false; /** - * @var string|int|null + * @var string|null */ private $name; @@ -847,6 +847,8 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); } + $child = (string) $child; + if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index fa7bac32bb..9effe1a7c6 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -107,7 +107,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * Creates an empty form configuration. * - * @param string|int $name The form name + * @param string|null $name The form name * @param string|null $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options @@ -115,7 +115,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface * @throws InvalidArgumentException if the data class is not a valid class or if * the name contains invalid characters */ - public function __construct($name, ?string $dataClass, EventDispatcherInterface $dispatcher, array $options = []) + public function __construct(?string $name, ?string $dataClass, EventDispatcherInterface $dispatcher, array $options = []) { self::validateName($name); @@ -123,7 +123,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface throw new InvalidArgumentException(sprintf('Class "%s" not found. Is the "data_class" form option set correctly?', $dataClass)); } - $this->name = (string) $name; + $this->name = $name ?? ''; $this->dataClass = $dataClass; $this->dispatcher = $dispatcher; $this->options = $options; @@ -767,15 +767,17 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * Validates whether the given variable is a valid form name. * - * @param string|int|null $name The tested form name + * @param string|null $name The tested form name * * @throws UnexpectedTypeException if the name is not a string or an integer * @throws InvalidArgumentException if the name contains invalid characters + * + * @internal since Symfony 4.4 */ public static function validateName($name) { - if (null !== $name && !\is_string($name) && !\is_int($name)) { - throw new UnexpectedTypeException($name, 'string, integer or null'); + if (null !== $name && !\is_string($name)) { + throw new UnexpectedTypeException($name, 'string or null'); } if (!self::isValidName($name)) { @@ -792,12 +794,8 @@ class FormConfigBuilder implements FormConfigBuilderInterface * * starts with a letter, digit or underscore * * contains only letters, digits, numbers, underscores ("_"), * hyphens ("-") and colons (":") - * - * @param string|null $name The tested form name - * - * @return bool Whether the name is valid */ - public static function isValidName($name) + final public static function isValidName(?string $name): bool { return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); } diff --git a/src/Symfony/Component/Form/FormError.php b/src/Symfony/Component/Form/FormError.php index f0898b7665..f390854aee 100644 --- a/src/Symfony/Component/Form/FormError.php +++ b/src/Symfony/Component/Form/FormError.php @@ -47,9 +47,9 @@ class FormError * * @see \Symfony\Component\Translation\Translator */ - public function __construct(?string $message, string $messageTemplate = null, array $messageParameters = [], int $messagePluralization = null, $cause = null) + public function __construct(string $message, string $messageTemplate = null, array $messageParameters = [], int $messagePluralization = null, $cause = null) { - $this->message = (string) $message; + $this->message = $message; $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; diff --git a/src/Symfony/Component/Form/FormFactory.php b/src/Symfony/Component/Form/FormFactory.php index b397f9a21f..ac38b0a39e 100644 --- a/src/Symfony/Component/Form/FormFactory.php +++ b/src/Symfony/Component/Form/FormFactory.php @@ -73,7 +73,7 @@ class FormFactory implements FormFactoryInterface $type = $this->registry->getType($type); - $builder = $type->createBuilder($this, $name, $options); + $builder = $type->createBuilder($this, (string) $name, $options); // Explicitly call buildForm() in order to be able to override either // createBuilder() or buildForm() in the resolved form type diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index bde6c2808d..a46c3de6c7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -46,6 +46,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase { $this->tokenManager = $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock(); $this->translator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); + $this->translator->expects($this->any())->method('trans')->willReturnArgument(0); parent::setUp(); } @@ -371,16 +372,11 @@ class FormTypeCsrfExtensionTest extends TypeTestCase ->with($csrfToken) ->willReturn(false); - $this->translator->expects($this->once()) - ->method('trans') - ->with('Foobar') - ->willReturn('[trans]Foobar[/trans]'); - $form = $this->factory ->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, - 'csrf_message' => 'Foobar', + 'csrf_message' => '[trans]Foobar[/trans]', 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, ]) diff --git a/src/Symfony/Component/Form/Tests/FormConfigTest.php b/src/Symfony/Component/Form/Tests/FormConfigTest.php index 18dac5528f..c241f09973 100644 --- a/src/Symfony/Component/Form/Tests/FormConfigTest.php +++ b/src/Symfony/Component/Form/Tests/FormConfigTest.php @@ -57,11 +57,6 @@ class FormConfigTest extends TestCase [123], // NULL is allowed [null], - // Other types are not - [1.23, 'Symfony\Component\Form\Exception\UnexpectedTypeException'], - [5., 'Symfony\Component\Form\Exception\UnexpectedTypeException'], - [true, 'Symfony\Component\Form\Exception\UnexpectedTypeException'], - [new \stdClass(), 'Symfony\Component\Form\Exception\UnexpectedTypeException'], ]; } diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php index 8d04aa42c9..c6b559beb1 100644 --- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -32,7 +32,7 @@ class RedirectResponse extends Response * * @see http://tools.ietf.org/html/rfc2616#section-10.3 */ - public function __construct(?string $url, int $status = 302, array $headers = []) + public function __construct(string $url, int $status = 302, array $headers = []) { parent::__construct('', $status, $headers); @@ -82,7 +82,7 @@ class RedirectResponse extends Response */ public function setTargetUrl($url) { - if (empty($url)) { + if ('' == $url) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php index 5f6a8ac088..24d703d52b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php @@ -28,10 +28,11 @@ class RedirectResponseTest extends TestCase /** * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Cannot redirect to an empty URL. */ - public function testRedirectResponseConstructorNullUrl() + public function testRedirectResponseConstructorEmptyUrl() { - $response = new RedirectResponse(null); + $response = new RedirectResponse(''); } /** diff --git a/src/Symfony/Component/Validator/ConstraintViolation.php b/src/Symfony/Component/Validator/ConstraintViolation.php index 8651913c3e..a0ce00e334 100644 --- a/src/Symfony/Component/Validator/ConstraintViolation.php +++ b/src/Symfony/Component/Validator/ConstraintViolation.php @@ -44,12 +44,12 @@ class ConstraintViolation implements ConstraintViolationInterface * violation * @param int|null $plural The number for determining the plural * form when translating the message - * @param mixed $code The error code of the violation + * @param string|null $code The error code of the violation * @param Constraint|null $constraint The constraint whose validation * caused the violation * @param mixed $cause The cause of the violation */ - public function __construct(?string $message, ?string $messageTemplate, array $parameters, $root, ?string $propertyPath, $invalidValue, int $plural = null, $code = null, Constraint $constraint = null, $cause = null) + public function __construct(string $message, ?string $messageTemplate, array $parameters, $root, ?string $propertyPath, $invalidValue, int $plural = null, $code = null, Constraint $constraint = null, $cause = null) { $this->message = $message; $this->messageTemplate = $messageTemplate; diff --git a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php index 35e78268d4..b4ec2037fc 100644 --- a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php @@ -99,6 +99,7 @@ abstract class ConstraintValidatorTestCase extends TestCase protected function createContext() { $translator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); + $translator->expects($this->any())->method('trans')->willReturnArgument(0); $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock(); @@ -330,7 +331,7 @@ class ConstraintViolationAssertion private function getViolation() { return new ConstraintViolation( - null, + $this->message, $this->message, $this->parameters, $this->context->getRoot(), diff --git a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php index c5b1d0b83f..553f17f14a 100644 --- a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php +++ b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php @@ -47,7 +47,7 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface /** * @param TranslatorInterface $translator */ - public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, $translator, $translationDomain = null) + public function __construct(ConstraintViolationList $violations, Constraint $constraint, string $message, array $parameters, $root, string $propertyPath, $invalidValue, $translator, string $translationDomain = null) { if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { throw new \TypeError(sprintf('Argument 8 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));