Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down Expand Up @@ -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**
Expand Down
193 changes: 183 additions & 10 deletions gump.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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;
}
Expand Down Expand Up @@ -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.
*
Expand Down
5 changes: 5 additions & 0 deletions lang/de.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
Expand Down
5 changes: 5 additions & 0 deletions lang/el.php
Original file line number Diff line number Diff line change
Expand Up @@ -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} χαρακτήρες',
Expand Down
5 changes: 5 additions & 0 deletions lang/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions lang/eo.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions lang/es.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions lang/fa.php
Original file line number Diff line number Diff line change
Expand Up @@ -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} کاراکتر یا بیشتر باشد',
Expand Down
5 changes: 5 additions & 0 deletions lang/fr.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions lang/he.php
Original file line number Diff line number Diff line change
Expand Up @@ -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} תווים',
Expand Down
Loading