Fine tune constructor types

This commit is contained in:
Tobias Schultze 2019-06-17 00:17:09 +01:00
parent 8496003634
commit 507794a575
17 changed files with 39 additions and 41 deletions

View File

@ -47,7 +47,10 @@ abstract class BaseNode implements NodeInterface
*/ */
public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) 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.'".'); throw new \InvalidArgumentException('The name must not contain "'.$pathSeparator.'".');
} }

View File

@ -41,7 +41,7 @@ abstract class NodeDefinition implements NodeParentInterface
public function __construct(?string $name, NodeParentInterface $parent = null) public function __construct(?string $name, NodeParentInterface $parent = null)
{ {
$this->parent = $parent; $this->parent = $parent;
$this->name = $name; $this->name = $name ?? '';
} }
/** /**

View File

@ -39,7 +39,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface
* *
* @throws \InvalidArgumentException * @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->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
$this->pattern = $pattern; $this->pattern = $pattern;

View File

@ -71,6 +71,7 @@ class FileLoaderTest extends TestCase
public function testImportWithGlobLikeResource() public function testImportWithGlobLikeResource()
{ {
$locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock(); $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
$locatorMock->expects($this->once())->method('locate')->willReturn('');
$loader = new TestFileLoader($locatorMock); $loader = new TestFileLoader($locatorMock);
$this->assertSame('[foo]', $loader->import('[foo]')); $this->assertSame('[foo]', $loader->import('[foo]'));
@ -79,6 +80,7 @@ class FileLoaderTest extends TestCase
public function testImportWithNoGlobMatch() public function testImportWithNoGlobMatch()
{ {
$locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock(); $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
$locatorMock->expects($this->once())->method('locate')->willReturn('');
$loader = new TestFileLoader($locatorMock); $loader = new TestFileLoader($locatorMock);
$this->assertNull($loader->import('./*.abc')); $this->assertNull($loader->import('./*.abc'));

View File

@ -24,7 +24,7 @@ abstract class AbstractUriElement
protected $node; protected $node;
/** /**
* @var string The method to use for the element * @var string|null The method to use for the element
*/ */
protected $method; protected $method;
@ -36,7 +36,7 @@ abstract class AbstractUriElement
/** /**
* @param \DOMElement $node A \DOMElement instance * @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 $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 * @throws \InvalidArgumentException if the node is not a link
*/ */
@ -70,7 +70,7 @@ abstract class AbstractUriElement
*/ */
public function getMethod() public function getMethod()
{ {
return $this->method; return $this->method ?? 'GET';
} }
/** /**

View File

@ -137,7 +137,7 @@ class FormValidator extends ConstraintValidator
// Mark the form with an error if it contains extra fields // Mark the form with an error if it contains extra fields
if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) { if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) {
$this->context->setConstraint($formConstraint); $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())).'"') ->setParameter('{{ extra_fields }}', '"'.implode('", "', array_keys($form->getExtraData())).'"')
->setInvalidValue($form->getExtraData()) ->setInvalidValue($form->getExtraData())
->setCode(Form::NO_SUCH_FIELD_ERROR) ->setCode(Form::NO_SUCH_FIELD_ERROR)

View File

@ -146,7 +146,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
private $lockSetData = false; private $lockSetData = false;
/** /**
* @var string|int|null * @var string|null
*/ */
private $name; private $name;
@ -847,6 +847,8 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface');
} }
$child = (string) $child;
if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) { if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) {
throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface');
} }

View File

@ -107,7 +107,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface
/** /**
* Creates an empty form configuration. * 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 string|null $dataClass The class of the form's data
* @param EventDispatcherInterface $dispatcher The event dispatcher * @param EventDispatcherInterface $dispatcher The event dispatcher
* @param array $options The form options * @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 * @throws InvalidArgumentException if the data class is not a valid class or if
* the name contains invalid characters * 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); 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)); 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->dataClass = $dataClass;
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
$this->options = $options; $this->options = $options;
@ -767,15 +767,17 @@ class FormConfigBuilder implements FormConfigBuilderInterface
/** /**
* Validates whether the given variable is a valid form name. * 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 UnexpectedTypeException if the name is not a string or an integer
* @throws InvalidArgumentException if the name contains invalid characters * @throws InvalidArgumentException if the name contains invalid characters
*
* @internal since Symfony 4.4
*/ */
public static function validateName($name) public static function validateName($name)
{ {
if (null !== $name && !\is_string($name) && !\is_int($name)) { if (null !== $name && !\is_string($name)) {
throw new UnexpectedTypeException($name, 'string, integer or null'); throw new UnexpectedTypeException($name, 'string or null');
} }
if (!self::isValidName($name)) { if (!self::isValidName($name)) {
@ -792,12 +794,8 @@ class FormConfigBuilder implements FormConfigBuilderInterface
* * starts with a letter, digit or underscore * * starts with a letter, digit or underscore
* * contains only letters, digits, numbers, underscores ("_"), * * contains only letters, digits, numbers, underscores ("_"),
* hyphens ("-") and colons (":") * 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); return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name);
} }

