Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ce6910d

Browse filesBrowse files
committed
Add ParameterBag::getString and rename getInt to getInteger
1 parent 94d6bbb commit ce6910d
Copy full SHA for ce6910d

File tree

6 files changed

+252
-17
lines changed
Filter options

6 files changed

+252
-17
lines changed

‎UPGRADE-6.3.md

Copy file name to clipboardExpand all lines: UPGRADE-6.3.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ SecurityBundle
1515
--------------
1616

1717
* Deprecate enabling bundle and not configuring it
18+
19+
HttpFoundation
20+
--------------
21+
22+
* Deprecate `ParameterBag::getInt`, use `ParameterBag::getInteger` instead

‎src/Symfony/Component/HttpFoundation/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
CHANGELOG
22
=========
3+
6.3
4+
---
5+
6+
* Deprecate `ParameterBag::getInt`, replaced by `ParameterBag::getInteger` to behavior on invalid value
7+
* Add `ParameterBag::getString` and `ParameterBag::getInteger` to validate and convert a parameter into string or int
8+
* Calling `ParameterBag` `getDigit`, `getAlnum`, `getAlpha`, `getInteger`, `getString` on an `array` throws an `UnexpectedValueException` instead of a `TypeError`
39

410
6.2
511
---

‎src/Symfony/Component/HttpFoundation/InputBag.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/InputBag.php
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ public function set(string $key, mixed $value)
7373
$this->parameters[$key] = $value;
7474
}
7575

76+
public function getString(string $key, string $default = ''): string
77+
{
78+
return (string) $this->get($key, $default);
79+
}
80+
7681
public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed
7782
{
7883
$value = $this->has($key) ? $this->all()[$key] : $default;

‎src/Symfony/Component/HttpFoundation/ParameterBag.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/ParameterBag.php
+50-4Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,40 +105,82 @@ public function remove(string $key)
105105
*/
106106
public function getAlpha(string $key, string $default = ''): string
107107
{
108-
return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default));
108+
return preg_replace('/[^[:alpha:]]/', '', $this->getString($key, $default));
109109
}
110110

111111
/**
112112
* Returns the alphabetic characters and digits of the parameter value.
113113
*/
114114
public function getAlnum(string $key, string $default = ''): string
115115
{
116-
return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default));
116+
return preg_replace('/[^[:alnum:]]/', '', $this->getString($key, $default));
117117
}
118118

119119
/**
120120
* Returns the digits of the parameter value.
121121
*/
122122
public function getDigits(string $key, string $default = ''): string
123123
{
124+
$value = $this->filter($key, $default, \FILTER_SANITIZE_NUMBER_INT, ['flags' => \FILTER_REQUIRE_SCALAR]);
125+
if (false === $value) {
126+
throw new \UnexpectedValueException(sprintf('Parameter value "%s" cannot be converted to "string".', $key));
127+
}
128+
124129
// we need to remove - and + because they're allowed in the filter
125-
return str_replace(['-', '+'], '', $this->filter($key, $default, \FILTER_SANITIZE_NUMBER_INT));
130+
return str_replace(['-', '+'], '', $value);
126131
}
127132

128133
/**
129134
* Returns the parameter value converted to integer.
135+
* @deprecated since Symfony 6.3, replaced by getInteger
130136
*/
131137
public function getInt(string $key, int $default = 0): int
132138
{
139+
trigger_deprecation('symfony/http-foundation', '6.3', 'Method "getInt" is deprecated and replaced by "getInteger".');
140+
133141
return (int) $this->get($key, $default);
134142
}
135143

144+
/**
145+
* Returns the parameter value converted to integer.
146+
*/
147+
public function getInteger(string $key, int $default = 0): int
148+
{
149+
$value = $this->filter($key, $default, \FILTER_VALIDATE_INT, ['flags' => \FILTER_REQUIRE_SCALAR]);
150+
if (!\is_int($value)) {
151+
throw new \UnexpectedValueException(sprintf('Parameter value "%s" cannot be converted to "int".', $key));
152+
}
153+
154+
return $value;
155+
}
156+
157+
/**
158+
* Returns the parameter as string.
159+
*
160+
* @@throws \UnexpectedValueException when
161+
*/
162+
public function getString(string $key, string $default = ''): string
163+
{
164+
$value = $this->get($key, $default);
165+
if (!\is_scalar($value) && !$value instanceof \Stringable) {
166+
throw new \UnexpectedValueException(sprintf('Parameter value "%s" cannot be converted to "string".', $key));
167+
}
168+
169+
return (string) $value;
170+
}
171+
136172
/**
137173
* Returns the parameter value converted to boolean.
138174
*/
139175
public function getBoolean(string $key, bool $default = false): bool
140176
{
141-
return $this->filter($key, $default, \FILTER_VALIDATE_BOOL);
177+
$value = $this->filter($key, $default, \FILTER_VALIDATE_BOOL);
178+
// Could be an array
179+
if (!\is_bool($value)) {
180+
throw new \UnexpectedValueException(sprintf('Parameter value "%s" cannot be converted to "bool".', $key));
181+
}
182+
183+
return $value;
142184
}
143185

