1
|
|
|
<?php namespace Sample; |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Copyright 2015-2017 [email protected] |
5
|
|
|
* |
6
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
7
|
|
|
* you may not use this file except in compliance with the License. |
8
|
|
|
* You may obtain a copy of the License at |
9
|
|
|
* |
10
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0 |
11
|
|
|
* |
12
|
|
|
* Unless required by applicable law or agreed to in writing, software |
13
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
14
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15
|
|
|
* See the License for the specific language governing permissions and |
16
|
|
|
* limitations under the License. |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
use DateTime; |
20
|
|
|
use DateTimeInterface; |
21
|
|
|
use Limoncello\Validation\ArrayValidator as vv; |
22
|
|
|
use Limoncello\Validation\Contracts\Captures\CaptureAggregatorInterface; |
23
|
|
|
use Limoncello\Validation\Contracts\Errors\ErrorAggregatorInterface; |
24
|
|
|
use Limoncello\Validation\Contracts\Errors\ErrorInterface; |
25
|
|
|
use Limoncello\Validation\SingleValidator as v; |
26
|
|
|
use MessageFormatter; |
27
|
|
|
use Sample\Validation\CustomErrorMessages; |
28
|
|
|
use Sample\Validation\CustomRules as r; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @package Sample |
32
|
|
|
*/ |
33
|
|
|
class Application |
34
|
|
|
{ |
35
|
|
|
/** |
36
|
|
|
* @var bool |
37
|
|
|
*/ |
38
|
|
|
private $isOutputToConsole; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @param bool $isOutputToConsole |
42
|
|
|
*/ |
43
|
|
|
public function __construct(bool $isOutputToConsole = true) |
44
|
|
|
{ |
45
|
|
|
$this->isOutputToConsole = $isOutputToConsole; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @return void |
50
|
|
|
*/ |
51
|
|
|
public function run(): void |
52
|
|
|
{ |
53
|
|
|
$this->showSingleValueValidation(); |
54
|
|
|
|
55
|
|
|
$this->showArrayValuesValidation(); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Shows single value validation with built-in rules. |
60
|
|
|
*/ |
61
|
|
|
private function showSingleValueValidation(): void |
62
|
|
|
{ |
63
|
|
|
$this->console('Basic usage sample.' . PHP_EOL); |
64
|
|
|
$this->console('===================' . PHP_EOL); |
65
|
|
|
|
66
|
|
|
// Let's build a rule that validates an input to be either `null` or a string from 5 to 10 characters. |
67
|
|
|
$validator = v::validator( |
68
|
|
|
r::nullable(r::isString(r::stringLengthBetween(5, 10))) |
69
|
|
|
); |
70
|
|
|
|
71
|
|
|
// let's try validation with valid input |
72
|
|
|
$input = null; |
73
|
|
View Code Duplication |
if ($validator->validate($input) === true) { |
|
|
|
|
74
|
|
|
$this->console("Validation OK for `null`." . PHP_EOL); |
75
|
|
|
} else { |
76
|
|
|
assert(false, 'We should not be here.'); |
77
|
|
|
} |
78
|
|
|
// another one |
79
|
|
|
$input = 'Hello'; |
80
|
|
View Code Duplication |
if ($validator->validate($input) === true) { |
|
|
|
|
81
|
|
|
$this->console("Validation OK for `$input`." . PHP_EOL); |
82
|
|
|
} else { |
83
|
|
|
assert(false, 'We should not be here.'); |
84
|
|
|
} |
85
|
|
|
// this one should not pass the validation |
86
|
|
|
$input = 'This string is too long.'; |
87
|
|
|
if ($validator->validate($input) === false) { |
88
|
|
|
$this->console("Input `$input` has not passed validation." . PHP_EOL); |
89
|
|
|
$this->printErrors($validator->getErrors()); |
90
|
|
|
} else { |
91
|
|
|
assert(false, 'We should not be here.'); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
// next example demonstrates |
95
|
|
|
// - parsing strings as dates |
96
|
|
|
// - validation for dates |
97
|
|
|
// - data capture so you don't need to parse the input second time after validation |
98
|
|
|
$fromDate = new DateTime('2001-02-03'); |
99
|
|
|
$toDate = new DateTime('2001-04-05'); |
100
|
|
|
$validator = v::validator( |
101
|
|
|
r::isString(r::stringToDateTime(DATE_ATOM, r::between($fromDate, $toDate))) |
102
|
|
|
->setName('my_date')->enableCapture() |
103
|
|
|
); |
104
|
|
|
$input = '2001-03-04T05:06:07+08:00'; |
105
|
|
|
if ($validator->validate($input) === true) { |
106
|
|
|
$this->console("Validation OK for `$input`." . PHP_EOL); |
107
|
|
|
$myDate = $validator->getCaptures()->get()['my_date']; |
108
|
|
|
// note that captured date is already DateTime |
109
|
|
|
assert($myDate instanceof DateTimeInterface); |
110
|
|
|
} else { |
111
|
|
|
assert(false, 'We should not be here.'); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
$this->console(PHP_EOL . PHP_EOL . PHP_EOL); |
115
|
|
|
|
116
|
|
|
// The output would be |
117
|
|
|
// ------------------------------------------------------------------------------------------------------- |
118
|
|
|
// Basic usage sample. |
119
|
|
|
// =================== |
120
|
|
|
// Validation OK for `null`. |
121
|
|
|
// Validation OK for `Hello`. |
122
|
|
|
// Input `This string is too long to pass validation.` has not passed validation. |
123
|
|
|
// Validation failed for `This string is too long.` with: The value should be between 5 and 10 characters. |
124
|
|
|
// Validation OK for `2001-03-04T05:06:07+08:00`. |
125
|
|
|
// ------------------------------------------------------------------------------------------------------- |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Shows validation for array values with custom rules. |
130
|
|
|
*/ |
131
|
|
|
private function showArrayValuesValidation(): void |
132
|
|
|
{ |
133
|
|
|
$this->console('Advanced usage sample.' . PHP_EOL); |
134
|
|
|
$this->console('===================' . PHP_EOL); |
135
|
|
|
|
136
|
|
|
// Validation rules for input are |
137
|
|
|
// - `email` must be a string and a valid email value (as FILTER_VALIDATE_EMAIL describes) |
138
|
|
|
// - `first_name` required in input, must be a string with length from 1 to 255 characters |
139
|
|
|
// - `last_name` could be either `null` or if given it must be a string with length from 1 to 255 characters |
140
|
|
|
// - `payment_plan` must be a valid index for data in database (we will emulate request to database) |
141
|
|
|
$validator = vv::validator([ |
142
|
|
|
'email' => r::isEmail(), |
143
|
|
|
'first_name' => r::isRequiredString(255), |
144
|
|
|
'last_name' => r::isNullOrNonEmptyString(255), |
145
|
|
|
'payment_plan' => r::isExistingPaymentPlan(), |
146
|
|
|
]); |
147
|
|
|
|
148
|
|
|
// Check with invalid data |
149
|
|
|
$invalidInput = [ |
150
|
|
|
'email' => 'john.dow', |
151
|
|
|
//'first_name' => 'John', |
152
|
|
|
'last_name' => '', |
153
|
|
|
'payment_plan' => '123', |
154
|
|
|
]; |
155
|
|
|
$this->console('Invalid data (errors)' . PHP_EOL); |
156
|
|
|
$validator->validate($invalidInput); |
157
|
|
|
$this->printErrors($validator->getErrors()); |
158
|
|
|
$this->console('Invalid data (captures)' . PHP_EOL); |
159
|
|
|
$this->printCaptures($validator->getCaptures()); |
160
|
|
|
|
161
|
|
|
// Check with valid data |
162
|
|
|
$validInput = [ |
163
|
|
|
'email' => '[email protected]', |
164
|
|
|
'first_name' => 'John', |
165
|
|
|
'last_name' => null, |
166
|
|
|
'payment_plan' => '2', |
167
|
|
|
]; |
168
|
|
|
$this->console(PHP_EOL . 'Valid data (errors)' . PHP_EOL); |
169
|
|
|
$validator->validate($validInput); |
170
|
|
|
$this->printErrors($validator->getErrors()); |
171
|
|
|
$this->console('Valid data (captures)' . PHP_EOL); |
172
|
|
|
$this->printCaptures($validator->getCaptures()); |
173
|
|
|
|
174
|
|
|
// The output would be |
175
|
|
|
// ------------------------------------------------------------------------------------------------------- |
176
|
|
|
// Advanced usage sample. |
177
|
|
|
// =================== |
178
|
|
|
// Invalid data (errors) |
179
|
|
|
// Param `email` failed for `john.dow` with: The value should be a valid email address. |
180
|
|
|
// Param `last_name` failed for `` with: The value should be between 1 and 255 characters. |
181
|
|
|
// Param `payment_plan` failed for `123` with: The value should be a valid payment plan. |
182
|
|
|
// Param `first_name` failed for `` with: The value is required. |
183
|
|
|
// Invalid data (captures) |
184
|
|
|
// No captures |
185
|
|
|
// |
186
|
|
|
// Valid data (errors) |
187
|
|
|
// No errors |
188
|
|
|
// Valid data (captures) |
189
|
|
|
// `email` = `[email protected]` (string) |
|
|
|
|
190
|
|
|
// `first_name` = `John` (string) |
|
|
|
|
191
|
|
|
// `last_name` = `` (NULL) |
|
|
|
|
192
|
|
|
// `payment_plan` = `2` (integer) |
|
|
|
|
193
|
|
|
// ------------------------------------------------------------------------------------------------------- |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @param ErrorAggregatorInterface $errors |
198
|
|
|
* |
199
|
|
|
* @return void |
200
|
|
|
*/ |
201
|
|
|
private function printErrors(ErrorAggregatorInterface $errors): void |
202
|
|
|
{ |
203
|
|
|
$hasErrors = false; |
204
|
|
|
|
205
|
|
|
foreach ($errors->get() as $error) { |
206
|
|
|
$hasErrors = true; |
207
|
|
|
$this->printError($error); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
if ($hasErrors === false) { |
211
|
|
|
$this->console('No errors' . PHP_EOL); |
212
|
|
|
} |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* @param ErrorInterface $error |
217
|
|
|
* |
218
|
|
|
* @return void |
219
|
|
|
*/ |
220
|
|
|
private function printError(ErrorInterface $error): void |
221
|
|
|
{ |
222
|
|
|
$paramName = $error->getParameterName(); |
223
|
|
|
$entry = empty($paramName) ? 'Validation' : "Param `$paramName`"; |
224
|
|
|
$paramValue = $error->getParameterValue(); |
225
|
|
|
$errorMsg = CustomErrorMessages::MESSAGES[$error->getMessageCode()]; |
226
|
|
|
$context = $error->getMessageContext(); |
227
|
|
|
$errorMsg = MessageFormatter::formatMessage('en', $errorMsg, $context !== null ? $context : []); |
228
|
|
|
|
229
|
|
|
$this->console("$entry failed for `$paramValue` with: $errorMsg" . PHP_EOL); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* @param CaptureAggregatorInterface $captures |
234
|
|
|
* |
235
|
|
|
* @return void |
236
|
|
|
*/ |
237
|
|
|
private function printCaptures(CaptureAggregatorInterface $captures): void |
238
|
|
|
{ |
239
|
|
|
$hasCaptures = false; |
240
|
|
|
|
241
|
|
|
foreach ($captures->get() as $name => $value) { |
242
|
|
|
$hasCaptures = true; |
243
|
|
|
$type = gettype($value); |
244
|
|
|
$this->console("`$name` = `$value` ($type)" . PHP_EOL); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
if ($hasCaptures === false) { |
248
|
|
|
$this->console('No captures' . PHP_EOL); |
249
|
|
|
} |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* @param string $string |
254
|
|
|
*/ |
255
|
|
|
private function console(string $string): void |
256
|
|
|
{ |
257
|
|
|
if ($this->isOutputToConsole === true) { |
258
|
|
|
echo $string; |
259
|
|
|
} |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.