Skip to content

Commit

Permalink
Merge pull request #62 from programmatordev/1.x
Browse files Browse the repository at this point in the history
1.x
  • Loading branch information
andrepimpao authored Apr 2, 2024
2 parents 63cf347 + 3abee54 commit 26d37c1
Show file tree
Hide file tree
Showing 22 changed files with 570 additions and 64 deletions.
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@

PHP validator with expressive error messages.

> [!NOTE]
> This library is not in version 1.x mainly because there are few available rules.
> Hopefully, that will change in the near future.
> [!IMPORTANT]
> Expect some breaking changes until version `1.0`.
## Requirements

- PHP 8.1 or higher.
Expand Down
8 changes: 7 additions & 1 deletion docs/03-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Date Rules](#date-rules)
- [Choice Rules](#choice-rules)
- [Iterable Rules](#iterable-rules)
- [Other Rules](#other-rules)

## Basic Rules

Expand Down Expand Up @@ -41,5 +42,10 @@

## Iterable Rules

- [Collection](03-rules_collection.md)
- [EachValue](03-rules_each-value.md)
- [EachKey](03-rules_each-key.md)
- [EachKey](03-rules_each-key.md)

## Other Rules

- [Optional](03-rules_optional.md)
10 changes: 5 additions & 5 deletions docs/03-rules_choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ Choice(
## Basic Usage

```php
// Single choice
// single choice
Validator::choice(['red', 'green', 'blue'])->validate('green'); // true
Validator::choice(['red', 'green', 'blue'])->validate('yellow'); // false

// Multiple choices
// multiple choices
Validator::choice(['red', 'green', 'blue'], multiple: true)->validate(['red', 'blue']); // true;
Validator::choice(['red', 'green', 'blue'], multiple: true)->validate(['red', 'yellow']); // false;

// Multiple with minimum number of choices
// multiple with minimum number of choices
Validator::choice(['red', 'green', 'blue'], multiple: true, min: 2)->validate(['red', 'blue']); // true
Validator::choice(['red', 'green', 'blue'], multiple: true, min: 2)->validate(['red']); // false

// Multiple with maximum number of choices
// multiple with maximum number of choices
Validator::choice(['red', 'green', 'blue'], multiple: true, max: 2)->validate(['red', 'blue']); // true
Validator::choice(['red', 'green', 'blue'], multiple: true, max: 2)->validate(['red', 'green', 'blue']); // false

// Multiple with minimum and maximum number of choices
// multiple with minimum and maximum number of choices
Validator::choice(['red', 'green', 'blue'], multiple: true, min: 2, max: 3)->validate(['red', 'blue']); // true
Validator::choice(['red', 'green', 'blue'], multiple: true, min: 2, max: 3)->validate(['red']); // false
```
Expand Down
145 changes: 145 additions & 0 deletions docs/03-rules_collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Collection

Validates each key of an `array`, or object implementing `\Traversable`, with a set of validation constraints.

```php
/** @var array<mixed, Validator> $fields */
Collection(
array $fields,
bool $allowExtraFields = false,
?string $message = null,
?string $extraFieldsMessage = null,
?string $missingFieldsMessage = null
);
```

## Basic Usage

```php
Validator::collection(fields: [
'name' => Validator::notBlank(),
'age' => Validator::type('int')->greaterThanOrEqual(18)
])->validate([
'name' => 'Name',
'age' => 25
]); // true

Validator::collection(fields: [
'name' => Validator::notBlank(),
'age' => Validator::type('int')->greaterThanOrEqual(18)
])->validate([
'name' => '',
'age' => 25
]); // false ("name" is blank)

///////////////////////////////

// by default, extra fields are not allowed
Validator::collection(fields: [
'name' => Validator::notBlank(),
'age' => Validator::type('int')->greaterThanOrEqual(18)
])->validate([
'name' => 'Name',
'age' => 25,
'email' => 'mail@example.com'
]); // false ("email" field is not allowed)

// to allow extra fields, set option to true
Validator::collection(
fields: [
'name' => Validator::notBlank(),
'age' => Validator::type('int')->greaterThanOrEqual(18)
],
allowExtraFields: true
)->validate([
'name' => 'Name',
'age' => 25,
'email' => 'mail@example.com'
]); // true

///////////////////////////////

// by default, missing fields are not allowed
Validator::collection(fields: [
'name' => Validator::notBlank(),
'age' => Validator::type('int')->greaterThanOrEqual(18)
])->validate([
'age' => 25
]); // false ("name" is missing)

// but it is possible to use the Optional validation for optional fields
Validator::collection(fields: [
'name' => Validator::optional(
Validator::notBlank()
),
'age' => Validator::type('int')->greaterThanOrEqual(18)
])->validate([
'age' => 25
]); // true ("name" is optional)
```

> [!NOTE]
> An `UnexpectedValueException` will be thrown when a value in the `fields` associative array is not an instance of `Validator`.
> [!NOTE]
> An `UnexpectedValueException` will be thrown when the input value is not an `array` or an object implementing `\Traversable`.
## Options

### `fields`

type: `array<mixed, Validator>` `required`

Associative array with a set of validation constraints for each key.

### `allowExtraFields`

type: `bool` default: `false`

By default, it is not allowed to have fields (array keys) that are not defined in the `fields` option.
If set to `true`, it will be allowed (but not validated).

### `message`

type: `?string` default: `{{ message }}`

Message that will be shown when one of the fields is invalid.

The following parameters are available:

| Parameter | Description |
|-----------------|---------------------------------------|
| `{{ name }}` | Name of the invalid value |
| `{{ field }}` | Name of the invalid field (array key) |
| `{{ message }}` | The rule message of the invalid field |

### `extraFieldsMessage`

type: `?string` default: `The {{ field }} field is not allowed.`

Message that will be shown when the input value has a field that is not defined in the `fields` option
and `allowExtraFields` is set to `false`.

The following parameters are available:

| Parameter | Description |
|-----------------|---------------------------------------|
| `{{ name }}` | Name of the invalid value |
| `{{ field }}` | Name of the invalid field (array key) |

### `missingFieldsMessage`

type: `?string` default: `The {{ field }} field is missing.`

Message that will be shown when the input value *does not* have a field that is defined in the `fields` option.

The following parameters are available:

| Parameter | Description |
|-----------------|---------------------------------------|
| `{{ name }}` | Name of the invalid value |
| `{{ field }}` | Name of the invalid field (array key) |

## Changelog

- `1.0.0` Created
9 changes: 4 additions & 5 deletions docs/03-rules_country.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ Country(
## Basic Usage

```php
// Default alpha-2 code
Validator::country()->validate('PT'); // true
Validator::country(code: 'alpha-2')->validate('PT'); // true
// default alpha-2 code
Validator::country()->validate('pt'); // true

// Alpha-3 code
Validator::country(code: 'alpha-3')->validate('PRT'); // true
// alpha-3 code
Validator::country(code: 'alpha-3')->validate('prt'); // true
```

> [!NOTE]
Expand Down
4 changes: 2 additions & 2 deletions docs/03-rules_each-key.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ EachKey(

```php
Validator::eachKey(
Validator::notBlank()->type('string')
Validator::type('string')->notBlank()
)->validate(['red' => '#f00', 'green' => '#0f0']); // true

Validator::eachKey(
Validator::notBlank()->type('string')
Validator::type('string')->notBlank()
)->validate(['red' => '#f00', 1 => '#0f0']); // false
```

Expand Down
4 changes: 2 additions & 2 deletions docs/03-rules_each-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ EachValue(

```php
Validator::eachValue(
Validator::notBlank()->greaterThan(1)->lessThan(10)
Validator::type('int')->range(1, 10)
)->validate([4, 5, 6]); // true

Validator::eachValue(
Validator::notBlank()->greaterThan(1)->lessThan(10)
Validator::type('int')->range(1, 10)
)->validate([4, 5, 20]); // false
```

Expand Down
2 changes: 1 addition & 1 deletion docs/03-rules_email.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Email(
## Basic Usage

```php
// html5 mode (default)
// default html5 mode
Validator::email()->validate('test@example.com'); // true
Validator::email()->validate('test@example'); // false

Expand Down
37 changes: 37 additions & 0 deletions docs/03-rules_optional.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Optional

Validates only if value is *not* `null`.

```php
Optional(
Validator $validator,
);
```

## Basic Usage

```php
Validator::optional(
Validator::type('int')->greaterThanEqualTo(18)
)->validate(null); // true

Validator::optional(
Validator::type('int')->greaterThanEqualTo(18)
)->validate(20); // true

Validator::optional(
Validator::type('int')->greaterThanEqualTo(18)
)->validate(16); // false
```

## Options

### `validator`

type: `Validator` `required`

Validator that will validate the input value only when it is *not* `null`.

## Changelog

- `1.0.0` Created
8 changes: 4 additions & 4 deletions docs/03-rules_timezone.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ Timezone(
## Basic Usage

```php
// All timezone identifiers
// all timezone identifiers
Validator::timezone()->validate('Europe/Lisbon'); // true

// Restrict timezone identifiers to a specific geographical zone
// restrict timezone identifiers to a specific geographical zone
Validator::timezone(timezoneGroup: \DateTimeZone::EUROPE)->validate('Europe/Lisbon'); // true
Validator::timezone(timezoneGroup: \DateTimeZone::AFRICA)->validate('Europe/Lisbon'); // false
// Or multiple geographical zones
// or multiple geographical zones
Validator::timezone(timezoneGroup: \DateTimeZone::AFRICA | \DateTimeZone::EUROPE)->validate('Europe/Lisbon'); // true

// Restrict timezone identifiers to a specific country
// restrict timezone identifiers to a specific country
Validator::timezone(timezoneGroup: \DateTimeZone::PER_COUNTRY, countryCode: 'pt')->validate('Europe/Lisbon'); // true
Validator::timezone(timezoneGroup: \DateTimeZone::PER_COUNTRY, countryCode: 'en')->validate('Europe/Lisbon'); // false
```
Expand Down
8 changes: 4 additions & 4 deletions docs/03-rules_type.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ Type(
## Basic Usage

```php
// Single type
// single type
Validator::type('string')->validate('green'); // true
Validator::type('alphanumeric')->validate('gr33n'); // true

// Multiple types
// Validates if value is of at least one of the provided types
// multiple types
// validates if value is of at least one of the provided types
Validator::type(['alpha', 'numeric'])->validate('green'); // true (alpha)
Validator::type(['alpha', 'numeric'])->validate('33'); // true (numeric)
Validator::type(['alpha', 'numeric'])->validate('gr33n'); // false (not alpha nor numeric)

// Class or interface type
// class or interface type
Validator::type(\DateTime::class)->validate(new \DateTime()); // true
Validator::type(\DateTimeInterface::class)->validate(new \DateTime()); // true
```
Expand Down
6 changes: 3 additions & 3 deletions docs/03-rules_url.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ Url(
```php
Validator::url()->validate('https://example.com'); // true

// Only allow the https protocol
// only allow the https protocol
Validator::url(protocols: ['https'])->validate('http://example.com'); // false
// Or allow the ftp protocol too
// or allow the ftp protocol too
Validator::url(protocols: ['https', 'ftp'])->validate('ftp://example.com'); // true

// Allow relative protocol
// allow relative protocol
Validator::url()->validate('//example.com'); // false
Validator::url(allowRelativeProtocol: true)->validate('//example.com'); // true
Validator::url(allowRelativeProtocol: true)->validate('https://example.com'); // true
Expand Down
12 changes: 12 additions & 0 deletions src/ChainedValidatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ public function choice(
?string $maxMessage = null
): ChainedValidatorInterface&Validator;

public function collection(
array $fields,
bool $allowExtraFields = false,
?string $message = null,
?string $extraFieldsMessage = null,
?string $missingFieldsMessage = null
): ChainedValidatorInterface&Validator;

public function count(
?int $min = null,
?int $max = null,
Expand Down Expand Up @@ -89,6 +97,10 @@ public function notBlank(
?string $message = null
): ChainedValidatorInterface&Validator;

public function optional(
Validator $validator
): ChainedValidatorInterface&Validator;

public function passwordStrength(
string $minStrength = 'medium',
?string $message = null
Expand Down
5 changes: 5 additions & 0 deletions src/Exception/CollectionException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

namespace ProgrammatorDev\Validator\Exception;

class CollectionException extends ValidationException {}
Loading

0 comments on commit 26d37c1

Please sign in to comment.