diff --git a/UPGRADE-6.2.md b/UPGRADE-6.2.md index 60c5b84b43793..d0667fe2d79c6 100644 --- a/UPGRADE-6.2.md +++ b/UPGRADE-6.2.md @@ -13,6 +13,7 @@ HttpFoundation -------------- * Deprecate `Request::getContentType()`, use `Request::getContentTypeFormat()` instead + * Deprecate passing `\Stringable` objects to `InputBag`, use scalars, arrays or null instead. Mailer -------- diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index d78710a3e43f2..e1fc84b48058d 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.2 +--- + + * Deprecate passing `\Stringable` objects to `InputBag`, use scalars, arrays or null instead. + 6.1 --- diff --git a/src/Symfony/Component/HttpFoundation/InputBag.php b/src/Symfony/Component/HttpFoundation/InputBag.php index fd833467f4dd5..d4655a445de37 100644 --- a/src/Symfony/Component/HttpFoundation/InputBag.php +++ b/src/Symfony/Component/HttpFoundation/InputBag.php @@ -27,16 +27,26 @@ final class InputBag extends ParameterBag */ public function get(string $key, mixed $default = null): string|int|float|bool|null { + // @deprecated since symfony 6.2, in 7.0 change to: + // if (null !== $default && !\is_scalar($default)) { if (null !== $default && !\is_scalar($default) && !$default instanceof \Stringable) { throw new \InvalidArgumentException(sprintf('Expected a scalar value as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($default))); } + if ($default instanceof \Stringable) { + trigger_deprecation('symfony/http-foundation', '6.2', 'Passing a "%s" object as 2nd argument ($default) to "%s()" is deprecated, pass a scalar or null instead.', get_debug_type($default), __METHOD__); + } + $value = parent::get($key, $this); if (null !== $value && $this !== $value && !\is_scalar($value) && !$value instanceof \Stringable) { throw new BadRequestException(sprintf('Input value "%s" contains a non-scalar value.', $key)); } + if ($value instanceof \Stringable) { + trigger_deprecation('symfony/http-foundation', '6.2', 'Retrieving a "%s" object from "%s()" is deprecated, use scalars or null instead.', get_debug_type($value), __METHOD__); + } + return $this === $value ? $default : $value; } @@ -66,10 +76,16 @@ public function add(array $inputs = []) */ public function set(string $key, mixed $value) { + // @deprecated since symfony 6.2, in 7.0 change to: + // if (null !== $value && !\is_scalar($value) && !\is_array($value)) { if (null !== $value && !\is_scalar($value) && !\is_array($value) && !$value instanceof \Stringable) { throw new \InvalidArgumentException(sprintf('Expected a scalar, or an array as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($value))); } + if ($value instanceof \Stringable) { + trigger_deprecation('symfony/http-foundation', '6.2', 'Passing a "%s" object as a 2nd argument ($value) to "%s()" is deprecated. Pass a scalar, an array or null instead.', get_debug_type($value), __METHOD__); + } + $this->parameters[$key] = $value; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php index 696318e91ea98..8cdc8e909550f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php @@ -12,26 +12,23 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\InputBag; class InputBagTest extends TestCase { + use ExpectDeprecationTrait; + public function testGet() { - $bag = new InputBag(['foo' => 'bar', 'null' => null, 'int' => 1, 'float' => 1.0, 'bool' => false, 'stringable' => new class() implements \Stringable { - public function __toString(): string - { - return 'strval'; - } - }]); + $bag = new InputBag(['foo' => 'bar', 'null' => null, 'int' => 1, 'float' => 1.0, 'bool' => false]); $this->assertSame('bar', $bag->get('foo'), '->get() gets the value of a string parameter'); $this->assertSame('default', $bag->get('unknown', 'default'), '->get() returns second argument as default if a parameter is not defined'); $this->assertNull($bag->get('null', 'default'), '->get() returns null if null is set'); $this->assertSame(1, $bag->get('int'), '->get() gets the value of an int parameter'); $this->assertSame(1.0, $bag->get('float'), '->get() gets the value of a float parameter'); - $this->assertSame('strval', $bag->get('stringable'), '->get() gets the string value of a \Stringable parameter'); $this->assertFalse($bag->get('bool'), '->get() gets the value of a bool parameter'); } @@ -106,4 +103,35 @@ public function testFilterArrayWithoutArrayFlag() $bag = new InputBag(['foo' => ['bar', 'baz']]); $bag->filter('foo', \FILTER_VALIDATE_INT); } + + /** + * @group legacy + */ + public function testLegacyGetStringableObject() + { + $bag = new InputBag(['stringable' => new class() implements \Stringable { + public function __toString(): string + { + return 'strval'; + } + }]); + + $this->expectDeprecation('Since symfony/http-foundation 6.2: Retrieving a "Stringable@anonymous" object from "Symfony\Component\HttpFoundation\InputBag::get()" is deprecated, use scalars or null instead.'); + $this->assertSame('strval', $bag->get('stringable'), '->get() gets the string value of a \Stringable parameter'); + } + + /** + * @group legacy + */ + public function testLegacySetStringableObject() + { + $bag = new InputBag(); + $this->expectDeprecation('Since symfony/http-foundation 6.2: Passing a "Stringable@anonymous" object as a 2nd argument ($value) to "Symfony\Component\HttpFoundation\InputBag::set()" is deprecated. Pass a scalar, an array or null instead.'); + $bag->set('stringable', new class() implements \Stringable { + public function __toString(): string + { + return 'strval'; + } + }); + } }