View File

@ -47,9 +47,9 @@ class FormError
* *
* @see \Symfony\Component\Translation\Translator * @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->messageTemplate = $messageTemplate ?: $message;
$this->messageParameters = $messageParameters; $this->messageParameters = $messageParameters;
$this->messagePluralization = $messagePluralization; $this->messagePluralization = $messagePluralization;

View File

@ -73,7 +73,7 @@ class FormFactory implements FormFactoryInterface
$type = $this->registry->getType($type); $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 // Explicitly call buildForm() in order to be able to override either
// createBuilder() or buildForm() in the resolved form type // createBuilder() or buildForm() in the resolved form type

View File

@ -46,6 +46,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
{ {
$this->tokenManager = $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock(); $this->tokenManager = $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock();
$this->translator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); $this->translator = $this->getMockBuilder(TranslatorInterface::class)->getMock();
$this->translator->expects($this->any())->method('trans')->willReturnArgument(0);
parent::setUp(); parent::setUp();
} }
@ -371,16 +372,11 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
->with($csrfToken) ->with($csrfToken)
->willReturn(false); ->willReturn(false);
$this->translator->expects($this->once())
->method('trans')
->with('Foobar')
->willReturn('[trans]Foobar[/trans]');
$form = $this->factory $form = $this->factory
->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ ->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_token_manager' => $this->tokenManager, 'csrf_token_manager' => $this->tokenManager,
'csrf_message' => 'Foobar', 'csrf_message' => '[trans]Foobar[/trans]',
'csrf_token_id' => 'TOKEN_ID', 'csrf_token_id' => 'TOKEN_ID',
'compound' => true, 'compound' => true,
]) ])

View File

@ -57,11 +57,6 @@ class FormConfigTest extends TestCase
[123], [123],
// NULL is allowed // NULL is allowed
[null], [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'],
]; ];
} }

View File

@ -32,7 +32,7 @@ class RedirectResponse extends Response
* *
* @see http://tools.ietf.org/html/rfc2616#section-10.3 * @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); parent::__construct('', $status, $headers);
@ -82,7 +82,7 @@ class RedirectResponse extends Response
*/ */
public function setTargetUrl($url) public function setTargetUrl($url)
{ {
if (empty($url)) { if ('' == $url) {
throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
} }

View File

@ -28,10 +28,11 @@ class RedirectResponseTest extends TestCase
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Cannot redirect to an empty URL.
*/ */
public function testRedirectResponseConstructorNullUrl() public function testRedirectResponseConstructorEmptyUrl()
{ {
$response = new RedirectResponse(null); $response = new RedirectResponse('');
} }
/** /**

View File

@ -44,12 +44,12 @@ class ConstraintViolation implements ConstraintViolationInterface
* violation * violation
* @param int|null $plural The number for determining the plural * @param int|null $plural The number for determining the plural
* form when translating the message * 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 * @param Constraint|null $constraint The constraint whose validation
* caused the violation * caused the violation
* @param mixed $cause The cause of 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->message = $message;
$this->messageTemplate = $messageTemplate; $this->messageTemplate = $messageTemplate;

View File

@ -99,6 +99,7 @@ abstract class ConstraintValidatorTestCase extends TestCase
protected function createContext() protected function createContext()
{ {
$translator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); $translator = $this->getMockBuilder(TranslatorInterface::class)->getMock();
$translator->expects($this->any())->method('trans')->willReturnArgument(0);
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
$contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock(); $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
@ -330,7 +331,7 @@ class ConstraintViolationAssertion
private function getViolation() private function getViolation()
{ {
return new ConstraintViolation( return new ConstraintViolation(
null, $this->message,
$this->message, $this->message,
$this->parameters, $this->parameters,
$this->context->getRoot(), $this->context->getRoot(),

View File

@ -47,7 +47,7 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
/** /**
* @param TranslatorInterface $translator * @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) { 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))); 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)));