From cff57e88f213c74d4088026b244d411d70197687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ch=C3=A2u=20Ng=E1=BB=8Dc=20Long?= Date: Tue, 13 Oct 2026 14:35:43 +0700 Subject: [PATCH] feat: add conditional required validators --- README.md | 61 ++++++ gump.class.php | 193 +++++++++++++++++- lang/de.php | 5 + lang/el.php | 5 + lang/en.php | 5 + lang/eo.php | 5 + lang/es.php | 5 + lang/fa.php | 5 + lang/fr.php | 5 + lang/he.php | 5 + lang/hu.php | 5 + lang/id.php | 5 + lang/it.php | 5 + lang/ja.php | 5 + lang/nl.php | 5 + lang/pt-br.php | 5 + lang/ru.php | 5 + lang/tr.php | 5 + lang/uk.php | 5 + lang/vi.php | 5 + lang/zh-CN.php | 5 + tests/StaticSetErrorMessagesTest.php | 89 ++++++++ .../RequiredArrayKeysValidatorTest.php | 51 +++++ .../RequiredWithAllValidatorTest.php | 63 ++++++ .../Validators/RequiredWithValidatorTest.php | 59 ++++++ .../RequiredWithoutValidatorTest.php | 68 ++++++ 26 files changed, 669 insertions(+), 10 deletions(-) create mode 100644 tests/Validators/RequiredArrayKeysValidatorTest.php create mode 100644 tests/Validators/RequiredWithAllValidatorTest.php create mode 100644 tests/Validators/RequiredWithValidatorTest.php create mode 100644 tests/Validators/RequiredWithoutValidatorTest.php diff --git a/README.md b/README.md index d8915f7..4b09693 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,11 @@ GUMP provides **76 built-in validators** for comprehensive data validation: | Rule | Description | |--------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **required** | Ensures the specified key value exists and is not empty (not null, not empty string, not empty array). | +| **required_with**,field1;field2 | Field is required when ANY of the specified fields are present and not empty. | +| **required_with_all**,field1;field2 | Field is required when ALL of the specified fields are present and not empty. | +| **required_without**,field1;field2 | Field is required when ANY of the specified fields are not present or empty. | +| **required_without_all**,field1;field2 | Field is required when ALL of the specified fields are not present or empty. | +| **required_array_keys**,key1;key2 | Field must be an array and contain all specified keys. | | **contains**,one;two;use array format if one of the values contains semicolons | Verify that a value is contained within the pre-defined value set. | | **contains_list**,value1;value2 | Verify that a value is contained within the pre-defined value set. Error message will NOT show the list of possible values. | | **doesnt_contain_list**,value1;value2 | Verify that a value is contained within the pre-defined value set. Error message will NOT show the list of possible values. | @@ -319,6 +324,62 @@ GUMP provides **76 built-in validators** for comprehensive data validation: 'title' => 'between_len,5;100' // Handles émojis, ñ, etc. correctly ``` +### Conditional Required Validators + +**`required_with,field1;field2`** - Field required when ANY specified field is present + +```php +// String format +'recipient_name' => 'required_with,shipping_address' + +// Array format +'recipient_name' => ['required_with' => ['shipping_address']] + +// Multiple trigger fields +'recipient_name' => 'required_with,shipping_address;billing_address' +'recipient_name' => ['required_with' => ['shipping_address', 'billing_address']] +``` + +**`required_with_all,field1;field2`** - Field required when ALL specified fields are present + +```php +// String format +'order_note' => 'required_with_all,shipping_address;billing_address' + +// Array format +'order_note' => ['required_with_all' => ['shipping_address', 'billing_address']] +``` + +**`required_without,field1;field2`** - Field required when ANY specified field is missing/empty + +```php +// String format +'contact_email' => 'required_without,phone;mobile' + +// Array format +'contact_email' => ['required_without' => ['phone', 'mobile']] +``` + +**`required_without_all,field1;field2`** - Field required when ALL specified fields are missing/empty + +```php +// String format +'contact_email' => 'required_without_all,phone;mobile' + +// Array format +'contact_email' => ['required_without_all' => ['phone', 'mobile']] +``` + +**`required_array_keys,key1;key2`** - Array must contain all specified keys + +```php +// String format +'data' => 'required_array_keys,id;name' + +// Array format +'data' => ['required_array_keys' => ['id', 'name']] +``` + ### Real-World Usage Examples **User Registration Form** diff --git a/gump.class.php b/gump.class.php index a8115f0..a08d219 100644 --- a/gump.class.php +++ b/gump.class.php @@ -600,6 +600,36 @@ private function parse_rule_params($param) return [ $param ]; } + /** + * Extracts the rule name from a rule definition. + * + * @param mixed $rule_definition + * @return string + * @throws RuntimeException If definition is invalid or extracted name is empty. + */ + private function extract_rule_name_from_definition($rule_definition) + { + if (is_array($rule_definition) && !empty($rule_definition)) { + $rule_name = reset($rule_definition); + } elseif (is_string($rule_definition)) { + $rule_name = $rule_definition; + } else { + throw new RuntimeException(sprintf('Invalid rule definition: expected non-empty array or string, got %s.', gettype($rule_definition))); + } + + if (is_string($rule_name)) { + $rule_name = strtok($rule_name, self::$rules_parameters_delimiter); + } + + $rule_name = is_string($rule_name) ? trim($rule_name) : ''; + + if ($rule_name === '') { + throw new RuntimeException('Invalid rule name: extracted rule name must not be empty.'); + } + + return $rule_name; + } + /** * Checks if array of rules contains a required type of validator. * @@ -608,18 +638,21 @@ private function parse_rule_params($param) */ private function field_has_required_rules(array $rules) { - $require_type_of_rules = ['required', 'required_file']; + $require_type_of_rules = [ + 'required', + 'required_file', + 'required_with', + 'required_with_all', + 'required_without', + 'required_without_all', + 'required_array_keys', + ]; - // v2 format (using arrays for definition of rules) - if (is_array($rules) && is_array($rules[0])) { - $found = array_filter($rules, function ($item) use ($require_type_of_rules) { - return in_array($item[0], $require_type_of_rules); - }); + $rule_names = array_map(function ($rule) { + return $this->extract_rule_name_from_definition($rule); + }, $rules); - return count($found) > 0; - } - - $found = array_values(array_intersect($require_type_of_rules, $rules)); + $found = array_values(array_intersect($require_type_of_rules, $rule_names)); return count($found) > 0; } @@ -1261,6 +1294,146 @@ protected function validate_required($field, array $input, array $params = [], $ return isset($value) && !self::is_empty($value); } + /** + * The field under validation must be present and not empty ONLY IF ANY of the other specified fields are present and not empty. + * + * @param string $field + * @param array $input + * @param array $params + * @param mixed $value + * @return bool + */ + protected function validate_required_with($field, array $input, array $params = [], $value = null) + { + $any_present = false; + + foreach ($params as $other_field) { + $other_val = ArrayHelpers::data_get($input, trim($other_field)); + if (!self::is_empty($other_val)) { + $any_present = true; + break; + } + } + + if ($any_present) { + return $this->validate_required($field, $input, [], $value); + } + + return true; + } + + /** + * The field under validation must be present and not empty ONLY IF ALL of the other specified fields are present and not empty. + * + * @param string $field + * @param array $input + * @param array $params + * @param mixed $value + * @return bool + */ + protected function validate_required_with_all($field, array $input, array $params = [], $value = null) + { + $all_present = true; + + foreach ($params as $other_field) { + $other_val = ArrayHelpers::data_get($input, trim($other_field)); + if (self::is_empty($other_val)) { + $all_present = false; + break; + } + } + + if ($all_present) { + return $this->validate_required($field, $input, [], $value); + } + + return true; + } + + /** + * + * The field under validation must be present and not empty ONLY WHEN ANY of the other specified fields are NOT present or empty. + * + * @param string $field + * @param array $input + * @param array $params + * @param mixed $value + * @return bool + */ + protected function validate_required_without($field, array $input, array $params = [], $value = null) + { + $any_missing = false; + + foreach ($params as $other_field) { + $other_val = ArrayHelpers::data_get($input, trim($other_field)); + if (self::is_empty($other_val)) { + $any_missing = true; + break; + } + } + + if ($any_missing) { + return $this->validate_required($field, $input, [], $value); + } + + return true; + } + + /** + * The field under validation must be present and not empty ONLY WHEN ALL of the other specified fields are NOT present or empty. + * + * @param string $field + * @param array $input + * @param array $params + * @param mixed $value + * @return bool + */ + protected function validate_required_without_all($field, array $input, array $params = [], $value = null) + { + $all_missing = true; + + foreach ($params as $other_field) { + $other_val = ArrayHelpers::data_get($input, trim($other_field)); + if (!self::is_empty($other_val)) { + $all_missing = false; + break; + } + } + + if ($all_missing) { + return $this->validate_required($field, $input, [], $value); + } + + return true; + } + + /** + * The field under validation must be an array and contain all specified keys. + * + * @param string $field + * @param array $input + * @param array $params + * @param mixed $value + * @return bool + */ + protected function validate_required_array_keys($field, array $input, array $params = [], $value = null) + { + $field_value = ArrayHelpers::data_get($input, $field); + + if (!is_array($field_value)) { + return false; + } + + foreach ($params as $required_key) { + $required_key = trim($required_key); + if (!ArrayHelpers::exists($field_value, $required_key)) { + return false; + } + } + + return true; + } + /** * Verify that a value is contained within the pre-defined value set. * diff --git a/lang/de.php b/lang/de.php index 72eb49f..819628f 100644 --- a/lang/de.php +++ b/lang/de.php @@ -2,6 +2,11 @@ return [ 'required' => 'Das Feld "{field}" ist erforderlich.', + 'required_with' => 'Das Feld "{field}" ist erforderlich, wenn {param} vorhanden ist', + 'required_with_all' => 'Das Feld "{field}" ist erforderlich, wenn alle {param} vorhanden sind', + 'required_without' => 'Das Feld "{field}" ist erforderlich, wenn {param} nicht vorhanden ist', + 'required_without_all' => 'Das Feld "{field}" ist erforderlich, wenn alle {param} nicht vorhanden sind', + 'required_array_keys' => 'Das Feld "{field}" ist erforderlich und muss die Schlüssel enthalten: {param}', 'valid_email' => 'Das Feld "{field}" muss eine gültige E-Mail-Adresse sein.', 'max_len' => 'Das Feld "{field}" darf maximal {param} Zeichen enthalten.', 'min_len' => 'Das Feld "{field}" muss mindestens {param} Zeichen enthalten.', diff --git a/lang/el.php b/lang/el.php index 0b494f4..5894a8d 100644 --- a/lang/el.php +++ b/lang/el.php @@ -2,6 +2,11 @@ return [ 'required' => 'Το πεδίο {field} είναι απαραίτητο', + 'required_with' => 'Το πεδίο {field} είναι απαραίτητο όταν {param} υπάρχει', + 'required_with_all' => 'Το πεδίο {field} είναι απαραίτητο όταν όλα τα {param} υπάρχουν', + 'required_without' => 'Το πεδίο {field} είναι απαραίτητο όταν {param} δεν υπάρχει', + 'required_without_all' => 'Το πεδίο {field} είναι απαραίτητο όταν όλα τα {param} δεν υπάρχουν', + 'required_array_keys' => 'Το πεδίο {field} είναι απαραίτητο και πρέπει να περιέχει τα κλειδιά: {param}', 'valid_email' => 'Το πεδίο {field} πρέπει να είναι μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου', 'max_len' => 'Το πεδίο {field} πρέπει να είναι {param} χαρακτήρες ή λιγότεροι', 'min_len' => 'Το πεδίο {field} πρέπει να είναι τουλάχιστον {param} χαρακτήρες', diff --git a/lang/en.php b/lang/en.php index 1c3e65a..d4039c5 100644 --- a/lang/en.php +++ b/lang/en.php @@ -2,6 +2,11 @@ return [ 'required' => 'The {field} field is required', + 'required_with' => 'The {field} field is required when {param} is present', + 'required_with_all' => 'The {field} field is required when all {param} are present', + 'required_without' => 'The {field} field is required when {param} is not present', + 'required_without_all' => 'The {field} field is required when all {param} are not present', + 'required_array_keys' => 'The {field} field is required and must contain keys: {param}', 'valid_email' => 'The {field} field must be a valid email address', 'max_len' => 'The {field} field needs to be {param} characters or less', 'min_len' => 'The {field} field needs to be at least {param} characters', diff --git a/lang/eo.php b/lang/eo.php index 20919fb..c0cc589 100644 --- a/lang/eo.php +++ b/lang/eo.php @@ -2,6 +2,11 @@ return [ 'required' => 'La kampo “{field}” estas deviga', + 'required_with' => 'La kampo "{field}" estas deviga kiam {param} ĉeestas', + 'required_with_all' => 'La kampo "{field}" estas deviga kiam ĉiuj {param} ĉeestas', + 'required_without' => 'La kampo "{field}" estas deviga kiam {param} ne ĉeestas', + 'required_without_all' => 'La kampo "{field}" estas deviga kiam ĉiuj {param} ne ĉeestas', + 'required_array_keys' => 'La kampo "{field}" estas deviga kaj devas enhavi ŝlosilojn: {param}', 'valid_email' => 'La kampo “{field}” devas enhavi validan retadreson', 'max_len' => 'La kampo “{field}” devas enhavi maksimume {param} signojn', 'min_len' => 'La kampo “{field}” devas enhavi minimume {param} signojn', diff --git a/lang/es.php b/lang/es.php index 125032e..05da78d 100644 --- a/lang/es.php +++ b/lang/es.php @@ -2,6 +2,11 @@ return [ 'required' => 'El campo {field} es requerido', + 'required_with' => 'El campo {field} es requerido cuando {param} está presente', + 'required_with_all' => 'El campo {field} es requerido cuando todos los {param} están presentes', + 'required_without' => 'El campo {field} es requerido cuando {param} no está presente', + 'required_without_all' => 'El campo {field} es requerido cuando todos los {param} no están presentes', + 'required_array_keys' => 'El campo {field} es requerido y debe contener las claves: {param}', 'valid_email' => 'El campo {field} debe ser una dirección de correo electrónico válida', 'max_len' => 'El campo {field} no puede tener más de {param} caracteres de longitud', 'min_len' => 'El campo {field} debe tener al menos {param} caracteres de longitud', diff --git a/lang/fa.php b/lang/fa.php index 1c7c318..21ffb60 100644 --- a/lang/fa.php +++ b/lang/fa.php @@ -2,6 +2,11 @@ return [ 'required' => '{field} الزامی میباشد', + 'required_with' => '{field} الزامی است وقتی {param} وجود دارد', + 'required_with_all' => '{field} الزامی است وقتی همه {param} وجود دارند', + 'required_without' => '{field} الزامی است وقتی {param} وجود ندارد', + 'required_without_all' => '{field} الزامی است وقتی همه {param} وجود ندارند', + 'required_array_keys' => '{field} الزامی است و باید شامل کلیدهای زیر باشد: {param}', 'valid_email' => '{field} باید یک آدرس ایمیل معتبر باشد ', 'max_len' => '{field} باید حد اکثر {param} کاراکتر یا کمتر باشد', 'min_len' => '{field} باید حد اقل {param} کاراکتر یا بیشتر باشد', diff --git a/lang/fr.php b/lang/fr.php index c406b59..f5d4c7f 100644 --- a/lang/fr.php +++ b/lang/fr.php @@ -2,6 +2,11 @@ return [ 'required' => 'Le champ {field} est obligatoire', + 'required_with' => 'Le champ {field} est obligatoire lorsque {param} est présent', + 'required_with_all' => 'Le champ {field} est obligatoire lorsque tous les {param} sont présents', + 'required_without' => 'Le champ {field} est obligatoire lorsque {param} n\'est pas présent', + 'required_without_all' => 'Le champ {field} est obligatoire lorsque tous les {param} ne sont pas présents', + 'required_array_keys' => 'Le champ {field} est obligatoire et doit contenir les clés: {param}', 'valid_email' => 'Le champ {field} doit être un email valide', 'max_len' => 'Le champ {field} doit avoir un nombre de caractère de {param} ou moins', 'min_len' => 'Le champ {field} doit avoir un nombre de caractère de {param} ou plus', diff --git a/lang/he.php b/lang/he.php index 29f74d5..e048e0f 100644 --- a/lang/he.php +++ b/lang/he.php @@ -2,6 +2,11 @@ return [ 'required' => 'שדה {field} הינו חובה', + 'required_with' => 'שדה {field} הינו חובה כאשר {param} קיים', + 'required_with_all' => 'שדה {field} הינו חובה כאשר כל ה-{param} קיימים', + 'required_without' => 'שדה {field} הינו חובה כאשר {param} לא קיים', + 'required_without_all' => 'שדה {field} הינו חובה כאשר כל ה-{param} לא קיימים', + 'required_array_keys' => 'שדה {field} הינו חובה וחייב להכיל את המפתחות: {param}', 'valid_email' => 'שדה {field} מוכרח להיות כתובת דוא"ל חוקית', 'max_len' => 'שדה {field} מוכרח להיות {param} תווים או פחות', 'min_len' => 'שדה {field} מוכרח להיות לפחות {param} תווים', diff --git a/lang/hu.php b/lang/hu.php index a25fd07..ac6756b 100644 --- a/lang/hu.php +++ b/lang/hu.php @@ -2,6 +2,11 @@ return [ 'required' => '{field} mező kötelező.', + 'required_with' => '{field} mező kötelező, ha {param} jelen van', + 'required_with_all' => '{field} mező kötelező, ha minden {param} jelen van', + 'required_without' => '{field} mező kötelező, ha {param} nincs jelen', + 'required_without_all' => '{field} mező kötelező, ha minden {param} nincs jelen', + 'required_array_keys' => '{field} mező kötelező és tartalmaznia kell a kulcsokat: {param}', 'valid_email' => '{field} mezőnek valós email címnek kell lennie.', 'max_len' => '{field} mező legfeljebb {param} karakter hosszú lehet.', 'min_len' => '{field} mezőnek legalább {param} karakter hosszúnak kell lennie.', diff --git a/lang/id.php b/lang/id.php index 7ae364d..532440d 100644 --- a/lang/id.php +++ b/lang/id.php @@ -2,6 +2,11 @@ return [ 'required' => 'Bagian {field} harus diisi', + 'required_with' => 'Bagian {field} wajib diisi ketika {param} ada', + 'required_with_all' => 'Bagian {field} wajib diisi ketika semua {param} ada', + 'required_without' => 'Bagian {field} wajib diisi ketika {param} tidak ada', + 'required_without_all' => 'Bagian {field} wajib diisi ketika semua {param} tidak ada', + 'required_array_keys' => 'Bagian {field} wajib diisi dan harus berisi kunci: {param}', 'valid_email' => 'Bagian {field} harus berisi alamat email yang benar', 'max_len' => 'Bagian {field} harus memiliki {param} karakter atau kurang', 'min_len' => 'Bagian {field} memiliki sedikitnya {param} karakter', diff --git a/lang/it.php b/lang/it.php index c5fcd35..6442b2d 100644 --- a/lang/it.php +++ b/lang/it.php @@ -2,6 +2,11 @@ return [ 'required' => 'Il campo {field} è obbligatorio', + 'required_with' => 'Il campo {field} è obbligatorio quando {param} è presente', + 'required_with_all' => 'Il campo {field} è obbligatorio quando tutti i {param} sono presenti', + 'required_without' => 'Il campo {field} è obbligatorio quando {param} non è presente', + 'required_without_all' => 'Il campo {field} è obbligatorio quando tutti i {param} non sono presenti', + 'required_array_keys' => 'Il campo {field} è obbligatorio e deve contenere le chiavi: {param}', 'valid_email' => 'Il campo {field} deve essere un indirizzo email valido', 'max_len' => 'Il campo {field} deve essere di {param} caratteri o inferiore', 'min_len' => 'Il campo {field} deve essere di almeno {param} caratteri', diff --git a/lang/ja.php b/lang/ja.php index 7fe95f1..fc2b1b1 100644 --- a/lang/ja.php +++ b/lang/ja.php @@ -2,6 +2,11 @@ return [ 'required' => '{field}フィールドは必須です', + 'required_with' => '{param}が存在する場合、{field}フィールドは必須です', + 'required_with_all' => 'すべての{param}が存在する場合、{field}フィールドは必須です', + 'required_without' => '{param}が存在しない場合、{field}フィールドは必須です', + 'required_without_all' => 'すべての{param}が存在しない場合、{field}フィールドは必須です', + 'required_array_keys' => '{field}フィールドは必須で、次のキーを含む必要があります:{param}', 'valid_email' => '{field}フィールドはメールアドレス形式でなければいけません', 'max_len' => '{field}フィールドは{param}文字以下でなければいけません', 'min_len' => '{field}フィールドは{param}文字以上でなければいけません', diff --git a/lang/nl.php b/lang/nl.php index 0548826..ebf5987 100644 --- a/lang/nl.php +++ b/lang/nl.php @@ -2,6 +2,11 @@ return [ 'required' => 'Het veld {field} is verplicht', + 'required_with' => 'Het veld {field} is verplicht wanneer {param} aanwezig is', + 'required_with_all' => 'Het veld {field} is verplicht wanneer alle {param} aanwezig zijn', + 'required_without' => 'Het veld {field} is verplicht wanneer {param} niet aanwezig is', + 'required_without_all' => 'Het veld {field} is verplicht wanneer alle {param} niet aanwezig zijn', + 'required_array_keys' => 'Het veld {field} is verplicht en moet de sleutels bevatten: {param}', 'valid_email' => 'Het veld {field} moet een geldige e-mail zijn', 'max_len' => 'Het veld {field} moet een aantal tekens van {param} of minder hebben', 'min_len' => 'Het veld {field} moet een tekennummer van {param} of meer hebben', diff --git a/lang/pt-br.php b/lang/pt-br.php index a47ca1a..3ac1178 100644 --- a/lang/pt-br.php +++ b/lang/pt-br.php @@ -2,6 +2,11 @@ return [ 'required' => 'O preenchimento do campo {field} é obrigatório', + 'required_with' => 'O campo {field} é obrigatório quando {param} está presente', + 'required_with_all' => 'O campo {field} é obrigatório quando todos os {param} estão presentes', + 'required_without' => 'O campo {field} é obrigatório quando {param} não está presente', + 'required_without_all' => 'O campo {field} é obrigatório quando todos os {param} não estão presentes', + 'required_array_keys' => 'O campo {field} é obrigatório e deve conter as chaves: {param}', 'valid_email' => 'O campo {field} precisa conter um e-mail válido', 'max_len' => 'O campo {field} pode conter no máximo {param} caracteres', 'min_len' => 'O campo {field} precisa conter no mínimo {param} caracteres', diff --git a/lang/ru.php b/lang/ru.php index 6d648d8..1e0ae59 100644 --- a/lang/ru.php +++ b/lang/ru.php @@ -2,6 +2,11 @@ return [ 'required' => 'Поле {field} является обязательным', + 'required_with' => 'Поле {field} обязательно, когда {param} присутствует', + 'required_with_all' => 'Поле {field} обязательно, когда все {param} присутствуют', + 'required_without' => 'Поле {field} обязательно, когда {param} отсутствует', + 'required_without_all' => 'Поле {field} обязательно, когда все {param} отсутствуют', + 'required_array_keys' => 'Поле {field} обязательно и должно содержать ключи: {param}', 'valid_email' => 'Поле {field} должно быть Email адресом', 'max_len' => 'Поле {field} должно быть максимум {param} символов', 'min_len' => 'Поле {field} должно быть минимум {param} символов', diff --git a/lang/tr.php b/lang/tr.php index f892281..b650350 100644 --- a/lang/tr.php +++ b/lang/tr.php @@ -2,6 +2,11 @@ return [ 'required' => '{field} alanı zorunludur', + 'required_with' => '{field} alanı {param} mevcut olduğunda zorunludur', + 'required_with_all' => '{field} alanı tüm {param} mevcut olduğunda zorunludur', + 'required_without' => '{field} alanı {param} mevcut olmadığında zorunludur', + 'required_without_all' => '{field} alanı tüm {param} mevcut olmadığında zorunludur', + 'required_array_keys' => '{field} alanı zorunludur ve şu anahtarları içermelidir: {param}', 'valid_email' => '{field} alanı geçerli bir e-posta adresi olmalı', 'max_len' => '{field} alanı en fazla {param} karakter veya daha az olmalı', 'min_len' => '{field} alanı en az {param} karakter olmalı', diff --git a/lang/uk.php b/lang/uk.php index 3d6205c..3d01fb9 100644 --- a/lang/uk.php +++ b/lang/uk.php @@ -2,6 +2,11 @@ return [ 'required' => 'Поле {field} є обов’язковим', + 'required_with' => 'Поле {field} є обов\'язковим, коли {param} присутнє', + 'required_with_all' => 'Поле {field} є обов\'язковим, коли всі {param} присутні', + 'required_without' => 'Поле {field} є обов\'язковим, коли {param} відсутнє', + 'required_without_all' => 'Поле {field} є обов\'язковим, коли всі {param} відсутні', + 'required_array_keys' => 'Поле {field} є обов\'язковим і має містити ключі: {param}', 'valid_email' => 'Поле {field} має бути Email адресою', 'max_len' => 'У полі {field} має бути максимум {param} символів', 'min_len' => 'У полі {field} має бути мінімум {param} символів', diff --git a/lang/vi.php b/lang/vi.php index df09d64..e9bfb55 100644 --- a/lang/vi.php +++ b/lang/vi.php @@ -2,6 +2,11 @@ return [ 'required' => '{field} là bắt buộc', + 'required_with' => 'Trường {field} là bắt buộc khi {param} xuất hiện', + 'required_with_all' => 'Trường {field} là bắt buộc khi tất cả {param} đều xuất hiện', + 'required_without' => 'Trường {field} là bắt buộc khi {param} rỗng', + 'required_without_all' => 'Trường {field} là bắt buộc khi tất cả {param} đều rỗng', + 'required_array_keys' => 'Trường {field} là bắt buộc và phải chứa các khóa: {param}', 'valid_email' => '{field} phải là địa chỉ email hợp lệ', 'max_len' => '{field} cần phải có {param} ký tự trở xuống', 'min_len' => '{field} cần có ít nhất {param} ký tự', diff --git a/lang/zh-CN.php b/lang/zh-CN.php index 69e3ca0..59e21e2 100644 --- a/lang/zh-CN.php +++ b/lang/zh-CN.php @@ -2,6 +2,11 @@ return [ 'required' => '字段 {field} 必填', + 'required_with' => '字段 {field} 在 {param} 存在时必填', + 'required_with_all' => '字段 {field} 在所有 {param} 都存在时必填', + 'required_without' => '字段 {field} 在 {param} 不存在时必填', + 'required_without_all' => '字段 {field} 在所有 {param} 都不存在时必填', + 'required_array_keys' => '字段 {field} 必填且必须包含以下键:{param}', 'valid_email' => '字段 {field} 必须是一个有效的邮箱地址', 'max_len' => '字段 {field} 不能大于 {param} 个字符', 'min_len' => '字段 {field} 不能小于 {param} 个字符', diff --git a/tests/StaticSetErrorMessagesTest.php b/tests/StaticSetErrorMessagesTest.php index 720d18d..75abe51 100644 --- a/tests/StaticSetErrorMessagesTest.php +++ b/tests/StaticSetErrorMessagesTest.php @@ -60,4 +60,93 @@ public function testItOverwritesLanguagefileErrorMessage() 'Field Test should be numeric !!!!!!!!!', ], $result); } + + public function testItOverwritesRequiredWithErrorMessage() + { + GUMP::set_error_messages([ + 'required_with' => 'Custom required_with message', + ]); + + $result = GUMP::is_valid([ + 'shipping_address' => '123 Main St', + ], [ + 'recipient_name' => 'required_with,shipping_address', + ]); + + $this->assertEquals([ + 'Custom required_with message', + ], $result); + } + + public function testItOverwritesRequiredWithAllErrorMessage() + { + GUMP::set_error_messages([ + 'required_with_all' => 'Custom required_with_all message', + ]); + + $result = GUMP::is_valid([ + 'shipping_address' => '123 Main St', + 'billing_address' => '456 Elm St', + 'order_note' => '', + ], [ + 'order_note' => 'required_with_all,shipping_address;billing_address', + ]); + + $this->assertEquals([ + 'Custom required_with_all message', + ], $result); + } + + public function testItOverwritesRequiredWithoutErrorMessage() + { + GUMP::set_error_messages([ + 'required_without' => 'Custom required_without message', + ]); + + $result = GUMP::is_valid([ + 'phone' => '', + 'mobile' => '', + ], [ + 'contact_email' => 'required_without,phone;mobile', + ]); + + $this->assertEquals([ + 'Custom required_without message', + ], $result); + } + + public function testItOverwritesRequiredWithoutAllErrorMessage() + { + GUMP::set_error_messages([ + 'required_without_all' => 'Custom required_without_all message', + ]); + + $result = GUMP::is_valid([ + 'phone' => '', + 'mobile' => '', + ], [ + 'contact_email' => 'required_without_all,phone;mobile', + ]); + + $this->assertEquals([ + 'Custom required_without_all message', + ], $result); + } + + public function testItOverwritesRequiredArrayKeysErrorMessage() + { + GUMP::set_error_messages([ + 'required_array_keys' => 'Custom required_array_keys message', + ]); + + $result = GUMP::is_valid([ + 'data' => ['id' => 10], + ], [ + 'data' => 'required_array_keys,id;name', + ]); + + $this->assertEquals([ + 'Custom required_array_keys message', + ], $result); + } } diff --git a/tests/Validators/RequiredArrayKeysValidatorTest.php b/tests/Validators/RequiredArrayKeysValidatorTest.php new file mode 100644 index 0000000..468c93d --- /dev/null +++ b/tests/Validators/RequiredArrayKeysValidatorTest.php @@ -0,0 +1,51 @@ +gump->validate( + [ + 'data' => ['id' => 10, 'name' => 'Order 42'], + ], + [ + 'data' => 'required_array_keys,id;name', + ] + ); + + $this->assertTrue($result); + } + + public function testErrorWhenFieldIsNotAnArray() + { + $result = $this->gump->validate( + [ + 'data' => 'not-an-array', + ], + [ + 'data' => 'required_array_keys,id;name', + ] + ); + + $this->assertNotTrue($result); + } + + public function testErrorWhenOneRequiredKeyIsMissing() + { + $result = $this->gump->validate( + [ + 'data' => ['id' => 10], + ], + [ + 'data' => 'required_array_keys,id;name', + ] + ); + + $this->assertNotTrue($result); + } +} + diff --git a/tests/Validators/RequiredWithAllValidatorTest.php b/tests/Validators/RequiredWithAllValidatorTest.php new file mode 100644 index 0000000..ff39a33 --- /dev/null +++ b/tests/Validators/RequiredWithAllValidatorTest.php @@ -0,0 +1,63 @@ +gump->validate( + [ + 'shipping_address' => '123 Main St', + 'billing_address' => '456 Elm St', + 'order_note' => 'Send ASAP', + ], + [ + 'order_note' => 'required_with_all,shipping_address;billing_address', + ] + ); + + $this->assertTrue($result); + } + + public function testSuccessWhenNotAllTriggersArePresent() + { + $result = $this->gump->validate( + [ + 'shipping_address' => '123 Main St', + 'billing_address' => '', + ], + [ + 'order_note' => 'required_with_all,shipping_address;billing_address', + ] + ); + + $this->assertTrue($result); + } + + public function testErrorWhenAllTriggersArePresentAndFieldIsEmpty() + { + $result = $this->gump->validate( + [ + 'shipping_address' => '123 Main St', + 'billing_address' => '456 Elm St', + 'order_note' => '', + ], + [ + 'order_note' => 'required_with_all,shipping_address;billing_address', + ] + ); + + $this->assertEquals([ + [ + 'field' => 'order_note', + 'value' => '', + 'rule' => 'required_with_all', + 'params' => ['shipping_address', 'billing_address'], + ] + ], $result); + } +} + diff --git a/tests/Validators/RequiredWithValidatorTest.php b/tests/Validators/RequiredWithValidatorTest.php new file mode 100644 index 0000000..5eed258 --- /dev/null +++ b/tests/Validators/RequiredWithValidatorTest.php @@ -0,0 +1,59 @@ +gump->validate( + [ + 'shipping_address' => '123 Main St', + 'recipient_name' => 'John Doe', + ], + [ + 'recipient_name' => 'required_with,shipping_address', + ] + ); + + $this->assertTrue($result); + } + + public function testSuccessWhenTriggerIsNotPresent() + { + $result = $this->gump->validate( + [ + 'shipping_address' => '', + ], + [ + 'recipient_name' => 'required_with,shipping_address', + ] + ); + + $this->assertTrue($result); + } + + public function testErrorWhenTriggerIsPresentAndFieldIsMissing() + { + $result = $this->gump->validate( + [ + 'shipping_address' => '123 Main St', + ], + [ + 'recipient_name' => 'required_with,shipping_address', + ] + ); + + $this->assertEquals([ + [ + 'field' => 'recipient_name', + 'value' => null, + 'rule' => 'required_with', + 'params' => ['shipping_address'], + ] + ], $result); + } +} + diff --git a/tests/Validators/RequiredWithoutValidatorTest.php b/tests/Validators/RequiredWithoutValidatorTest.php new file mode 100644 index 0000000..4b00cba --- /dev/null +++ b/tests/Validators/RequiredWithoutValidatorTest.php @@ -0,0 +1,68 @@ +gump->validate( + [ + 'phone' => '0912345678', + 'mobile' => '0998765432', + ], + [ + 'contact_email' => 'required_without,phone;mobile', + ] + ); + + $this->assertTrue($result); + } + + public function testErrorWhenAnyTrailingFieldIsEmptyAndFieldIsMissing() + { + $result = $this->gump->validate( + [ + 'phone' => '0912345678', + 'mobile' => '', + ], + [ + 'contact_email' => 'required_without,phone;mobile', + ] + ); + + $this->assertEquals([ + [ + 'field' => 'contact_email', + 'value' => null, + 'rule' => 'required_without', + 'params' => ['phone', 'mobile'], + ] + ], $result); + } + + public function testErrorWhenAllTrailingFieldsAreEmptyAndFieldIsMissing() + { + $result = $this->gump->validate( + [ + 'phone' => '', + 'mobile' => '', + ], + [ + 'contact_email' => 'required_without,phone;mobile', + ] + ); + + $this->assertEquals([ + [ + 'field' => 'contact_email', + 'value' => null, + 'rule' => 'required_without', + 'params' => ['phone', 'mobile'], + ] + ], $result); + } +} +