From 436bb473edceb6eaed66a0e43f7d165417273aee Mon Sep 17 00:00:00 2001 From: Denis Smet Date: Thu, 14 Mar 2024 02:40:43 +0400 Subject: [PATCH] Implement min and max precision rules Added new rules for minimum and maximum precision in the schema files and created corresponding validation logic in the PHP files. Updated test files to include tests for these new rules. Enhanced the precision functionality in the schema files and reflected these changes in the README for clarity. --- README.md | 12 ++++-- schema-examples/full.json | 4 +- schema-examples/full.php | 4 +- schema-examples/full.yml | 4 +- src/Rules/MaxPrecision.php | 32 ++++++++++++++++ src/Rules/MinPrecision.php | 32 ++++++++++++++++ src/Rules/Precision.php | 6 +-- tests/Blueprint/RulesTest.php | 71 +++++++++++++++++++++++++++++++++++ 8 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 src/Rules/MaxPrecision.php create mode 100644 src/Rules/MinPrecision.php diff --git a/README.md b/README.md index f4d67e89..559c68da 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,9 @@ columns: # Decimal and integer numbers min: 10 # Can be integer or float, negative and positive max: 100.50 # Can be integer or float, negative and positive - precision: 2 # Strict(!) number of digits after the decimal point + precision: 3 # Strict(!) number of digits after the decimal point + min_precision: 2 # Min number of digits after the decimal point + max_precision: 4 # Max number of digits after the decimal point # Dates date_format: Y-m-d # See: https://www.php.net/manual/en/datetime.format.php @@ -384,7 +386,9 @@ columns: "only_capitalize" : true, "min" : 10, "max" : 100.5, - "precision" : 2, + "precision" : 3, + "min_precision" : 2, + "max_precision" : 4, "date_format" : "Y-m-d", "min_date" : "2000-01-02", "max_date" : "+1 day", @@ -449,7 +453,9 @@ return [ 'only_capitalize' => true, 'min' => 10, 'max' => 100.5, - 'precision' => 2, + 'precision' => 3, + 'min_precision' => 2, + 'max_precision' => 4, 'date_format' => 'Y-m-d', 'min_date' => '2000-01-02', 'max_date' => '+1 day', diff --git a/schema-examples/full.json b/schema-examples/full.json index 17131304..6897256e 100644 --- a/schema-examples/full.json +++ b/schema-examples/full.json @@ -25,7 +25,9 @@ "only_capitalize" : true, "min" : 10, "max" : 100.5, - "precision" : 2, + "precision" : 3, + "min_precision" : 2, + "max_precision" : 4, "date_format" : "Y-m-d", "min_date" : "2000-01-02", "max_date" : "+1 day", diff --git a/schema-examples/full.php b/schema-examples/full.php index 66c7542a..e80e81ad 100644 --- a/schema-examples/full.php +++ b/schema-examples/full.php @@ -43,7 +43,9 @@ 'only_capitalize' => true, 'min' => 10, 'max' => 100.5, - 'precision' => 2, + 'precision' => 3, + 'min_precision' => 2, + 'max_precision' => 4, 'date_format' => 'Y-m-d', 'min_date' => '2000-01-02', 'max_date' => '+1 day', diff --git a/schema-examples/full.yml b/schema-examples/full.yml index 98036c1c..73ef9fe1 100644 --- a/schema-examples/full.yml +++ b/schema-examples/full.yml @@ -51,7 +51,9 @@ columns: # Decimal and integer numbers min: 10 # Can be integer or float, negative and positive max: 100.50 # Can be integer or float, negative and positive - precision: 2 # Strict(!) number of digits after the decimal point + precision: 3 # Strict(!) number of digits after the decimal point + min_precision: 2 # Min number of digits after the decimal point + max_precision: 4 # Max number of digits after the decimal point # Dates date_format: Y-m-d # See: https://www.php.net/manual/en/datetime.format.php diff --git a/src/Rules/MaxPrecision.php b/src/Rules/MaxPrecision.php new file mode 100644 index 00000000..35e8a65c --- /dev/null +++ b/src/Rules/MaxPrecision.php @@ -0,0 +1,32 @@ + $this->getOptionAsInt()) { + return "Value \"{$cellValue}\" has a precision of {$valuePrecision} " . + "but should have a max precision of {$this->getOptionAsInt()}"; + } + + return null; + } +} diff --git a/src/Rules/MinPrecision.php b/src/Rules/MinPrecision.php new file mode 100644 index 00000000..8af2d12d --- /dev/null +++ b/src/Rules/MinPrecision.php @@ -0,0 +1,32 @@ +getOptionAsInt()) { + return "Value \"{$cellValue}\" has a precision of {$valuePrecision} " . + "but should have a min precision of {$this->getOptionAsInt()}"; + } + + return null; + } +} diff --git a/src/Rules/Precision.php b/src/Rules/Precision.php index df2c51af..25b6b816 100644 --- a/src/Rules/Precision.php +++ b/src/Rules/Precision.php @@ -16,13 +16,13 @@ namespace JBZoo\CsvBlueprint\Rules; -final class Precision extends AbstarctRule +class Precision extends AbstarctRule { public function validateRule(?string $cellValue): ?string { $valuePrecision = self::getFloatPrecision($cellValue); - if ($this->getOptionAsInt() !== $valuePrecision) { + if ($valuePrecision !== $this->getOptionAsInt()) { return "Value \"{$cellValue}\" has a precision of {$valuePrecision} " . "but should have a precision of {$this->getOptionAsInt()}"; } @@ -30,7 +30,7 @@ public function validateRule(?string $cellValue): ?string return null; } - private static function getFloatPrecision(?string $cellValue): int + protected static function getFloatPrecision(?string $cellValue): int { $floatAsString = (string)$cellValue; $dotPosition = \strpos($floatAsString, '.'); diff --git a/tests/Blueprint/RulesTest.php b/tests/Blueprint/RulesTest.php index cad32907..bd3a12da 100644 --- a/tests/Blueprint/RulesTest.php +++ b/tests/Blueprint/RulesTest.php @@ -33,9 +33,11 @@ use JBZoo\CsvBlueprint\Rules\Max; use JBZoo\CsvBlueprint\Rules\MaxDate; use JBZoo\CsvBlueprint\Rules\MaxLength; +use JBZoo\CsvBlueprint\Rules\MaxPrecision; use JBZoo\CsvBlueprint\Rules\Min; use JBZoo\CsvBlueprint\Rules\MinDate; use JBZoo\CsvBlueprint\Rules\MinLength; +use JBZoo\CsvBlueprint\Rules\MinPrecision; use JBZoo\CsvBlueprint\Rules\NotEmpty; use JBZoo\CsvBlueprint\Rules\OnlyCapitalize; use JBZoo\CsvBlueprint\Rules\OnlyLowercase; @@ -575,6 +577,75 @@ public function testPrecision(): void ); } + public function testMinPrecision(): void + { + $rule = new MinPrecision('prop', 0); + isSame(null, $rule->validate('0')); + isSame(null, $rule->validate('0.0')); + isSame(null, $rule->validate('0.1')); + isSame(null, $rule->validate('-1.0')); + isSame(null, $rule->validate('10.01')); + isSame(null, $rule->validate('-10.0001')); + + $rule = new MinPrecision('prop', 1); + isSame(null, $rule->validate('0.0')); + isSame(null, $rule->validate('10.0')); + isSame(null, $rule->validate('-10.0')); + + isSame( + '"min_precision" at line 0, column "prop". ' . + 'Value "2" has a precision of 0 but should have a min precision of 1.', + \strip_tags((string)$rule->validate('2')), + ); + + $rule = new MinPrecision('prop', 2); + isSame(null, $rule->validate('10.01')); + isSame(null, $rule->validate('-10.0001')); + + isSame( + '"min_precision" at line 0, column "prop". ' . + 'Value "2" has a precision of 0 but should have a min precision of 2.', + \strip_tags((string)$rule->validate('2')), + ); + + isSame( + '"min_precision" at line 0, column "prop". ' . + 'Value "2.0" has a precision of 1 but should have a min precision of 2.', + \strip_tags((string)$rule->validate('2.0')), + ); + } + + public function testMaxPrecision(): void + { + $rule = new MaxPrecision('prop', 0); + isSame(null, $rule->validate('0')); + isSame(null, $rule->validate('10')); + isSame(null, $rule->validate('-10')); + + isSame( + '"max_precision" at line 0, column "prop". ' . + 'Value "2.0" has a precision of 1 but should have a max precision of 0.', + \strip_tags((string)$rule->validate('2.0')), + ); + + $rule = new MaxPrecision('prop', 1); + isSame(null, $rule->validate('0.0')); + isSame(null, $rule->validate('10.0')); + isSame(null, $rule->validate('-10.0')); + + isSame( + '"max_precision" at line 0, column "prop". ' . + 'Value "-2.003" has a precision of 3 but should have a max precision of 1.', + \strip_tags((string)$rule->validate('-2.003')), + ); + + isSame( + '"max_precision" at line 0, column "prop". ' . + 'Value "2.00000" has a precision of 5 but should have a max precision of 1.', + \strip_tags((string)$rule->validate('2.00000')), + ); + } + public function testRegex(): void { $rule = new Regex('prop', '/^a/');