From 88d32a48fd8c26168b0e28ab7c8055d6e5a36cfb Mon Sep 17 00:00:00 2001 From: Oforomeh Oshomo Date: Sun, 18 Nov 2018 12:33:07 +0100 Subject: [PATCH] #5 (#10) * Added :line placeholder replacer, to replace the row/line number which the error occurred in the CSV. * Updated Validator to set row/line number and passed it to addFailure for setting the row/line number. * Updated all supported rules to display line number in their error message. * Updated test for checking if the line number is replaced properly. * Updated the README so, developers know they can pass :line number as a placeholder when overwriting the Rules error message. --- README.md | 8 ++++---- index.php | 2 +- src/Helpers/FormatsMessages.php | 20 ++++++++++++++++++-- src/Rules/AsciiOnly.php | 2 +- src/Rules/Between.php | 2 +- src/Rules/Url.php | 2 +- src/Validator/Validator.php | 17 +++++++++++++---- tests/src/CsvValidatorTest.php | 8 ++++---- tests/src/UppercaseRule.php | 2 +- 9 files changed, 44 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 634666a..df7536d 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ use Oshomo\CsvUtils\Validator\Validator; $validator = new Validator("some/valid/file_path", ",", [ 'title' => ["ascii_only", "url"] ], [ - 'ascii_only' => 'The :value supplied for :attribute attribute is invalid', + 'ascii_only' => 'The :value supplied for :attribute attribute is invalid on line :line of the CSV.', // This specifies a custom message for a given attribute. - 'hotel_link:url' => 'The :attribute must be a valid link', + 'hotel_link:url' => 'The :attribute must be a valid link. This error occured on line :line of the CSV.', ]); ``` -In this above example, the `:attribute` place-holder will be replaced by the actual name of the field under validation. The `:value` place-holder will also be replaced with value being validated. You may also utilize other place-holders in validation messages. For example the `between` rule exposes two other placeholder `min` and `max`. Find more about this in the available rules section +In this above example, the `:attribute` place-holder will be replaced by the actual name of the field under validation. The `:value` place-holder will be replaced with value being validated. The `:line` place-holder will also be replaced with the row/line number in the CSV in which the error happened. You may also utilize other place-holders in validation messages. For example the `between` rule exposes two other placeholder `min` and `max`. Find more about this in the available rules section ##### Available rules @@ -206,7 +206,7 @@ class UppercaseRule implements ValidationRuleInterface */ public function message() { - return "The :attribute value :value must be uppercase."; + return "The :attribute value :value must be uppercase on line :line."; } /** diff --git a/index.php b/index.php index b860224..dbdb260 100644 --- a/index.php +++ b/index.php @@ -9,7 +9,7 @@ $file_path = realpath(dirname(__FILE__)); $file = $file_path . '/sample/sample.csv'; $validator = new Validator($file, ',', [ - 'stars' => ['between:0,5'], + 'stars' => ['between:7,10'], 'name' => ['ascii_only'], 'uri' => ['url', function ($value, $fail) { if (0 !== strpos($value, 'https://')) { diff --git a/src/Helpers/FormatsMessages.php b/src/Helpers/FormatsMessages.php index 14d4cc7..737e6b7 100755 --- a/src/Helpers/FormatsMessages.php +++ b/src/Helpers/FormatsMessages.php @@ -65,7 +65,7 @@ protected function getFromLocalArray($attribute, $lowerRule) /** * @param $rule * - * @return null|string|string[] + * @return string|string[]|null */ protected function ruleToLower($rule) { @@ -86,15 +86,18 @@ protected function ruleToLower($rule) * @param mixed $value * @param ValidationRuleInterface $rule * @param array $parameters + * @param $lineNumber * * @return string */ - protected function makeReplacements($message, $attribute, $value, $rule, $parameters) + protected function makeReplacements($message, $attribute, $value, $rule, $parameters, $lineNumber) { $message = $this->replaceAttributePlaceholder($message, $attribute); $message = $this->replaceValuePlaceholder($message, $value); + $message = $this->replaceErrorLinePlaceholder($message, $lineNumber); + $message = $rule->parameterReplacer($message, $parameters); return $message; @@ -125,4 +128,17 @@ protected function replaceValuePlaceholder($message, $value) { return str_replace([':value'], [$value], $message); } + + /** + * Replace the :line placeholder in the given message. + * + * @param $message + * @param $lineNUmber + * + * @return mixed + */ + protected function replaceErrorLinePlaceholder($message, $lineNUmber) + { + return str_replace([':line'], [$lineNUmber], $message); + } } diff --git a/src/Rules/AsciiOnly.php b/src/Rules/AsciiOnly.php index 09fb245..045706f 100644 --- a/src/Rules/AsciiOnly.php +++ b/src/Rules/AsciiOnly.php @@ -36,7 +36,7 @@ public function passes($value, $parameters) */ public function message() { - return 'The :attribute value :value contains a non-ascii character'; + return 'The :attribute value :value contains a non-ascii character on line :line.'; } /** diff --git a/src/Rules/Between.php b/src/Rules/Between.php index 6e66fbf..6255cff 100644 --- a/src/Rules/Between.php +++ b/src/Rules/Between.php @@ -40,7 +40,7 @@ public function passes($value, $parameters) */ public function message() { - return 'The :attribute value :value is not between :min - :max.'; + return 'The :attribute value :value is not between :min - :max on line :line.'; } /** diff --git a/src/Rules/Url.php b/src/Rules/Url.php index c5c4835..3fdf0a1 100644 --- a/src/Rules/Url.php +++ b/src/Rules/Url.php @@ -57,7 +57,7 @@ public function passes($value, $parameters) */ public function message() { - return 'The :attribute value :value is not a valid url'; + return 'The :attribute value :value is not a valid url on line :line.'; } /** diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index 48df2ba..d4f413e 100755 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -39,6 +39,13 @@ class Validator */ protected $message; + /** + * The line number of the row under validation. + * + * @var int + */ + protected $currentRowLineNumber = 0; + /** * The row under validation. * @@ -79,7 +86,7 @@ class Validator * * @var string */ - protected $delimiter; + protected $delimiter = ','; /** * The rules to be applied to the data. @@ -110,7 +117,7 @@ class Validator * @param array $rules * @param array $messages */ - public function __construct($filePath, $delimiter = ',', array $rules, array $messages = []) + public function __construct($filePath, $delimiter, array $rules, array $messages = []) { $this->filePath = $filePath; $this->delimiter = $delimiter; @@ -175,6 +182,7 @@ protected function passes() if ($this->doesFileExistAndReadable($this->filePath)) { if (false !== ($handle = fopen($this->filePath, 'r'))) { while (false !== ($row = fgetcsv($handle, 0, $this->delimiter))) { + ++$this->currentRowLineNumber; if (empty($this->headers)) { $this->setHeaders($row); continue; @@ -269,7 +277,7 @@ protected function validateRow($row) * @param string $attribute * @param string $rule * - * @return null|void + * @return void|null */ protected function validateAttribute($attribute, $rule) { @@ -423,7 +431,8 @@ protected function addFailure($message, $attribute, $value, $rule, $parameters = $attribute, $value, $rule, - $parameters + $parameters, + $this->currentRowLineNumber ); } diff --git a/tests/src/CsvValidatorTest.php b/tests/src/CsvValidatorTest.php index aba4ad1..ca38136 100755 --- a/tests/src/CsvValidatorTest.php +++ b/tests/src/CsvValidatorTest.php @@ -57,7 +57,7 @@ public function testAsciiOnlyValidationRule() ); $this->assertContains( - 'The name value Well Health Hotels¡ contains a non-ascii character', + 'The name value Well Health Hotels¡ contains a non-ascii character on line 2.', $validator->errors()['data'][0]['errors'] ); } @@ -83,7 +83,7 @@ public function testBetweenValidationRule() ); $this->assertContains( - 'The stars value 3 is not between 4 - 10.', + 'The stars value 3 is not between 4 - 10 on line 2.', $validator->errors()['data'][0]['errors'] ); } @@ -109,7 +109,7 @@ public function testUrlValidationRule() ); $this->assertContains( - 'The uri value http//:well.org is not a valid url', + 'The uri value http//:well.org is not a valid url on line 2.', $validator->errors()['data'][0]['errors'] ); } @@ -135,7 +135,7 @@ public function testValidatorWithCustomRuleObject() ); $this->assertContains( - 'The name value Well Health Hotels¡ must be uppercase.', + 'The name value Well Health Hotels¡ must be uppercase on line 2.', $validator->errors()['data'][0]['errors'] ); } diff --git a/tests/src/UppercaseRule.php b/tests/src/UppercaseRule.php index adcd705..1ba1fd7 100644 --- a/tests/src/UppercaseRule.php +++ b/tests/src/UppercaseRule.php @@ -30,7 +30,7 @@ public function passes($value, $parameters) */ public function message() { - return 'The :attribute value :value must be uppercase.'; + return 'The :attribute value :value must be uppercase on line :line.'; } /**