Files
duckbrain/src/Libs/Validator.php

213 lines
5.7 KiB
PHP

<?php
namespace Libs;
use Exception;
/**
* Validator - DuckBrain
*
* Complementary library to the Request library.
* Simplifies value verification.
*
* It has the ability to verify both individual rules and in batches.
*
* |----------+--------------------------------------------------------|
* | Rule | Description |
* |----------+--------------------------------------------------------|
* | not | Negates the next rule. Ex: not:float |
* | exists | Is required; must be defined and can be empty |
* | required | Is required; must be defined and not empty |
* | number | Is numeric |
* | int | Is an integer |
* | float | Is a float |
* | bool | Is a boolean |
* | email | Is an email |
* | enum | Is in a list of values. Ex: enum:admin,user,guest |
* | url | Is a valid URL |
* |----------+--------------------------------------------------------|
*
* Rule lists are separated by |, e.g., required|email
*
* @author KJ
* @website https://kj2.me
* @license MIT
*/
class Validator
{
/**
* Stores the last failed rule.
*
* @var string
*/
public static string $lastFailed = '';
/**
* Validates a list of rules against the properties of an object.
*
* @param array $rulesList The list of rules.
* @param Neuron $haystack The object whose properties will be validated.
*
* @return bool Returns true only if all rules are met, and false as soon as one fails.
*/
public static function validateList(array $rulesList, Neuron $haystack): bool
{
foreach ($rulesList as $target => $rules) {
$rules = preg_split('/\|/', $rules);
foreach ($rules as $rule) {
if (static::checkRule($haystack->{$target}, $rule)) {
continue;
}
static::$lastFailed = $target . '.' . $rule;
return false;
}
}
return true;
}
/**
* Checks if a rule is met.
*
* @param mixed $subject The value to verify.
* @param string $rule The rule to test.
*
* @return bool
* @throws Exception If the rule is not callable.
*/
public static function checkRule(mixed $subject, string $rule): bool
{
$arguments = preg_split('/[:,]/', $rule);
$rule = [static::class, $arguments[0]];
$arguments[0] = $subject;
if (is_callable($rule)) {
return call_user_func_array($rule, $arguments);
}
throw new Exception('Bad rule: "' . preg_split('/::/', $rule)[1] . '"');
}
/**
* Verifies the rule in a negative way.
*
* @param mixed $subject The value to verify.
* @param mixed $rule The rule to test.
*
* @return bool
*/
public static function not(mixed $subject, ...$rule): bool
{
return !static::checkRule($subject, join(':', $rule));
}
/**
* Checks if the value is defined/exists.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function exists(mixed $subject): bool
{
return isset($subject);
}
/**
* Checks if the value is defined and not empty.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function required(mixed $subject): bool
{
return isset($subject) && !empty($subject);
}
/**
* Checks if the value is numeric.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function number(mixed $subject): bool
{
return is_numeric($subject);
}
/**
* Checks if the value is an integer.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function int(mixed $subject): bool
{
return filter_var($subject, FILTER_VALIDATE_INT) !== false;
}
/**
* Checks if the value is a float.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function float(mixed $subject): bool
{
return filter_var($subject, FILTER_VALIDATE_FLOAT) !== false;
}
/**
* Checks if the value is a boolean.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function bool(mixed $subject): bool
{
return filter_var($subject, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null;
}
/**
* Checks if the value is a valid email address.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function email(mixed $subject): bool
{
return filter_var($subject, FILTER_VALIDATE_EMAIL) !== false;
}
/**
* Checks if the value is a valid URL.
*
* @param mixed $subject The value to check.
*
* @return bool
*/
public static function url(mixed $subject): bool
{
return filter_var($subject, FILTER_VALIDATE_URL) !== false;
}
/**
* Checks if the value is present in a list of allowed values.
*
* @param mixed $subject The value to check.
* @param mixed ...$values A variable number of allowed values.
*
* @return bool
*/
public static function enum(mixed $subject, ...$values): bool
{
return in_array($subject, $values);
}
}