feat: add Type::ENUM (#8)

* feat: add multiple Types support

* feat: add Type::ENUM as type constraint

* feat(doc): add Type::ENUM to README

* fix(doc): Type::ENUM anchor link fix

* fix: bool true bug
This commit is contained in:
Victor Westerlund 2023-11-29 09:24:17 +01:00 committed by GitHub
parent 23530c57b0
commit 067896dafe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 5 deletions

View file

@ -102,8 +102,20 @@ Type|Description
`Type::BOOLEAN`|Value must be a boolean or ([**considered bool for GET rules**](#boolean-coercion-from-string-for-search-parameters))
`Type::ARRAY`|Value must be a JSON array
`Type::OBJECT`|Value must be a JSON object
`Type::ENUM`|Value must be exactly one of pre-defined values ([**more information**](#typeenum))
`Type::NULL`|Value must be null or ([**considered null for GET rules**](#null-coercion-from-string-for-search-parameters))
#### `Type::ENUM`
Provided value for property must be an exact match of any value provided as an `array` to the second argument of `type(Type::ENUM, <whitelist>)`
```php
Rules->type(Type::ENUM, [
"FOO",
"BAR"
]);
```
Any value that isn't `"FOO"` or `"BAR"` will be rejected.
#### Boolean coercion from string for search parameters
Search parameters are read as strings, a boolean is therefor coerced from the following rules.

View file

@ -10,12 +10,13 @@
enum Type {
use xEnum;
case NULL;
case ENUM;
case ARRAY;
case NUMBER;
case STRING;
case BOOLEAN;
case ARRAY;
case OBJECT;
case NULL;
case BOOLEAN;
}
class Rules {
@ -28,6 +29,8 @@
// Typed array of type ReflectRules\Type
public ?array $types = null;
public ?array $enum = null;
private bool $default_enabled = false;
public mixed $default;
@ -72,8 +75,16 @@
return $this;
}
// Set property Types
public function type(Type $type): self {
// Add Type constraint with optional argument
public function type(Type $type, mixed $arg = null): self {
if ($type === Type::ENUM) {
if (!is_array($arg)) {
throw new \Exception("Expected type 'array' of ENUM values as second argument");
}
$this->enum = $arg;
}
$this->types[] = $type;
return $this;
}
@ -121,6 +132,11 @@
return is_bool($value);
}
private function eval_type_enum(mixed $value): bool {
// Return true if value isn't boolean and exists in enum array
return !is_bool($value) && in_array($value, $this->enum);
}
/*
## Public eval methods
These are the entry-point eval methods that in turn can call other
@ -152,6 +168,7 @@
Type::BOOLEAN => $match = $this->eval_type_boolean($value, $scope),
Type::ARRAY,
Type::OBJECT => $match = is_array($value),
Type::ENUM => $match = $this->eval_type_enum($value),
Type::NULL => $match = is_null($value)
};

View file

@ -84,6 +84,12 @@
// List names of each allowed type
$types = implode(" or ", array_map(fn($type): string => $type->name, $rules->types));
// List allowed enum values
if ($rules->enum) {
$values = implode(" or ", array_map(fn($value): string => "'{$value}'", $rules->enum));
$this->add_error($name, "Value must be exactly: {$values}");
}
$this->add_error($name, "Value must be of type {$types}");
}