Skip to content

Commit 466c5c0

Browse files
committed
add non empty string constraint
1 parent fa83713 commit 466c5c0

File tree

7 files changed

+148
-7
lines changed

7 files changed

+148
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- `Innmind\Validation\Constraint::object()`
88
- `Innmind\Validation\Constraint::failWith()`
9+
- `Innmind\Validation\Constraint::string()->nonEmpty()`
910
- `Innmind\Validation\Constraint\Provider`
1011

1112
### Changed

docs/constraints/primitives.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
$validate = Is::string();
88
```
99

10+
=== "`non-empty-string`"
11+
```php
12+
use Innmind\Validation\Is;
13+
14+
$validate = Is::string()->nonEmpty();
15+
```
16+
1017
=== "`int`"
1118
```php
1219
use Innmind\Validation\Is;

proofs/is.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,68 @@ static function($assert, $string, $other) {
5454
},
5555
);
5656

57+
yield proof(
58+
'Is::string()->nonEmpty()',
59+
given(
60+
Set::strings()->atLeast(1),
61+
Set::either(
62+
Set::integers(),
63+
Set::realNumbers(),
64+
Set::of(
65+
true,
66+
false,
67+
null,
68+
new stdClass,
69+
),
70+
Set::sequence(Set::strings()),
71+
),
72+
),
73+
static function($assert, $string, $other) {
74+
$constraint = Is::string()->nonEmpty();
75+
76+
$assert->true(
77+
$constraint->asPredicate()($string),
78+
);
79+
$assert->same(
80+
$string,
81+
$constraint($string)->match(
82+
static fn($value) => $value,
83+
static fn() => null,
84+
),
85+
);
86+
$assert->false(
87+
$constraint->asPredicate()($other),
88+
);
89+
$assert->same(
90+
[['$', 'Value is not of type string']],
91+
$constraint($other)->match(
92+
static fn() => null,
93+
static fn($failures) => $failures
94+
->map(static fn($failure) => [
95+
$failure->path()->toString(),
96+
$failure->message(),
97+
])
98+
->toList(),
99+
),
100+
);
101+
$assert->false(
102+
$constraint->asPredicate()(''),
103+
);
104+
$assert->same(
105+
[['$', 'String cannot be empty']],
106+
$constraint('')->match(
107+
static fn() => null,
108+
static fn($failures) => $failures
109+
->map(static fn($failure) => [
110+
$failure->path()->toString(),
111+
$failure->message(),
112+
])
113+
->toList(),
114+
),
115+
);
116+
},
117+
);
118+
57119
yield proof(
58120
'Is::string()->withFailure()',
59121
given(

src/Constraint.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,10 @@ public static function object(): Provider\Objet
6262

6363
/**
6464
* @psalm-pure
65-
*
66-
* @return self<mixed, string>
6765
*/
68-
public static function string(): self
66+
public static function string(): Provider\Str
6967
{
70-
return new self(Constraint\Primitive::string());
68+
return Provider\Str::of(self::build(...));
7169
}
7270

7371
/**

src/Constraint/Like.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ public function failWith(string $message): Constraint
8686
->failWith($message);
8787
}
8888

89+
/**
90+
* @deprecated Use self::failWith(), this method exist for backaward compatibility
91+
*
92+
* @param non-empty-string $message
93+
*
94+
* @return Constraint<I, O>
95+
*/
96+
public function withFailure(string $message): Constraint
97+
{
98+
return $this->failWith($message);
99+
}
100+
89101
/**
90102
* @return Predicate<O>
91103
*/

src/Constraint/Provider/Str.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace Innmind\Validation\Constraint\Provider;
5+
6+
use Innmind\Validation\{
7+
Constraint,
8+
Constraint\Provider,
9+
Constraint\Implementation,
10+
Constraint\Primitive,
11+
Constraint\Like,
12+
Failure,
13+
};
14+
use Innmind\Immutable\Validation;
15+
16+
/**
17+
* @psalm-immutable
18+
* @implements Provider<mixed, string>
19+
*/
20+
final class Str implements Provider
21+
{
22+
/** @use Like<mixed, string> */
23+
use Like;
24+
25+
/**
26+
* @param pure-Closure(Implementation): Constraint $build
27+
*/
28+
private function __construct(
29+
private \Closure $build,
30+
) {
31+
}
32+
33+
/**
34+
* @internal
35+
* @psalm-pure
36+
*
37+
* @param pure-Closure(Implementation): Constraint $build
38+
*/
39+
public static function of(\Closure $build): self
40+
{
41+
return new self($build);
42+
}
43+
44+
#[\Override]
45+
public function toConstraint(): Constraint
46+
{
47+
/** @var Constraint<mixed, string> */
48+
return ($this->build)(Primitive::string());
49+
}
50+
51+
/**
52+
* @return Constraint<mixed, non-empty-string>
53+
*/
54+
public function nonEmpty(): Constraint
55+
{
56+
return $this
57+
->toConstraint()
58+
->and(Constraint::of(static fn(string $string) => match ($string) {
59+
'' => Validation::fail(Failure::of('String cannot be empty')),
60+
default => Validation::success($string),
61+
}));
62+
}
63+
}

src/Is.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ private function __construct()
2121

2222
/**
2323
* @psalm-pure
24-
*
25-
* @return Constraint<mixed, string>
2624
*/
27-
public static function string(): Constraint
25+
public static function string(): Provider\Str
2826
{
2927
return Constraint::string();
3028
}

0 commit comments

Comments
 (0)