Skip to content

Commit 501829e

Browse files
committed
Prevent validators from generating validatorBuilder Ids
When calling `v::validatorName()`, a `ValidatorBuilder` is instantiated to manage the validation chain. However, users generally expect the ID to reflect the specific validator invoked rather than the internal builder class. This commit updates `Id::fromValidator()` to resolve the ID from the underlying validator when it is the sole member of the `ValidatorBuilder`, ensuring more intuitive identification.
1 parent aee9123 commit 501829e

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

src/Id.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace Respect\Validation;
1212

13+
use function count;
1314
use function lcfirst;
1415
use function strrchr;
1516
use function substr;
@@ -24,6 +25,10 @@ public function __construct(
2425

2526
public static function fromValidator(Validator $validator): self
2627
{
28+
if ($validator instanceof ValidatorBuilder && count($validator->getValidators()) === 1) {
29+
return self::fromValidator($validator->getValidators()[0]);
30+
}
31+
2732
return new self(lcfirst(substr((string) strrchr($validator::class, '\\'), 1)));
2833
}
2934

tests/unit/IdTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Respect\Validation;
11+
12+
use PHPUnit\Framework\Attributes\CoversClass;
13+
use PHPUnit\Framework\Attributes\Test;
14+
use Respect\Validation\Test\TestCase;
15+
use Respect\Validation\Validators\AlwaysInvalid;
16+
17+
#[CoversClass(Id::class)]
18+
final class IdTest extends TestCase
19+
{
20+
#[Test]
21+
public function shouldCreateInstanceWithValue(): void
22+
{
23+
$id = new Id('test');
24+
25+
self::assertSame('test', $id->value);
26+
}
27+
28+
#[Test]
29+
public function shouldCreateIdFromSimpleValidator(): void
30+
{
31+
$validator = new AlwaysInvalid();
32+
$id = Id::fromValidator($validator);
33+
34+
self::assertSame('alwaysInvalid', $id->value);
35+
}
36+
37+
#[Test]
38+
public function shouldCreateIdFromNestedValidatorBuilder(): void
39+
{
40+
$validator = ValidatorBuilder::stringType();
41+
42+
$id = Id::fromValidator($validator);
43+
44+
self::assertSame('stringType', $id->value);
45+
}
46+
47+
#[Test]
48+
public function shouldCreateIdFromMultipleValidatorsInBuilder(): void
49+
{
50+
$validator = ValidatorBuilder::stringType()->intType();
51+
52+
$id = Id::fromValidator($validator);
53+
54+
self::assertSame('validatorBuilder', $id->value);
55+
}
56+
57+
#[Test]
58+
public function shouldAddPrefixToValue(): void
59+
{
60+
$id = new Id('test');
61+
$prefixed = $id->withPrefix('my');
62+
63+
self::assertSame('myTest', $prefixed->value);
64+
self::assertNotSame($id, $prefixed);
65+
}
66+
67+
#[Test]
68+
public function shouldHandleEmptyValueWithPrefix(): void
69+
{
70+
$id = new Id('');
71+
$prefixed = $id->withPrefix('prefix');
72+
73+
self::assertSame('prefix', $prefixed->value);
74+
}
75+
76+
#[Test]
77+
public function shouldHandleMultipleRecursionInFromValidator(): void
78+
{
79+
$validator = ValidatorBuilder::init(ValidatorBuilder::stringType());
80+
81+
$id = Id::fromValidator($validator);
82+
83+
self::assertSame('stringType', $id->value);
84+
}
85+
}

0 commit comments

Comments
 (0)