144186
/**
@@ -162,6 +204,10 @@ public function filter(string $key, mixed $default = null, int $filter = \FILTER
162204
$options['flags'] = \FILTER_REQUIRE_ARRAY;
163205
}
164206

207+
if (\is_object($value) && !$value instanceof \Stringable) {
208+
throw new \UnexpectedValueException(sprintf('Parameter value "%s" cannot be filtered.', $key));
209+
}
210+
165211
if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) {
166212
throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null)));
167213
}

‎src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,29 @@ public function __toString(): string
3535
$this->assertFalse($bag->get('bool'), '->get() gets the value of a bool parameter');
3636
}
3737

38+
public function testGetString()
39+
{
40+
$bag = new InputBag(['integer' => 123, 'bool_true' => true, 'bool_false' => false, 'string' => 'abc', 'stringable' => new ParamStringable('bar')]);
41+
42+
$this->assertSame('123', $bag->getString('integer'), '->getString() gets a value of parameter as string');
43+
$this->assertSame('abc', $bag->getString('string'), '->getString() gets a value of parameter as string');
44+
$this->assertSame('', $bag->getString('unknown'), '->getString() returns zero if a parameter is not defined');
45+
$this->assertSame('foo', $bag->getString('unknown', 'foo'), '->getString() returns the default if a parameter is not defined');
46+
$this->assertSame('1', $bag->getString('bool_true'), '->getString() returns "1" if a parameter is true');
47+
$this->assertSame('', $bag->getString('bool_false', 'foo'), '->getString() returns an empty empty string if a parameter is false');
48+
$this->assertSame('bar', $bag->getString('stringable'), '->getString() gets a value of a stringable paramater as string');
49+
}
50+
51+
public function testGetStringExceptionWithArray()
52+
{
53+
$bag = new InputBag(['key' => ['abc']]);
54+
55+
$this->expectException(BadRequestException::class);
56+
$this->expectExceptionMessage('Input value "key" contains a non-scalar value.');
57+
58+
$bag->getString('key');
59+
}
60+
3861
public function testGetDoesNotUseDeepByDefault()
3962
{
4063
$bag = new InputBag(['foo' => ['bar' => 'moo']]);
@@ -107,3 +130,15 @@ public function testFilterArrayWithoutArrayFlag()
107130
$bag->filter('foo', \FILTER_VALIDATE_INT);
108131
}
109132
}
133+
134+
class ParamStringable
135+
{
136+
public function __construct(private string $value)
137+
{
138+
}
139+
140+
public function __toString(): string
141+
{
142+
return $this->value;
143+
}
144+
}

‎src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php
+151-13Lines changed: 151 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
namespace Symfony\Component\HttpFoundation\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
1516
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
1617
use Symfony\Component\HttpFoundation\ParameterBag;
1718

1819
class ParameterBagTest extends TestCase
1920
{
21+
use ExpectDeprecationTrait;
22+
2023
public function testConstructor()
2124
{
2225
$this->testAll();
@@ -111,34 +114,154 @@ public function testHas()
111114

112115
public function testGetAlpha()
113116
{
114-
$bag = new ParameterBag(['word' => 'foo_BAR_012']);
117+
$bag = new ParameterBag(['word' => 'foo_BAR_012', 'bool' => true, 'integer' => 123]);
118+
119+
$this->assertSame('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters');
120+
$this->assertSame('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined');
121+
$this->assertSame('abcDEF', $bag->getAlpha('unknown', 'abc_DEF_012'), '->getAlpha() returns filtered default if a parameter is not defined');
122+
$this->assertSame('', $bag->getAlpha('integer', 'abc_DEF_012'), '->getAlpha() returns empty string if a parameter is an integer');
123+
$this->assertSame('', $bag->getAlpha('bool', 'abc_DEF_012'), '->getAlpha() returns empty string if a parameter is a boolean');
124+
}
115125

116-
$this->assertEquals('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters');
117-
$this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined');
126+
public function testGetAlphaExceptionWithArray()
127+
{
128+
$bag = new ParameterBag(['word' => ['foo_BAR_012']]);
129+
130+
$this->expectException(\UnexpectedValueException::class);
131+
$this->expectExceptionMessage('Parameter value "word" cannot be converted to "string".');
132+
133+
$bag->getAlpha('word');
118134
}
119135

120136
public function testGetAlnum()
121137
{
122-
$bag = new ParameterBag(['word' => 'foo_BAR_012']);
138+
$bag = new ParameterBag(['word' => 'foo_BAR_012', 'bool' => true, 'integer' => 123]);
123139

124-
$this->assertEquals('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters');
125-
$this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined');
140+
$this->assertSame('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters');
141+
$this->assertSame('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined');
142+
$this->assertSame('abcDEF012', $bag->getAlnum('unknown', 'abc_DEF_012'), '->getAlnum() returns filtered default if a parameter is not defined');
143+
$this->assertSame('123', $bag->getAlnum('integer', 'abc_DEF_012'), '->getAlnum() returns the number as string if a parameter is an integer');
144+
$this->assertSame('1', $bag->getAlnum('bool', 'abc_DEF_012'), '->getAlnum() returns 1 if a parameter is true');
145+
}
146+
147+
public function testGetAlnumExceptionWithArray()
148+
{
149+
$bag = new ParameterBag(['word' => ['foo_BAR_012']]);
150+
151+
$this->expectException(\UnexpectedValueException::class);
152+
$this->expectExceptionMessage('Parameter value "word" cannot be converted to "string".');
153+
154+
$bag->getAlnum('word');
126155
}
127156

128157
public function testGetDigits()
129158
{
130-
$bag = new ParameterBag(['word' => 'foo_BAR_012']);
159+
$bag = new ParameterBag(['word' => 'foo_BAR_012', 'bool' => true, 'integer' => 123]);
131160

132-
$this->assertEquals('012', $bag->getDigits('word'), '->getDigits() gets only digits as string');
133-
$this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined');
161+
$this->assertSame('012', $bag->getDigits('word'), '->getDigits() gets only digits as string');
162+
$this->assertSame('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined');
163+
$this->assertSame('012', $bag->getDigits('unknown', 'abc_DEF_012'), '->getDigits() returns filtered default if a parameter is not defined');
164+
$this->assertSame('123', $bag->getDigits('integer', 'abc_DEF_012'), '->getDigits() returns the number as string if a parameter is an integer');
165+
$this->assertSame('1', $bag->getDigits('bool', 'abc_DEF_012'), '->getDigits() returns 1 if a parameter is true');
134166
}
135167

168+
public function testGetDigitsExceptionWithArray()
169+
{
170+
$bag = new ParameterBag(['word' => ['foo_BAR_012']]);
171+
172+
$this->expectException(\UnexpectedValueException::class);
173+
$this->expectExceptionMessage('Parameter value "word" cannot be converted to "string".');
174+
175+
$bag->getDigits('word');
176+
}
177+
178+
/**
179+
* @group legacy
180+
*/
136181
public function testGetInt()
137182
{
138-
$bag = new ParameterBag(['digits' => '0123']);
183+
$this->expectDeprecation('Since symfony/http-foundation 6.3: Method "getInt" is deprecated and replaced by "getInteger".');
184+
185+
$bag = new ParameterBag(['digits' => '123', 'bool' => true, 'string' => 'abc']);
186+
187+
$this->assertSame(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer');
188+
$this->assertSame(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined');
189+
$this->assertSame(10, $bag->getInt('unknown', 10), '->getInt() returns the default if a parameter is not defined');
190+
$this->assertSame(1, $bag->getInt('bool', 10), '->getInt() returns zero if a parameter is invalid');
191+
$this->assertSame(0, $bag->getInt('string', 10), '->getInt() returns zero if a parameter is invalid');
192+
}
193+
194+
public function testGetInteger()
195+
{
196+
$bag = new ParameterBag(['digits' => '123', 'bool' => true]);
139197

140-
$this->assertEquals(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer');
141-
$this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined');
198+
$this->assertSame(123, $bag->getInteger('digits'), '->getInteger() gets a value of parameter as integer');
199+
$this->assertSame(0, $bag->getInteger('unknown'), '->getInteger() returns zero if a parameter is not defined');
200+
$this->assertSame(10, $bag->getInteger('unknown', 10), '->getInteger() returns the default if a parameter is not defined');
201+
$this->assertSame(1, $bag->getInteger('bool'), '->getInteger() returns 1 if a parameter is true');
202+
}
203+
204+
public function testGetIntegerExceptionWithArray()
205+
{
206+
$bag = new ParameterBag(['digits' => ['123']]);
207+
208+
$this->expectException(\UnexpectedValueException::class);
209+
$this->expectExceptionMessage('Parameter value "digits" cannot be converted to "int".');
210+
211+
$bag->getInteger('digits');
212+
}
213+
214+
public function testGetIntegerExceptionWithObject()
215+
{
216+
$bag = new ParameterBag(['object' => $this]);
217+
218+
$this->expectException(\UnexpectedValueException::class);
219+
$this->expectExceptionMessage('Parameter value "object" cannot be filtered.');
220+
221+
$bag->getInteger('object');
222+
}
223+
224+
public function testGetIntegerExceptionWithInvalid()
225+
{
226+
$bag = new ParameterBag(['word' => 'foo_BAR_012']);
227+
228+
$this->expectException(\UnexpectedValueException::class);
229+
$this->expectExceptionMessage('Parameter value "word" cannot be converted to "int".');
230+
231+
$bag->getInteger('word');
232+
}
233+
234+
public function testGetString()
235+
{
236+
$bag = new ParameterBag(['integer' => 123, 'bool_true' => true, 'bool_false' => false, 'string' => 'abc', 'stringable' => new InputStringable('bar')]);
237+
238+
$this->assertSame('123', $bag->getString('integer'), '->getString() gets a value of parameter as string');
239+
$this->assertSame('abc', $bag->getString('string'), '->getString() gets a value of parameter as string');
240+
$this->assertSame('', $bag->getString('unknown'), '->getString() returns zero if a parameter is not defined');
241+
$this->assertSame('foo', $bag->getString('unknown', 'foo'), '->getString() returns the default if a parameter is not defined');
242+
$this->assertSame('1', $bag->getString('bool_true'), '->getString() returns "1" if a parameter is true');
243+
$this->assertSame('', $bag->getString('bool_false', 'foo'), '->getString() returns an empty empty string if a parameter is false');
244+
$this->assertSame('bar', $bag->getString('stringable'), '->getString() gets a value of a stringable paramater as string');
245+
}
246+
247+
public function testGetStringExceptionWithArray()
248+
{
249+
$bag = new ParameterBag(['key' => ['abc']]);
250+
251+
$this->expectException(\UnexpectedValueException::class);
252+
$this->expectExceptionMessage('Parameter value "key" cannot be converted to "string".');
253+
254+
$bag->getString('key');
255+
}
256+
257+
public function testGetStringExceptionWithObject()
258+
{
259+
$bag = new ParameterBag(['object' => $this]);
260+
261+
$this->expectException(\UnexpectedValueException::class);
262+
$this->expectExceptionMessage('Parameter value "object" cannot be converted to "string".');
263+
264+
$bag->getString('object');
142265
}
143266

144267
public function testFilter()
@@ -219,11 +342,26 @@ public function testCount()
219342

220343
public function testGetBoolean()
221344
{
222-
$parameters = ['string_true' => 'true', 'string_false' => 'false'];
345+
$parameters = ['string_true' => 'true', 'string_false' => 'false', 'string' => 'abc'];
223346
$bag = new ParameterBag($parameters);
224347

225348
$this->assertTrue($bag->getBoolean('string_true'), '->getBoolean() gets the string true as boolean true');
226349
$this->assertFalse($bag->getBoolean('string_false'), '->getBoolean() gets the string false as boolean false');
227350
$this->assertFalse($bag->getBoolean('unknown'), '->getBoolean() returns false if a parameter is not defined');
351+
$this->assertTrue($bag->getBoolean('unknown', true), '->getBoolean() returns default if a parameter is not defined');
352+
$this->assertFalse($bag->getBoolean('string'), '->getBoolean() returns false if a parameter is invalid');
353+
$this->assertFalse($bag->getBoolean('string', true), '->getBoolean() returns false if a parameter is invalid');
354+
}
355+
}
356+
357+
class InputStringable
358+
{
359+
public function __construct(private string $value)
360+
{
361+
}
362+
363+
public function __toString(): string
364+
{
365+
return $this->value;
228366
}
229367
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.