Skip to content

Commit

Permalink
Implement type=number, type=range with max, min and step
Browse files Browse the repository at this point in the history
  • Loading branch information
g105b committed Dec 31, 2019
1 parent 38f6e38 commit e9f45c8
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/Rule/Pattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public function isValid(DOMElement $element, string $value):bool {
return preg_match($pattern, $value);
}

public function getErrorMessage(string $name):string {
public function getHint(DOMElement $element, string $value):string {
return "This field does not match the required pattern";
}
}
2 changes: 1 addition & 1 deletion src/Rule/Required.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function isValid(DOMElement $element, string $value):bool {
return !empty($value);
}

public function getErrorMessage(string $name):string {
public function getHint(DOMElement $element, string $value):string {
return "This field is required";
}
}
2 changes: 1 addition & 1 deletion src/Rule/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ public function getAttributes():array {

abstract public function isValid(DOMElement $element, string $value):bool;

abstract public function getErrorMessage(string $name):string;
abstract public function getHint(DOMElement $element, string $value):string;
}
64 changes: 62 additions & 2 deletions src/Rule/TypeNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,73 @@
class TypeNumber extends Rule {
protected $attributes = [
"type=number",
"type=range",
];

public function isValid(DOMElement $element, string $value):bool {
return empty($value) || is_numeric($value);
$min = $element->getAttribute("min") ?? null;
$max = $element->getAttribute("max") ?? null;
$step = $element->getAttribute("step") ?? null;

if(empty($value)) {
return true;
}

if(!is_numeric($value)) {
return false;
}

if($min !== ""
&& $value < $min) {
return false;
}

if($max !== ""
&& $value > $max) {
return false;
}

if($step !== "") {
if($min) {
return ($value - $min) % $step === 0;
}

return $value % $step === 0;
}

return true;
}

public function getErrorMessage(string $name):string {
public function getHint(DOMElement $element, string $value):string {
$min = $element->getAttribute("min") ?? null;
$max = $element->getAttribute("max") ?? null;
$step = $element->getAttribute("step") ?? null;

if(!is_numeric($value)) {
return "Field must be a number";
}

if($min !== ""
&& $value < $min) {
return "Field value must not be less than $min";
}

if($max !== ""
&& $value > $max) {
return "Field value must not be greater than $max";
}

if(!empty($step)) {
if($min
&& ($value - $min) % $step !== 0) {
return "Field value must be $min plus a multiple of $step";
}

if($value % $step !== 0) {
return "Field value must be a multiple of $step";
}
}

return "Field must be a number";
}
}
5 changes: 4 additions & 1 deletion src/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ public function validate(DOMElement $form, array $input):void {

foreach($ruleArray as $rule) {
if(!$rule->isValid($element, $input[$name] ?? "")) {
$this->errorList->add($element, $rule->getErrorMessage($name));
$this->errorList->add(
$element,
$rule->getHint($element, $input[$name] ?? "")
);
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions test/phpunit/Helper/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,26 @@ class Helper {
</form>
HTML;

const HTML_STEP_NUMBERS = <<<HTML
<!doctype html>
<form method="post">
<label>
<span>Basic step of 7</span>
<input name="step1" type="number" step="7" />
</label>
<label>
<span>Step of 7, starting from 2</span>
<input name="step2" type="number" step="7" min="2" />
</label>
<label>
<span>Step of 7.2 (max 3 and a bit steps up)</span>
<input name="step3" type="range" step="7.2" max="25.1" />
</label>
<label>
<span>Step of 7.2, starting from 3.5 (max 3 steps up)</span>
<input name="step4" type="range" step="7.2" min="3.5" max="25.1" />
</label>
</form>
HTML;

}
160 changes: 160 additions & 0 deletions test/phpunit/Rule/TypeNumberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,164 @@ public function testNumberFieldNotANumber() {
);
}
}

public function testStep() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

$exception = null;

try {
$validator->validate($form, [
"step1" => "14",
]);
}
catch(ValidationException $exception) {}

self::assertNull($exception);
}

public function testStepInvalid() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

try {
$validator->validate($form, [
"step1" => "15",
]);
}
catch(ValidationException $exception) {
$errorArray = iterator_to_array($validator->getLastErrorList());
self::assertCount(1, $errorArray);
$step1Error = $errorArray["step1"];
self::assertContains(
"Field value must be a multiple of 7",
$step1Error
);
}
}

public function testStepNegative() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

$exception = null;

try {
$validator->validate($form, [
"step1" => "-21",
]);
}
catch(ValidationException $exception) {}

self::assertNull($exception);
}

public function testStepStartingFrom2() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

$exception = null;

try {
$validator->validate($form, [
"step2" => "16",
]);
}
catch(ValidationException $exception) {}

self::assertNull($exception);
}

public function testStepStartingFrom2Invalid() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

try {
$validator->validate($form, [
"step2" => "21",
]);
}
catch(ValidationException $exception) {
$errorArray = iterator_to_array($validator->getLastErrorList());
self::assertCount(1, $errorArray);
$step1Error = $errorArray["step2"];
self::assertContains(
"Field value must be 2 plus a multiple of 7",
$step1Error
);
}
}

public function testStepWithMax() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

$exception = null;

try {
$validator->validate($form, [
"step3" => 7.2 * 3, // within range
]);
}
catch(ValidationException $exception) {}

self::assertNull($exception);
}

public function testStepWithMaxBust() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

try {
$validator->validate($form, [
"step3" => 7.2 * 4, // out of range
]);
}
catch(ValidationException $exception) {
$errorArray = iterator_to_array($validator->getLastErrorList());
self::assertCount(1, $errorArray);
$step1Error = $errorArray["step3"];
self::assertContains(
"Field value must not be greater than 25.1",
$step1Error
);
}
}

public function testStepWithDecimalStart() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

$exception = null;

try {
$validator->validate($form, [
"step4" => 3.5 + (7.2 * 2),
]);
}
catch(ValidationException $exception) {}

self::assertNull($exception);
}

public function testStepWithDecimalStartBust() {
$form = self::getFormFromHtml(Helper::HTML_STEP_NUMBERS);
$validator = new Validator();

try {
$validator->validate($form, [
"step4" => 3.5 + (7.2 * 4),
]);
}
catch(ValidationException $exception) {
$errorArray = iterator_to_array($validator->getLastErrorList());
self::assertCount(1, $errorArray);
$step1Error = $errorArray["step4"];
self::assertContains(
"Field value must not be greater than 25.1",
$step1Error
);
}
}
}

0 comments on commit e9f45c8

Please sign in to comment.