mirror of
https://codeberg.org/reflect/reflect-rules-plugin.git
synced 2025-09-14 08:53:42 +02:00
feat: add strict mode (#11)
* feat: add strict mode * feat(doc): add strict mode to README
This commit is contained in:
parent
81a2b2129c
commit
9c837fd194
2 changed files with 80 additions and 11 deletions
10
README.md
10
README.md
|
@ -106,10 +106,20 @@ Error
|
||||||
--|
|
--|
|
||||||
[`Error::VALUE_MIN_ERROR`](#min)
|
[`Error::VALUE_MIN_ERROR`](#min)
|
||||||
[`Error::VALUE_MAX_ERROR`](#max)
|
[`Error::VALUE_MAX_ERROR`](#max)
|
||||||
|
[`Error::UNKNOWN_PROPERTY_NAME`](#strict-mode)
|
||||||
[`Error::INVALID_PROPERTY_TYPE`](#type)
|
[`Error::INVALID_PROPERTY_TYPE`](#type)
|
||||||
[`Error::INVALID_PROPERTY_VALUE`](#typeenum)
|
[`Error::INVALID_PROPERTY_VALUE`](#typeenum)
|
||||||
[`Error::MISSING_REQUIRED_PROPERTY`](#required)
|
[`Error::MISSING_REQUIRED_PROPERTY`](#required)
|
||||||
|
|
||||||
|
# Strict mode
|
||||||
|
Enable strict mode by initializing a Ruleset with the "strict" argument set to `true`.
|
||||||
|
|
||||||
|
```php
|
||||||
|
new Ruleset(strict: true);
|
||||||
|
```
|
||||||
|
|
||||||
|
Strict mode will not allow undefined properties to be set in all configured scopes. If a property exists in `Scope` that hasn't been defined with a `Rules()` instance, a `Errors::UNKNOWN_PROPERTY_NAME` error will be set.
|
||||||
|
|
||||||
# Available rules
|
# Available rules
|
||||||
The following methods can be chained onto a `Rules` instance to enforce certain constraints on a particular property
|
The following methods can be chained onto a `Rules` instance to enforce certain constraints on a particular property
|
||||||
|
|
||||||
|
|
|
@ -10,29 +10,44 @@
|
||||||
enum Scope: string {
|
enum Scope: string {
|
||||||
case GET = "_GET";
|
case GET = "_GET";
|
||||||
case POST = "_POST";
|
case POST = "_POST";
|
||||||
|
|
||||||
|
static function get_array(): array {
|
||||||
|
return [
|
||||||
|
Scope::GET->name => [],
|
||||||
|
Scope::POST->name => []
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Error {
|
enum Error {
|
||||||
case VALUE_MIN_ERROR;
|
case VALUE_MIN_ERROR;
|
||||||
case VALUE_MAX_ERROR;
|
case VALUE_MAX_ERROR;
|
||||||
|
case UNKNOWN_PROPERTY_NAME;
|
||||||
case INVALID_PROPERTY_TYPE;
|
case INVALID_PROPERTY_TYPE;
|
||||||
case INVALID_PROPERTY_VALUE;
|
case INVALID_PROPERTY_VALUE;
|
||||||
case MISSING_REQUIRED_PROPERTY;
|
case MISSING_REQUIRED_PROPERTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ruleset {
|
class Ruleset {
|
||||||
// Array of arrays with failed constraints
|
private bool $is_valid = true;
|
||||||
private array $errors = [];
|
private ?bool $strict;
|
||||||
|
private array $errors;
|
||||||
|
|
||||||
public function __construct() {}
|
private array $rules_names;
|
||||||
|
|
||||||
|
public function __construct(bool $strict = false) {
|
||||||
|
/*
|
||||||
|
Strict mode can only be enabled or disabled as a bool argument.
|
||||||
|
'null' is used internally on this property as a re-evaluate flag.
|
||||||
|
*/
|
||||||
|
$this->strict = $strict;
|
||||||
|
|
||||||
|
$this->errors = Scope::get_array();
|
||||||
|
$this->rules_names = Scope::get_array();
|
||||||
|
}
|
||||||
|
|
||||||
// Append an error to the array of errors
|
// Append an error to the array of errors
|
||||||
private function add_error(Error $error, Scope $scope, string $property, mixed $expected): void {
|
private function add_error(Error $error, Scope $scope, string $property, mixed $expected): void {
|
||||||
// Create sub array if this is the first error in this scope
|
|
||||||
if (!array_key_exists($scope->name, $this->errors)) {
|
|
||||||
$this->errors[$scope->name] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create sub array if this is the first error for this property
|
// Create sub array if this is the first error for this property
|
||||||
if (!array_key_exists($property, $this->errors[$scope->name])) {
|
if (!array_key_exists($property, $this->errors[$scope->name])) {
|
||||||
$this->errors[$scope->name][$property] = [];
|
$this->errors[$scope->name][$property] = [];
|
||||||
|
@ -40,6 +55,21 @@
|
||||||
|
|
||||||
// Set expected value value for property in scope
|
// Set expected value value for property in scope
|
||||||
$this->errors[$scope->name][$property][$error->name] = $expected;
|
$this->errors[$scope->name][$property][$error->name] = $expected;
|
||||||
|
// Unset valid flag
|
||||||
|
$this->is_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate an array of Rules property names against scope keys
|
||||||
|
private function eval_strict(Scope $scope): void {
|
||||||
|
$name_diffs = array_diff(array_keys($GLOBALS[$scope->value]), $this->rules_names[$scope->name]);
|
||||||
|
|
||||||
|
// Set errors for each undefined property
|
||||||
|
foreach ($name_diffs as $name_diff) {
|
||||||
|
$this->add_error(Error::UNKNOWN_PROPERTY_NAME, $scope, $name_diff, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset strict mode property now that we have evaled it up to this point
|
||||||
|
$this->strict = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate Rules against a given value
|
// Evaluate Rules against a given value
|
||||||
|
@ -91,23 +121,52 @@
|
||||||
|
|
||||||
// Perform request processing on GET properties (search parameters)
|
// Perform request processing on GET properties (search parameters)
|
||||||
public function GET(array $rules): void {
|
public function GET(array $rules): void {
|
||||||
|
// (Re)enable strict mode if property is null
|
||||||
|
if ($this->strict === null) {
|
||||||
|
$this->strict = true;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
|
$this->rules_names[Scope::GET->name][] = $rule->get_property_name();
|
||||||
|
|
||||||
$this->eval_rules($rule, Scope::GET);
|
$this->eval_rules($rule, Scope::GET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform request processing on POST properties (request body)
|
// Perform request processing on POST properties (request body)
|
||||||
public function POST(array $rules): void {
|
public function POST(array $rules): void {
|
||||||
|
// (Re)enable strict mode if property is null
|
||||||
|
if ($this->strict === null) {
|
||||||
|
$this->strict = true;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
|
$this->rules_names[Scope::POST->name][] = $rule->get_property_name();
|
||||||
|
|
||||||
$this->eval_rules($rule, Scope::POST);
|
$this->eval_rules($rule, Scope::POST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function is_valid(): bool {
|
// ----
|
||||||
return empty($this->errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Return array of all set Errors
|
||||||
public function get_errors(): array {
|
public function get_errors(): array {
|
||||||
|
// Strict mode is enabled
|
||||||
|
if ($this->strict === true) {
|
||||||
|
$this->eval_strict(Scope::GET);
|
||||||
|
$this->eval_strict(Scope::POST);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->errors;
|
return $this->errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function is_valid(): bool {
|
||||||
|
// Strict mode is enabled
|
||||||
|
if ($this->strict === true) {
|
||||||
|
$this->eval_strict(Scope::GET);
|
||||||
|
$this->eval_strict(Scope::POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->is_valid;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue