Skip to content

Commit 8a21226

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: Update ExceptionInterface.php Revert removal of Stringable check Flush with flush() after ob_end_flush() [Validator] : Fix "PHP Warning: Undefined array key 1" in NotCompromisedPasswordValidator [Validator] Fix traverse option on Valid constraint when used as Attribute [HttpFoundation] Fix deleteFileAfterSend on client abortion Prevent that bad Ignore method annotations lead to incorrect results also fix the test fix deprecation fix sending request to paths containing multiple slashes Fix generated validation error message for wrong exception mapping status code
2 parents 40e78fc + f268dd1 commit 8a21226

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

Constraints/NotCompromisedPasswordValidator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ public function validate(mixed $value, Constraint $constraint)
9191
}
9292

9393
foreach (explode("\r\n", $result) as $line) {
94+
if (!str_contains($line, ':')) {
95+
continue;
96+
}
97+
9498
[$hashSuffix, $count] = explode(':', $line);
9599

96100
if ($hashPrefix.$hashSuffix === $hash && $constraint->threshold <= (int) $count) {

Constraints/Valid.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ class Valid extends Constraint
2424
{
2525
public $traverse = true;
2626

27+
public function __construct(array $options = null, array $groups = null, $payload = null, bool $traverse = null)
28+
{
29+
parent::__construct($options ?? [], $groups, $payload);
30+
31+
$this->traverse = $traverse ?? $this->traverse;
32+
}
33+
2734
public function __get(string $option): mixed
2835
{
2936
if ('groups' === $option) {

Tests/Constraints/NotCompromisedPasswordValidatorTest.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,31 @@ public function testInvalidPasswordCustomEndpoint()
162162
->assertRaised();
163163
}
164164

165+
public function testEndpointWithInvalidValueInReturn()
166+
{
167+
$returnValue = implode(
168+
"\r\n",
169+
[
170+
'36039744C253F9B2A4E90CBEDB02EBFB82D:5',
171+
'This should not break the validator',
172+
'3686792BBC66A72D40D928ED15621124CFE:7',
173+
'36EEC709091B810AA240179A44317ED415C:2',
174+
'',
175+
]
176+
);
177+
178+
$validator = new NotCompromisedPasswordValidator(
179+
$this->createHttpClientStub($returnValue),
180+
'UTF-8',
181+
true,
182+
'https://password-check.internal.example.com/range/%s'
183+
);
184+
185+
$validator->validate(self::PASSWORD_NOT_LEAKED, new NotCompromisedPassword());
186+
187+
$this->assertNoViolation();
188+
}
189+
165190
public function testInvalidConstraint()
166191
{
167192
$this->expectException(UnexpectedTypeException::class);
@@ -196,11 +221,11 @@ public function provideErrorSkippingConstraints(): iterable
196221
yield 'named arguments' => [new NotCompromisedPassword(skipOnError: true)];
197222
}
198223

199-
private function createHttpClientStub(): HttpClientInterface
224+
private function createHttpClientStub(?string $returnValue = null): HttpClientInterface
200225
{
201226
$httpClientStub = $this->createMock(HttpClientInterface::class);
202227
$httpClientStub->method('request')->willReturnCallback(
203-
function (string $method, string $url): ResponseInterface {
228+
function (string $method, string $url) use ($returnValue): ResponseInterface {
204229
if (self::PASSWORD_TRIGGERING_AN_ERROR_RANGE_URL === $url) {
205230
throw new class('Problem contacting the Have I been Pwned API.') extends \Exception implements ServerExceptionInterface {
206231
public function getResponse(): ResponseInterface
@@ -213,7 +238,7 @@ public function getResponse(): ResponseInterface
213238
$responseStub = $this->createMock(ResponseInterface::class);
214239
$responseStub
215240
->method('getContent')
216-
->willReturn(implode("\r\n", self::RETURN));
241+
->willReturn($returnValue ?? implode("\r\n", self::RETURN));
217242

218243
return $responseStub;
219244
}

Tests/Constraints/ValidTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Validator\Constraints\Valid;
16+
use Symfony\Component\Validator\Mapping\ClassMetadata;
17+
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
1618

1719
/**
1820
* @author Bernhard Schussek <[email protected]>
@@ -32,4 +34,34 @@ public function testGroupsAreNullByDefault()
3234

3335
$this->assertNull($constraint->groups);
3436
}
37+
38+
/**
39+
* @requires PHP 8
40+
*/
41+
public function testAttributes()
42+
{
43+
$metadata = new ClassMetaData(ValidDummy::class);
44+
$loader = new AnnotationLoader();
45+
self::assertTrue($loader->loadClassMetadata($metadata));
46+
47+
[$bConstraint] = $metadata->properties['b']->getConstraints();
48+
self::assertFalse($bConstraint->traverse);
49+
self::assertSame(['traverse_group'], $bConstraint->groups);
50+
51+
[$cConstraint] = $metadata->properties['c']->getConstraints();
52+
self::assertSame(['my_group'], $cConstraint->groups);
53+
self::assertSame('some attached data', $cConstraint->payload);
54+
}
55+
}
56+
57+
class ValidDummy
58+
{
59+
#[Valid]
60+
private $a;
61+
62+
#[Valid(groups: ['traverse_group'], traverse: false)] // Needs a group to work at all for this test
63+
private $b;
64+
65+
#[Valid(groups: ['my_group'], payload: 'some attached data')]
66+
private $c;
3567
}

0 commit comments

Comments
 (0)