Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended validators to allow array values, dependent field validations and added new rules #22

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
35 changes: 16 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,22 @@ You may also utilize other place-holders in validation messages. For example the

##### Available rules

`between:min,max`:
```
Validates that a cell value is between a :min and :max. The rule exposes the :min and :max placeholder for inline messages
```
`ascii_only`:
```
Validates that a cell value does not contain a non-ascii character
```
`url`:
```
Validates that a cell value is a valid URL. By valid URL we mean

(#protocol)
(#basic auth)
(#a domain name or #an IP address or #an IPv6 address)
(#a port(optional)) then
(#a /, nothing, a / with something, a query or a fragment)

```
| Rule | Description |
| --- | --- |
| `alpha` | Validates that a cell value contains only lower and upper case alphabets |
| `alpha_num` | Validates that a cell value contains only numbers, lower and upper case alphabets |
| `ascii_only` | Validates that a cell value does not contain a non-ascii character |
| `between:min,max` | Validates that a cell value is between a :min and :max. The rule exposes the :min and :max placeholder for inline messages |
| `in:foo,bar,baz...` | Validates that a cell value is one of the values specified by the rule |
| `integer` | Validates that a cell has an integer value |
| `max:max_val` | Validates that a cell value must be less than or equal to max_val. |
| `max_length:length` | Validates that a cell value must contain less than or equal to length characters. |
| `min:min_val` | Validates that a cell value must be greater than or equal to min_val. |
| `min_length:length` | Validates that a cell value must contain greater than or equal to length characters. |
| `numeric` | Validates that a cell has a numeric value |
| `required` | Validates that a cell cannot be empty |
| `required_if:other_column,other_column_val` | Validates that a cell value must be present if a column specified by other_column has the value as other_column_val |
| `url` | Validates that a cell value is a valid URL. By valid URL we mean<br>(#protocol)<br>(#basic auth)<br>(#a domain name or #an IP address or #an IPv6 address)<br>(#a port(optional)) then<br>(#a /, nothing, a / with something, a query or a fragment) |

##### Writing CSV Output Data

Expand Down
22 changes: 22 additions & 0 deletions src/Contracts/ArrayParameterizedRuleInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Contracts;

interface ArrayParameterizedRuleInterface
{
/**
* Should return an array of the allowed parameters.
* The allowed parameters should be tokenized string
* e.g :min, :max, :first, :last etc.
*/
public function allowedParameters(): array;

/**
* Should return an array of parameter values as strings
* parsed in the same order and format as allowedParameters().
* This will aid in mapping our parameters to their placeholders.
*/
public function parseParameterValues(array $parameters): array;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is only useful when there a single parameter is allowed. Instead of doing this, I would rather update

protected function replaceParameterPlaceholder(

protected function replaceParameterPlaceholder(
    string $message,
    array $allowedParameters,
    array $parameters
): string {
    $hasMultipleAllowedParameter = count($allowedParameters) > 1;
    $search = $hasMultipleAllowedParameter ? $allowedParameters : $allowedParameters[0];
    $replace = $hasMultipleAllowedParameter ? $parameters : implode(',', $parameters);

    return str_replace($search, $replace, $message);
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this works as well. I just wanted to keep it open in case someone needed multiple parameters.

}
2 changes: 1 addition & 1 deletion src/Contracts/ParameterizedRuleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface ParameterizedRuleInterface
{
/**
* Should return an array of the allowed parameters.
* See the between rule. Tha allowed parameters should be
* See the between rule. The allowed parameters should be
* tokenized string e.g :min, :max, :first, :last etc.
*/
public function allowedParameters(): array;
Expand Down
2 changes: 1 addition & 1 deletion src/Contracts/ValidationRuleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface ValidationRuleInterface
*
* @param mixed $value
*/
public function passes($value, array $parameters): bool;
public function passes($value, array $parameters, array $row): bool;

/**
* Get the validation error message. Specify the message that should
Expand Down
9 changes: 9 additions & 0 deletions src/Helpers/FormatsMessages.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Oshomo\CsvUtils\Helpers;

use Oshomo\CsvUtils\Contracts\ArrayParameterizedRuleInterface;
use Oshomo\CsvUtils\Contracts\ParameterizedRuleInterface;
use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

Expand Down Expand Up @@ -88,6 +89,14 @@ protected function makeReplacements(
);
}

if ($rule instanceof ArrayParameterizedRuleInterface) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above

$message = $this->replaceParameterPlaceholder(
$message,
$rule->allowedParameters(),
$rule->parseParameterValues($parameters)
);
}

$message = $this->replaceValuePlaceholder($message, $value);

$message = $this->replaceErrorLinePlaceholder($message, $lineNumber);
Expand Down
35 changes: 35 additions & 0 deletions src/Rules/Alpha.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Rules;

use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

class Alpha implements ValidationRuleInterface
{
/**
* Determines if the validation rule passes. This is where we do the
* actual validation. If the validation passes return true else false.
*
* @param mixed $value
*/
public function passes($value, array $parameters, array $row): bool
{
if (null === $value || '' === $value) {
return true;
}

return ctype_alpha($value);
}

/**
* Get the validation error message. Specify the message that should
* be returned if the validation fails. You can make use of the
* :attribute and :value placeholders in the message string.
*/
public function message(): string
{
return 'The :attribute value :value may only contain letters on line :line.';
}
}
35 changes: 35 additions & 0 deletions src/Rules/AlphaNum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Rules;

use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

class AlphaNum implements ValidationRuleInterface
{
/**
* Determines if the validation rule passes. This is where we do the
* actual validation. If the validation passes return true else false.
*
* @param mixed $value
*/
public function passes($value, array $parameters, array $row): bool
{
if (null === $value || '' === $value) {
return true;
}

return ctype_alnum($value);
}

/**
* Get the validation error message. Specify the message that should
* be returned if the validation fails. You can make use of the
* :attribute and :value placeholders in the message string.
*/
public function message(): string
{
return 'The :attribute value :value may only contain letters and numbers on line :line.';
}
}
2 changes: 1 addition & 1 deletion src/Rules/AsciiOnly.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AsciiOnly implements ValidationRuleInterface
*
* @param mixed $value
*/
public function passes($value, array $parameters): bool
public function passes($value, array $parameters, array $row): bool
{
return (mb_detect_encoding($value, 'ASCII', true)) ? true : false;
}
Expand Down
8 changes: 3 additions & 5 deletions src/Rules/Between.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,18 @@ public function allowedParameters(): array
*
* @param mixed $value
*/
public function passes($value, array $parameters): bool
public function passes($value, array $parameters, array $row): bool
{
$size = (int) $value;

list($min, $max) = $parameters;

return $size >= (int) $min && $size <= (int) $max;
return +$value >= +$min && +$value <= +$max;
hoshomoh marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Get the validation error message.
*/
public function message(): string
{
return 'The :attribute value :value is not between :min - :max on line :line.';
return 'The :attribute value :value must be between :min and :max on line :line.';
}
}
4 changes: 2 additions & 2 deletions src/Rules/ClosureValidationRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public function __construct(\Closure $callback)
*
* @param mixed $value
*/
public function passes($value, array $parameters): bool
public function passes($value, array $parameters, array $row): bool
{
$this->failed = false;

$this->callback->__invoke($value, function ($message) {
$this->callback->__invoke($value, $row, function ($message) {
$this->failed = true;

$this->message = $message;
Expand Down
65 changes: 65 additions & 0 deletions src/Rules/In.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Rules;

use Oshomo\CsvUtils\Contracts\ArrayParameterizedRuleInterface;
use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

class In implements ValidationRuleInterface, ArrayParameterizedRuleInterface
{
/**
* Determines if the validation rule passes. This is where we do the
* actual validation. If the validation passes return true else false.
*
* @param mixed $value
*/
public function passes($value, array $parameters, array $row): bool
{
if (null === $value || '' === $value) {
return true;
}

return in_array($value, $parameters);
}

/**
* Get the validation error message. Specify the message that should
* be returned if the validation fails. You can make use of the
* :attribute and :value placeholders in the message string.
*/
public function message(): string
{
return 'The :attribute value :value does not exist in :allowed_values on line :line.';
}

/**
* Should return an array of the allowed parameters.
* The allowed parameters should be tokenized string
* e.g :min, :max, :first, :last etc.
*/
public function allowedParameters(): array
{
// all parameter values passed to the in rule will
// get mapped as allowed_values
// example in:1,2,3,4
// the values [1, 2, 3, 4] will get mapped to :allowed_values
// while checking for passes() and while writing message
// using parseParameterValues()
return [':allowed_values'];
}

/**
* Should return an array of parameter values as strings
* parsed in the same order and format as allowedParameters().
* This will aid in mapping our parameters to their placeholders.
*/
public function parseParameterValues(array $parameters): array
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above

{
// make sure to convert the values to an imploded string
// this will then get mapped to array index 0 which has
// the placeholder for :allowed_values
return [implode(',', $parameters)];
}
}
35 changes: 35 additions & 0 deletions src/Rules/Integer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Rules;

use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

class Integer implements ValidationRuleInterface
{
/**
* Determines if the validation rule passes. This is where we do the
* actual validation. If the validation passes return true else false.
*
* @param mixed $value
*/
public function passes($value, array $parameters, array $row): bool
{
if (null === $value || '' === $value) {
return true;
}

return ctype_digit((string) $value);
}

/**
* Get the validation error message. Specify the message that should
* be returned if the validation fails. You can make use of the
* :attribute and :value placeholders in the message string.
*/
public function message(): string
{
return 'The :attribute value :value must be an integer on line :line.';
}
}
36 changes: 36 additions & 0 deletions src/Rules/Max.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Oshomo\CsvUtils\Rules;

use Oshomo\CsvUtils\Contracts\ParameterizedRuleInterface;
use Oshomo\CsvUtils\Contracts\ValidationRuleInterface;

class Max implements ValidationRuleInterface, ParameterizedRuleInterface
{
public function allowedParameters(): array
{
return [':max'];
}

/**
* Determine if the validation rule passes.
*
* @param mixed $value
*/
public function passes($value, array $parameters, array $row): bool
{
list($max) = $parameters;

return +$value <= +$max;
hoshomoh marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Get the validation error message.
*/
public function message(): string
{
return 'The :attribute value :value may not be greater than :max on line :line.';
}
}
Loading