|
92 | 92 | * You want the name to be unique for a specific type in the division: *unique:type,shoes,division* |
93 | 93 | * You want the name to be unique for a specific type and division: *unique:type,shoes,division,10* |
94 | 94 | * |
| 95 | + * ## OR Operator |
| 96 | + * You can validate a field if any one of the validators passes. Use the vertical bar (|) to separate validators. If one of the validators passes, then the the field is valid. |
| 97 | + * |
| 98 | + * **Example:** |
| 99 | + * website|starts_with:/ will validate a fully qualified http url, or a root relative url. |
| 100 | + * |
95 | 101 | * ## Optional Validation |
96 | 102 | * You may need to do additional checks for a specific record type. A second parameter can be passed to the contructor which would represent the original values of the record. |
97 | 103 | * |
@@ -167,9 +173,9 @@ public function validate(string $optionalMethod = '') : bool |
167 | 173 | /** |
168 | 174 | * Gets the errors for a value with the record definition and associated validators |
169 | 175 | * |
170 | | - * @param array<int, array<mixed>> $fieldDefinitions |
| 176 | + * @param array<int, array<string>> $fieldDefinitions |
171 | 177 | * |
172 | | - * @return array of errors of translated text |
| 178 | + * @return array<string> of errors of translated text |
173 | 179 | */ |
174 | 180 | private function getFieldErrors(mixed $value, array $validators, array $fieldDefinitions) : array |
175 | 181 | { |
@@ -203,35 +209,40 @@ private function getFieldErrors(mixed $value, array $validators, array $fieldDef |
203 | 209 | return $errors; |
204 | 210 | } |
205 | 211 |
|
| 212 | + $orErrors = []; |
| 213 | + |
206 | 214 | foreach ($validators as $validator) |
207 | 215 | { |
208 | | - $parts = \explode(':', (string)$validator); |
209 | | - |
210 | | - $parameters = []; |
| 216 | + // Implements OR logic, any rule passes, the whole rule passes |
| 217 | + $orValidators = \explode('|', (string)$validator); |
211 | 218 |
|
212 | | - if (\count($parts) > 1) |
| 219 | + if (\count($orValidators) > 1) |
213 | 220 | { |
214 | | - $parameters = \explode(',', $parts[1]); |
215 | | - } |
216 | | - $validator = $parts[0]; |
217 | | - $method = 'validate_' . $validator; |
218 | | - |
219 | | - if (\method_exists($this, $method)) |
220 | | - { |
221 | | - $error = $this->{$method}($value, $parameters, $fieldDefinitions); |
| 221 | + $orErrors = []; |
222 | 222 |
|
223 | | - if ($error) |
| 223 | + foreach ($orValidators as $validator) |
224 | 224 | { |
225 | | - $errors[] = $error; |
| 225 | + $error = $this->validateRule($validator, $value, $fieldDefinitions); |
| 226 | + |
| 227 | + if ($error) |
| 228 | + { |
| 229 | + $orErrors = \array_merge($orErrors, $error); |
| 230 | + } |
| 231 | + else |
| 232 | + { |
| 233 | + $orErrors = []; |
| 234 | + |
| 235 | + break; |
| 236 | + } |
226 | 237 | } |
227 | 238 | } |
228 | 239 | else |
229 | 240 | { |
230 | | - throw new \Exception("Validator {$validator} (validate_{$validator} method) not found in class " . self::class); |
| 241 | + $errors = \array_merge($errors, $this->validateRule($validator, $value, $fieldDefinitions)); |
231 | 242 | } |
232 | 243 | } |
233 | 244 |
|
234 | | - return $errors; |
| 245 | + return \array_merge($errors, $orErrors); |
235 | 246 | } |
236 | 247 |
|
237 | 248 | /** |
@@ -873,4 +884,40 @@ private function validate_year_month(mixed $value, array $parameters, array $fie |
873 | 884 |
|
874 | 885 | return \checkdate((int)($parts[$month] ?? 0), $day, (int)($parts[$year] ?? 0)) ? '' : \PHPFUI\ORM::trans('.validator.year_month', ['value' => $value]); |
875 | 886 | } |
| 887 | + |
| 888 | + /** |
| 889 | + * Validate one rule. |
| 890 | + * |
| 891 | + * @return array<string> of errors of translated text |
| 892 | + */ |
| 893 | + private function validateRule(string $validator, mixed $value, array $fieldDefinitions) : array |
| 894 | + { |
| 895 | + $parts = \explode(':', (string)$validator); |
| 896 | + |
| 897 | + $parameters = $errors = []; |
| 898 | + |
| 899 | + if (\count($parts) > 1) |
| 900 | + { |
| 901 | + $parameters = \explode(',', $parts[1]); |
| 902 | + } |
| 903 | + $validator = $parts[0]; |
| 904 | + |
| 905 | + $method = 'validate_' . $validator; |
| 906 | + |
| 907 | + if (\method_exists($this, $method)) |
| 908 | + { |
| 909 | + $error = $this->{$method}($value, $parameters, $fieldDefinitions); |
| 910 | + |
| 911 | + if ($error) |
| 912 | + { |
| 913 | + $errors[] = $error; |
| 914 | + } |
| 915 | + } |
| 916 | + else |
| 917 | + { |
| 918 | + throw new \Exception("Validator {$validator} (validate_{$validator} method) not found in class " . self::class); |
| 919 | + } |
| 920 | + |
| 921 | + return $errors; |
| 922 | + } |
876 | 923 | } |
0 commit comments