mirror of
https://codeberg.org/reflect/reflect-rules-plugin.git
synced 2025-09-13 16:33:42 +02:00
feat: coerce primitive boolean from strings for GET rules (#3)
* feat: coerce bool primitive from strings * fix(doc): GitHub md highliting
This commit is contained in:
parent
d14d4bca6a
commit
7fc27ff89c
3 changed files with 68 additions and 23 deletions
|
@ -114,7 +114,7 @@ Value|Coerced to
|
|||
|
||||
Any other value will cause the `type()` rule to fail.
|
||||
|
||||
> **Note**
|
||||
> [!IMPORTANT]
|
||||
> This coercion is only applies for `Ruleset->GET()`. `Ruleset->POST()` will enforce real `true` and `type` values since it's JSON
|
||||
|
||||
#### Null coercion from string for search parameters
|
||||
|
@ -122,7 +122,7 @@ Search parameters are read as strings, a null value is therefor coerced from an
|
|||
|
||||
Any value that isn't an empty string will cause the `type()` rule to fail.
|
||||
|
||||
> **Note**
|
||||
> [!IMPORTANT]
|
||||
> This coercion is only applies for `Ruleset->GET()`. `Ruleset->POST()` will enforce the real `null` value since it's JSON
|
||||
|
||||
## `min()`
|
||||
|
@ -151,4 +151,4 @@ Type|Expects
|
|||
`Type::STRING`|String length to be smaller or equal to provided value
|
||||
`Type::ARRAY`, `Type::OBJECT`|Array size or object key count to be smaller or equal to provided value
|
||||
|
||||
**`max()` will not have an effect on [`Type`](#types)s not provided in this list.**
|
||||
**`max()` will not have an effect on [`Type`](#types)s not provided in this list.**
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
use \victorwesterlund\xEnum;
|
||||
|
||||
use \ReflectRules\Scope;
|
||||
|
||||
// Supported types for is_type()
|
||||
enum Type {
|
||||
use xEnum;
|
||||
|
@ -80,17 +82,60 @@
|
|||
Methods are not called until all rules have been defined.
|
||||
*/
|
||||
|
||||
public function eval_required(array $scope): bool {
|
||||
return array_key_exists($this->property, $scope);
|
||||
private function eval_type_boolean(mixed $value, Scope $scope): bool {
|
||||
// Coerce $value to bool primitive from string for GET parameters
|
||||
if ($scope === Scope::GET) {
|
||||
switch ($value) {
|
||||
case "true":
|
||||
case "1":
|
||||
case "on":
|
||||
case "yes":
|
||||
$value = true;
|
||||
break;
|
||||
|
||||
case "false":
|
||||
case "0":
|
||||
case "off":
|
||||
case "no":
|
||||
$value = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
$value = null;
|
||||
}
|
||||
|
||||
// Mutate value on superglobal from string to primitive
|
||||
$GLOBALS[$scope->value][$this->property] = $value;
|
||||
}
|
||||
|
||||
return is_bool($value);
|
||||
}
|
||||
|
||||
public function eval_type(mixed $value): bool {
|
||||
/*
|
||||
## Public eval methods
|
||||
These are the entry-point eval methods that in turn can call other
|
||||
helper methods for fine-graned validation.
|
||||
*/
|
||||
|
||||
public function eval_required(Scope $scope): bool {
|
||||
$scope_data = &$GLOBALS[$scope->value];
|
||||
|
||||
if (array_key_exists($this->property, $scope_data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Property does not exist in scope, create nulled superglobal for it
|
||||
$scope_data[$this->property] = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function eval_type(mixed $value, Scope $scope): bool {
|
||||
return match($this->type) {
|
||||
Type::NUMBER => is_numeric($value),
|
||||
Type::STRING => is_string($value),
|
||||
Type::BOOLEAN => is_bool($value),
|
||||
Type::ARRAY => is_array($value),
|
||||
Type::OBJECT => $this->eval_object($value),
|
||||
Type::BOOLEAN => $this->eval_type_boolean($value, $scope),
|
||||
Type::ARRAY,
|
||||
Type::OBJECT => is_array($value),
|
||||
Type::NULL => is_null($value),
|
||||
default => true
|
||||
};
|
||||
|
@ -115,9 +160,4 @@
|
|||
default => true
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Recursive Rules eval of multidimensional object
|
||||
public function eval_object(mixed $object): bool {
|
||||
return is_array($object);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,12 @@
|
|||
|
||||
require_once "Rules.php";
|
||||
|
||||
// Available superglobal scopes
|
||||
enum Scope: string {
|
||||
case GET = "_GET";
|
||||
case POST = "_POST";
|
||||
}
|
||||
|
||||
class Ruleset {
|
||||
// This plugin will return exit with a Reflect\Response if errors are found
|
||||
private bool $exit_on_errors;
|
||||
|
@ -52,14 +58,12 @@
|
|||
}
|
||||
|
||||
// Evaluate Rules against a given value
|
||||
private function eval_rules(Rules $rules, array &$scope): void {
|
||||
private function eval_rules(Rules $rules, Scope $scope): void {
|
||||
// Get the name of the current property being evaluated
|
||||
$name = $rules->get_property_name();
|
||||
|
||||
// Check if property name exists in scope
|
||||
if (!$rules->eval_required($scope)) {
|
||||
// Set property name value on superglobal to null if not defined
|
||||
$scope[$name] = null;
|
||||
|
||||
// Don't perform further processing if the property is optional and not provided
|
||||
if (!$rules->required) {
|
||||
return;
|
||||
|
@ -68,14 +72,15 @@
|
|||
$this->add_error($name, "Value can not be empty");
|
||||
}
|
||||
|
||||
$value = $scope[$name];
|
||||
// Get value from scope for the current property
|
||||
$value = $GLOBALS[$scope->value][$name];
|
||||
|
||||
/*
|
||||
Eval each rule that has been set.
|
||||
The error messages will be returned
|
||||
*/
|
||||
|
||||
if ($rules->type && !$rules->eval_type($value)) {
|
||||
if ($rules->type && !$rules->eval_type($value, $scope)) {
|
||||
$this->add_error($name, "Value must be of type '{$rules->type->name}'");
|
||||
}
|
||||
|
||||
|
@ -89,7 +94,7 @@
|
|||
}
|
||||
|
||||
// Evaluate all Rules in this Ruleset against values in scope and return true if no errors were found
|
||||
private function eval_all_rules(array $rules, array &$scope): bool {
|
||||
private function eval_all_rules(array $rules, Scope $scope): bool {
|
||||
foreach ($rules as $rule) {
|
||||
$this->eval_rules($rule, $scope);
|
||||
}
|
||||
|
@ -103,7 +108,7 @@
|
|||
public function GET(array $rules): true|array|Response {
|
||||
$this->eval_property_name_diff($rules, array_keys($_GET));
|
||||
|
||||
$is_valid = $this->eval_all_rules($rules, $_GET);
|
||||
$is_valid = $this->eval_all_rules($rules, Scope::GET);
|
||||
|
||||
// Return errors as a Reflect\Response
|
||||
if (!$is_valid && $this->exit_on_errors) {
|
||||
|
@ -117,7 +122,7 @@
|
|||
public function POST(array $rules): true|array|Response {
|
||||
$this->eval_property_name_diff($rules, array_keys($_POST));
|
||||
|
||||
$is_valid = $this->eval_all_rules($rules, $_POST);
|
||||
$is_valid = $this->eval_all_rules($rules, Scope::POST);
|
||||
|
||||
// Return errors as a Reflect\Response
|
||||
if (!$is_valid && $this->exit_on_errors) {
|
||||
|
|
Loading…
Add table
Reference in a new issue