|
1
|
<?php |
|
2
|
|
|
3
|
namespace mini; |
|
4
|
|
|
5
|
use mini\Validator\Validator; |
|
6
|
use mini\Validator\ValidatorStore; |
|
7
|
use mini\Validator\AttributeValidatorFactory; |
|
8
|
use mini\Validator\Purpose; |
|
9
|
|
|
10
|
// Register Validator services |
|
11
|
Mini::$mini->addService(Validator::class, Lifetime::Transient, fn() => new Validator()); |
|
12
|
Mini::$mini->addService(ValidatorStore::class, Lifetime::Singleton, fn() => new ValidatorStore()); |
|
13
|
Mini::$mini->addService(AttributeValidatorFactory::class, Lifetime::Singleton, fn() => new AttributeValidatorFactory()); |
|
14
|
|
|
15
|
/** |
|
16
|
* Get or create a Validator instance |
|
17
|
* |
|
18
|
* With no arguments: Returns a new Validator for building validation rules. |
|
19
|
* With class name: Returns the core validator (auto-built from class attributes). |
|
20
|
* With class name + purpose: Returns the purpose-specific validator. |
|
21
|
* |
|
22
|
* ## Examples |
|
23
|
* |
|
24
|
* ```php |
|
25
|
* // New validator for building rules |
|
26
|
* $v = validator()->type('string')->minLength(5); |
|
27
|
* |
|
28
|
* // Core validator (auto-built from class attributes) |
|
29
|
* $v = validator(User::class); |
|
30
|
* |
|
31
|
* // Purpose-specific validators |
|
32
|
* $v = validator(User::class, Purpose::Create); |
|
33
|
* $v = validator(User::class, Purpose::Update); |
|
34
|
* |
|
35
|
* // Custom purpose (string) |
|
36
|
* $v = validator(User::class, 'password-reset'); |
|
37
|
* ``` |
|
38
|
* |
|
39
|
* ## Validation Flow |
|
40
|
* |
|
41
|
* Purpose validation is done in the application layer: |
|
42
|
* ```php |
|
43
|
* // In controller/service |
|
44
|
* if ($error = validator(User::class, Purpose::Create)->isInvalid($user)) { |
|
45
|
* throw new ValidationException($error); |
|
46
|
* } |
|
47
|
* ``` |
|
48
|
* |
|
49
|
* Core validation is done in the repository layer: |
|
50
|
* ```php |
|
51
|
* // In repository |
|
52
|
* if ($error = validator(User::class)->isInvalid($user)) { |
|
53
|
* throw new ValidationException($error); |
|
54
|
* } |
|
55
|
* ``` |
|
56
|
* |
|
57
|
* @param class-string|string|null $classOrName Class name or custom identifier |
|
58
|
* @param Purpose|string|null $purpose Optional purpose scope (Create, Update, or custom string) |
|
59
|
* @return Validator Validator instance |
|
60
|
* @throws \InvalidArgumentException If identifier not found and not a valid class |
|
61
|
*/ |
|
62
|
function validator(?string $classOrName = null, Purpose|string|null $purpose = null): Validator { |
|
63
|
// No argument: return new validator |
|
64
|
if ($classOrName === null) { |
|
65
|
return Mini::$mini->get(Validator::class); |
|
66
|
} |
|
67
|
|
|
68
|
$store = Mini::$mini->get(ValidatorStore::class); |
|
69
|
|
|
70
|
// Get from store (auto-builds from attributes if class/interface and no purpose) |
|
71
|
$validator = $store->get($classOrName, $purpose); |
|
72
|
|
|
73
|
if ($validator === null) { |
|
74
|
// Standard purposes (Purpose enum) are opt-in: return empty validator |
|
75
|
if ($purpose instanceof Purpose) { |
|
76
|
return Mini::$mini->get(Validator::class); |
|
77
|
} |
|
78
|
|
|
79
|
// Custom string purposes and core validators: throw if not found |
|
80
|
$msg = $purpose !== null |
|
81
|
? "Validator '$classOrName' with purpose '$purpose' not found. Register it in ValidatorStore." |
|
82
|
: "Validator '$classOrName' not found. Register it in ValidatorStore or ensure the class exists."; |
|
83
|
throw new \InvalidArgumentException($msg); |
|
84
|
} |
|
85
|
|
|
86
|
// Return clone to allow modifications without affecting cached version |
|
87
|
return clone $validator; |
|
88
|
} |
|
89
|
|