<?php
namespace SHServ\Helpers;
/**
* Валидатор параметров action-скриптов по JSON-схеме.
*/
class ScriptParamsValidator {
public static function validate(?Array $schema, Array $params): Array {
if(!$schema) {
return ["ok" => true, "errors" => [], "params" => $params];
}
$errors = [];
$validated = [];
foreach($schema as $name => $config) {
$has_value = array_key_exists($name, $params);
if(($config["required"] ?? false) && !$has_value) {
$errors[] = ["field" => $name, "error" => "required"];
continue;
}
if(!$has_value) {
if(array_key_exists("default", $config)) {
$validated[$name] = $config["default"];
}
continue;
}
$value = $params[$name];
$type = $config["type"] ?? "text";
$type_error = self::validate_type($name, $type, $value, $config);
if($type_error) {
$errors[] = $type_error;
continue;
}
$validated[$name] = $value;
}
return [
"ok" => empty($errors),
"errors" => $errors,
"params" => $validated,
];
}
protected static function validate_type(String $name, String $type, $value, Array $config): ?Array {
switch($type) {
case "text":
case "textarea":
if(!is_string($value)) {
return ["field" => $name, "error" => "expected_string"];
}
return null;
case "number":
if(!self::is_numeric_value($value)) {
return ["field" => $name, "error" => "expected_number"];
}
$num = (float) $value;
if(isset($config["min"]) && $num < (float)$config["min"]) {
return ["field" => $name, "error" => "min", "min" => $config["min"]];
}
if(isset($config["max"]) && $num > (float)$config["max"]) {
return ["field" => $name, "error" => "max", "max" => $config["max"]];
}
return null;
case "range":
if(!self::is_numeric_value($value)) {
return ["field" => $name, "error" => "expected_number"];
}
$num = (float) $value;
if(isset($config["min"]) && $num < (float)$config["min"]) {
return ["field" => $name, "error" => "min", "min" => $config["min"]];
}
if(isset($config["max"]) && $num > (float)$config["max"]) {
return ["field" => $name, "error" => "max", "max" => $config["max"]];
}
return null;
case "select":
$options = array_keys($config["options"] ?? []);
if(!in_array($value, $options, true)) {
return ["field" => $name, "error" => "invalid_option"];
}
return null;
case "toggle":
if(!is_bool($value)) {
return ["field" => $name, "error" => "expected_bool"];
}
return null;
default:
return null;
}
}
protected static function is_numeric_value($value): Bool {
return is_int($value) || is_float($value) || (is_string($value) && is_numeric($value));
}
}