From a71023ba657581ea1434c9c602fb54925381c135 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 14 Mar 2020 16:15:49 +0100 Subject: [PATCH 1/4] [PropertyAccess] Improved errors when reading uninitialized properties --- .../PropertyAccess/PropertyAccessor.php | 62 ++++++++++++------- .../Fixtures/UninitializedPrivateProperty.php | 22 +++++++ .../Tests/Fixtures/UninitializedProperty.php | 17 +++++ .../Tests/PropertyAccessorTest.php | 24 +++++++ 4 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedPrivateProperty.php create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedProperty.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 371c6c23d5..8761d49995 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -465,30 +465,50 @@ class PropertyAccessor implements PropertyAccessorInterface $object = $zval[self::VALUE]; $access = $this->getReadAccessInfo(\get_class($object), $property); - if (self::ACCESS_TYPE_METHOD === $access[self::ACCESS_TYPE]) { - $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}(); - } elseif (self::ACCESS_TYPE_PROPERTY === $access[self::ACCESS_TYPE]) { - $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}; + try { + if (self::ACCESS_TYPE_METHOD === $access[self::ACCESS_TYPE]) { + try { + $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}(); + } catch (\TypeError $e) { + // handle uninitialized properties in PHP >= 7 + if (preg_match((sprintf('/^Return value of %s::%s\(\) must be of the type (\w+), null returned$/', preg_quote(\get_class($object)), $access[self::ACCESS_NAME])), $e->getMessage(), $matches)) { + throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Have you forgotten to initialize a property or to make the return type nullable using "?%3$s" instead?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e); + } - if ($access[self::ACCESS_REF] && isset($zval[self::REF])) { - $result[self::REF] = &$object->{$access[self::ACCESS_NAME]}; - } - } elseif (!$access[self::ACCESS_HAS_PROPERTY] && property_exists($object, $property)) { - // Needed to support \stdClass instances. We need to explicitly - // exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if - // a *protected* property was found on the class, property_exists() - // returns true, consequently the following line will result in a - // fatal error. + throw $e; + } + } elseif (self::ACCESS_TYPE_PROPERTY === $access[self::ACCESS_TYPE]) { + $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}; - $result[self::VALUE] = $object->$property; - if (isset($zval[self::REF])) { - $result[self::REF] = &$object->$property; + if ($access[self::ACCESS_REF] && isset($zval[self::REF])) { + $result[self::REF] = &$object->{$access[self::ACCESS_NAME]}; + } + } elseif (!$access[self::ACCESS_HAS_PROPERTY] && property_exists($object, $property)) { + // Needed to support \stdClass instances. We need to explicitly + // exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if + // a *protected* property was found on the class, property_exists() + // returns true, consequently the following line will result in a + // fatal error. + + $result[self::VALUE] = $object->$property; + if (isset($zval[self::REF])) { + $result[self::REF] = &$object->$property; + } + } elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) { + // we call the getter and hope the __call do the job + $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}(); + } else { + throw new NoSuchPropertyException($access[self::ACCESS_NAME]); } - } elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) { - // we call the getter and hope the __call do the job - $result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}(); - } else { - throw new NoSuchPropertyException($access[self::ACCESS_NAME]); + } catch (\Error $e) { + // handle uninitialized properties in PHP >= 7.4 + if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { + $r = new \ReflectionProperty($matches[1], $matches[2]); + + throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%3$s". You should either initialize it or make it nullable using "?%3$s" instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e); + } + + throw $e; } // Objects are always passed around by reference diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedPrivateProperty.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedPrivateProperty.php new file mode 100644 index 0000000000..b7acf8838b --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedPrivateProperty.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +class UninitializedPrivateProperty +{ + private $uninitialized; + + public function getUninitialized(): array + { + return $this->uninitialized; + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedProperty.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedProperty.php new file mode 100644 index 0000000000..ac757b4022 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/UninitializedProperty.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\PropertyAccess\Tests\Fixtures; + +class UninitializedProperty +{ + public string $uninitialized; +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 0eb4baacf2..62a95d68e9 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -25,6 +25,8 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassTypeErrorInsideCall use Symfony\Component\PropertyAccess\Tests\Fixtures\TestSingularAndPluralProps; use Symfony\Component\PropertyAccess\Tests\Fixtures\Ticket5775Object; use Symfony\Component\PropertyAccess\Tests\Fixtures\TypeHinted; +use Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty; +use Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty; class PropertyAccessorTest extends TestCase { @@ -118,6 +120,28 @@ class PropertyAccessorTest extends TestCase $this->propertyAccessor->getValue($objectOrArray, $path); } + /** + * @requires PHP 7.4 + */ + public function testGetValueThrowsExceptionIfUninitializedProperty() + { + $this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException'); + $this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty::$uninitialized" is not readable because it is typed "string". You should either initialize it or make it nullable using "?string" instead.'); + + $this->propertyAccessor->getValue(new UninitializedProperty(), 'uninitialized'); + } + + /** + * @requires PHP 7 + */ + public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetter() + { + $this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException'); + $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty::getUninitialized()" returned "null", but expected type "array". Have you forgotten to initialize a property or to make the return type nullable using "?array" instead?'); + + $this->propertyAccessor->getValue(new UninitializedPrivateProperty(), 'uninitialized'); + } + public function testGetValueThrowsExceptionIfNotArrayAccess() { $this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchIndexException'); From 019350022ce6ce9d07152e05278cc2cb1482d68a Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 13 Mar 2020 14:33:39 +0100 Subject: [PATCH 2/4] [3.4] Minor fixes --- .../SecurityBundle/DependencyInjection/MainConfiguration.php | 2 +- src/Symfony/Component/Security/Core/User/UserInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 251c7bb6a9..df96cf2db7 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -296,7 +296,7 @@ class MainConfiguration implements ConfigurationInterface ->scalarNode('provider')->end() ->scalarNode('parameter')->defaultValue('_switch_user')->end() ->scalarNode('role')->defaultValue('ROLE_ALLOWED_TO_SWITCH')->end() - ->booleanNode('stateless')->defaultValue(false)->end() + ->booleanNode('stateless')->defaultFalse()->end() ->end() ->end() ; diff --git a/src/Symfony/Component/Security/Core/User/UserInterface.php b/src/Symfony/Component/Security/Core/User/UserInterface.php index fdad6b055b..3b26da3055 100644 --- a/src/Symfony/Component/Security/Core/User/UserInterface.php +++ b/src/Symfony/Component/Security/Core/User/UserInterface.php @@ -23,7 +23,7 @@ use Symfony\Component\Security\Core\Role\Role; * * Regardless of how your users are loaded or where they come from (a database, * configuration, web service, etc.), you will have a class that implements - * this interface. Objects that implement this interface are created and + * this interface. Objects that implement this interface are created and * loaded by different objects that implement UserProviderInterface. * * @see UserProviderInterface From 4ab6156c5a26f3a4568e803eda95266ca6f7cc1e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 16 Mar 2020 16:39:23 +0100 Subject: [PATCH 3/4] Fix more quotes in exception messages --- .../Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php | 2 +- .../FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php | 2 +- .../DependencyInjection/FrameworkExtension.php | 2 +- .../Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php | 2 +- src/Symfony/Component/Cache/Traits/RedisTrait.php | 2 +- .../Component/HttpKernel/Controller/ArgumentResolver.php | 2 +- .../Component/Intl/NumberFormatter/NumberFormatter.php | 2 +- src/Symfony/Component/Lock/Store/MemcachedStore.php | 4 ++-- src/Symfony/Component/Lock/Store/RedisStore.php | 2 +- src/Symfony/Component/Process/InputStream.php | 2 +- src/Symfony/Component/Process/Pipes/AbstractPipes.php | 2 +- src/Symfony/Component/Process/ProcessUtils.php | 2 +- src/Symfony/Component/Process/Tests/ProcessBuilderTest.php | 2 +- src/Symfony/Component/Process/Tests/ProcessTest.php | 2 +- src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php | 2 +- .../Security/Guard/Firewall/GuardAuthenticationListener.php | 2 +- src/Symfony/Component/VarDumper/Cloner/Data.php | 2 +- 17 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php index e3ef1f0553..1e033e3eae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php @@ -40,7 +40,7 @@ class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterf $this->router = $container; @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since Symfony 3.4 and will be unsupported in version 4.0. Use a %s instead.', RouterInterface::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('"%s" only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php index b4439eff48..4c0387bdc6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php @@ -41,7 +41,7 @@ class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriber $this->translator = $container; @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since Symfony 3.4 and will be unsupported in version 4.0. Use a %s instead.', TranslatorInterface::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('"%s" only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index afad1629d3..09d06e4145 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1201,7 +1201,7 @@ class FrameworkExtension extends Extension if ($container->fileExists($dir)) { $dirs[] = $dir; } else { - throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory.', $dir)); + throw new \UnexpectedValueException(sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir)); } } diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index 23abdbf992..a51037dcb9 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -42,7 +42,7 @@ class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInte $this->twig = $container; @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since Symfony 3.4 and will be unsupported in version 4.0. Use a %s instead.', Environment::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('"%s" only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } $this->iterator = $iterator; diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index c5b60f9e19..315e426dde 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -48,7 +48,7 @@ trait RedisTrait throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); } if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) { - throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, "%s" given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); + throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, "%s" given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); } $this->redis = $redisClient; } diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php index fc6f969a9e..9d5f96ed2c 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php @@ -56,7 +56,7 @@ final class ArgumentResolver implements ArgumentResolverInterface $resolved = $resolver->resolve($request, $metadata); if (!$resolved instanceof \Generator) { - throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver))); + throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', \get_class($resolver))); } foreach ($resolved as $append) { diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index 72e1ca5b4e..7792a1e757 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -363,7 +363,7 @@ class NumberFormatter } if (self::CURRENCY === $this->style) { - throw new NotImplementedException(sprintf('%s() method does not support the formatting of currencies (instance with CURRENCY style). "%s".', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE)); + throw new NotImplementedException(sprintf('"%s()" method does not support the formatting of currencies (instance with CURRENCY style). "%s".', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE)); } // Only the default type is supported. diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index ebe6973133..52eff0a31c 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -46,7 +46,7 @@ class MemcachedStore implements StoreInterface } if ($initialTtl < 1) { - throw new InvalidArgumentException(sprintf('%s() expects a strictly positive TTL. Got %d.', __METHOD__, $initialTtl)); + throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive TTL. Got %d.', __METHOD__, $initialTtl)); } $this->memcached = $memcached; @@ -79,7 +79,7 @@ class MemcachedStore implements StoreInterface public function putOffExpiration(Key $key, $ttl) { if ($ttl < 1) { - throw new InvalidArgumentException(sprintf('%s() expects a TTL greater or equals to 1. Got %s.', __METHOD__, $ttl)); + throw new InvalidArgumentException(sprintf('"%s()" expects a TTL greater or equals to 1. Got %s.', __METHOD__, $ttl)); } // Interface defines a float value but Store required an integer. diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index 55213742a1..da076c0145 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -143,7 +143,7 @@ class RedisStore implements StoreInterface return \call_user_func_array([$this->redis, 'eval'], array_merge([$script, 1, $resource], $args)); } - throw new InvalidArgumentException(sprintf('%s() expects being initialized with a Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($this->redis) ? \get_class($this->redis) : \gettype($this->redis))); + throw new InvalidArgumentException(sprintf('"%s()" expects being initialized with a Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($this->redis) ? \get_class($this->redis) : \gettype($this->redis))); } /** diff --git a/src/Symfony/Component/Process/InputStream.php b/src/Symfony/Component/Process/InputStream.php index 82dbdb223d..ef38dd7bfd 100644 --- a/src/Symfony/Component/Process/InputStream.php +++ b/src/Symfony/Component/Process/InputStream.php @@ -45,7 +45,7 @@ class InputStream implements \IteratorAggregate return; } if ($this->isClosed()) { - throw new RuntimeException(sprintf('%s is closed.', static::class)); + throw new RuntimeException(sprintf('"%s" is closed.', static::class)); } $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); } diff --git a/src/Symfony/Component/Process/Pipes/AbstractPipes.php b/src/Symfony/Component/Process/Pipes/AbstractPipes.php index b84b4f084c..cdffaaffe4 100644 --- a/src/Symfony/Component/Process/Pipes/AbstractPipes.php +++ b/src/Symfony/Component/Process/Pipes/AbstractPipes.php @@ -107,7 +107,7 @@ abstract class AbstractPipes implements PipesInterface } elseif (!isset($this->inputBuffer[0])) { if (!\is_string($input)) { if (!is_scalar($input)) { - throw new InvalidArgumentException(sprintf('%s yielded a value of type "%s", but only scalars and stream resources are supported.', \get_class($this->input), \gettype($input))); + throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', \get_class($this->input), \gettype($input))); } $input = (string) $input; } diff --git a/src/Symfony/Component/Process/ProcessUtils.php b/src/Symfony/Component/Process/ProcessUtils.php index 00acde0a19..74f2d8654a 100644 --- a/src/Symfony/Component/Process/ProcessUtils.php +++ b/src/Symfony/Component/Process/ProcessUtils.php @@ -110,7 +110,7 @@ class ProcessUtils return new \IteratorIterator($input); } - throw new InvalidArgumentException(sprintf('%s only accepts strings, Traversable objects or stream resources.', $caller)); + throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller)); } return $input; diff --git a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php index 7ab74402ac..c2851357d7 100644 --- a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php @@ -200,7 +200,7 @@ class ProcessBuilderTest extends TestCase public function testInvalidInput() { $this->expectException('Symfony\Component\Process\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Symfony\Component\Process\ProcessBuilder::setInput only accepts strings, Traversable objects or stream resources.'); + $this->expectExceptionMessage('"Symfony\Component\Process\ProcessBuilder::setInput" only accepts strings, Traversable objects or stream resources.'); $builder = ProcessBuilder::create(); $builder->setInput([]); } diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 9bc3dedbf2..e5335282ca 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -263,7 +263,7 @@ class ProcessTest extends TestCase public function testInvalidInput($value) { $this->expectException('Symfony\Component\Process\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Symfony\Component\Process\Process::setInput only accepts strings, Traversable objects or stream resources.'); + $this->expectExceptionMessage('"Symfony\Component\Process\Process::setInput" only accepts strings, Traversable objects or stream resources.'); $process = $this->getProcess('foo'); $process->setInput($value); } diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index 33cfcacc9f..3920fc4bef 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -55,7 +55,7 @@ abstract class ObjectRouteLoader extends Loader $loaderObject = $this->getServiceObject($serviceString); if (!\is_object($loaderObject)) { - throw new \LogicException(sprintf('%s:getServiceObject() must return an object: "%s" returned.', static::class, \gettype($loaderObject))); + throw new \LogicException(sprintf('"%s:getServiceObject()" must return an object: "%s" returned.', static::class, \gettype($loaderObject))); } if (!method_exists($loaderObject, $method)) { diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php index ed21e9974e..dc0da956a4 100644 --- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php +++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php @@ -221,7 +221,7 @@ class GuardAuthenticationListener implements ListenerInterface } if (!$response instanceof Response) { - throw new \LogicException(sprintf('%s::onAuthenticationSuccess *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.', \get_class($guardAuthenticator))); + throw new \LogicException(sprintf('"%s::onAuthenticationSuccess()" *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.', \get_class($guardAuthenticator))); } $this->rememberMeServices->loginSuccess($request, $response, $token); diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index a279f9a69e..42742d852d 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -114,7 +114,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate public function getIterator() { if (!\is_array($value = $this->getValue())) { - throw new \LogicException(sprintf('%s object holds non-iterable type "%s".', self::class, \gettype($value))); + throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, \gettype($value))); } foreach ($value as $k => $v) { From c79fe029e75ccd5dad3766ca8c1f3a81b6308713 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 16 Mar 2020 17:13:17 +0100 Subject: [PATCH 4/4] Fix more quotes in exception messages --- src/Symfony/Component/HttpClient/CurlHttpClient.php | 2 +- src/Symfony/Component/HttpClient/MockHttpClient.php | 2 +- src/Symfony/Component/HttpClient/NativeHttpClient.php | 2 +- .../Session/Storage/Handler/RedisSessionHandler.php | 2 +- src/Symfony/Component/Lock/Store/PdoStore.php | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 9f9fbd0a8a..ddc7f9d9f3 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -319,7 +319,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, if ($responses instanceof CurlResponse) { $responses = [$responses]; } elseif (!is_iterable($responses)) { - throw new \TypeError(sprintf('%s() expects parameter 1 to be an iterable of CurlResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); + throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of CurlResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); } $active = 0; diff --git a/src/Symfony/Component/HttpClient/MockHttpClient.php b/src/Symfony/Component/HttpClient/MockHttpClient.php index 7e09e35089..07d53cc149 100644 --- a/src/Symfony/Component/HttpClient/MockHttpClient.php +++ b/src/Symfony/Component/HttpClient/MockHttpClient.php @@ -79,7 +79,7 @@ class MockHttpClient implements HttpClientInterface if ($responses instanceof ResponseInterface) { $responses = [$responses]; } elseif (!is_iterable($responses)) { - throw new \TypeError(sprintf('%s() expects parameter 1 to be an iterable of MockResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); + throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of MockResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); } return new ResponseStream(MockResponse::stream($responses, $timeout)); diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index ea78d84388..055227c3f3 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -238,7 +238,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac if ($responses instanceof NativeResponse) { $responses = [$responses]; } elseif (!is_iterable($responses)) { - throw new \TypeError(sprintf('%s() expects parameter 1 to be an iterable of NativeResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); + throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of NativeResponse objects, "%s" given.', __METHOD__, \is_object($responses) ? \get_class($responses) : \gettype($responses))); } return new ResponseStream(NativeResponse::stream($responses, $timeout)); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php index 8fc19c6bc4..699d6da6f6 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php @@ -54,7 +54,7 @@ class RedisSessionHandler extends AbstractSessionHandler !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy ) { - throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); + throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); } if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index 3d059f032d..5e2f01caa4 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -82,7 +82,7 @@ class PdoStore implements StoreInterface throw new InvalidArgumentException(sprintf('"%s" requires gcProbability between 0 and 1, "%f" given.', __METHOD__, $gcProbability)); } if ($initialTtl < 1) { - throw new InvalidTtlException(sprintf('%s() expects a strictly positive TTL, "%d" given.', __METHOD__, $initialTtl)); + throw new InvalidTtlException(sprintf('"%s()" expects a strictly positive TTL, "%d" given.', __METHOD__, $initialTtl)); } if ($connOrDsn instanceof \PDO) { @@ -156,7 +156,7 @@ class PdoStore implements StoreInterface public function putOffExpiration(Key $key, $ttl) { if ($ttl < 1) { - throw new InvalidTtlException(sprintf('%s() expects a TTL greater or equals to 1 second. Got %s.', __METHOD__, $ttl)); + throw new InvalidTtlException(sprintf('"%s()" expects a TTL greater or equals to 1 second. Got %s.', __METHOD__, $ttl)); } $key->reduceLifetime($ttl);