You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
7.5 KiB
234 lines
7.5 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Modified from phptutorial.net
|
|
* @link https://www.phptutorial.net/php-tutorial/php-validation/
|
|
*/
|
|
|
|
namespace CodeHydrater;
|
|
|
|
class validator {
|
|
|
|
const DEFAULT_VALIDATION_ERRORS = [
|
|
'required' => 'Please enter the %s',
|
|
'email' => 'The %s is not a valid email address',
|
|
'less_than' => 'The %s number must be less than %d',
|
|
'greater_than' => 'The %s number must be greater than %d',
|
|
'number_range' => 'The %s number must be in range of %d to %d',
|
|
'min' => 'The %s must have at least %s characters',
|
|
'max' => 'The %s must have at most %s characters',
|
|
'between' => 'The %s must have between %d and %d characters',
|
|
'same' => 'The %s must match with %s',
|
|
'alphanumeric' => 'The %s should have only letters and numbers',
|
|
'secure' => 'The %s must have between 8 and 64 characters and contain at least one number, one upper case letter, one lower case letter and one special character',
|
|
'valid_email_domain' => 'The %s email address is not active',
|
|
'valid_domain' => 'The %s domain name is not active',
|
|
];
|
|
|
|
private static function make_arrays(array $data, $field): array {
|
|
$dataset = [];
|
|
if (isset($data[$field])) {
|
|
if (common::get_count($data[$field])) {
|
|
foreach($data[$field] as $the_data) {
|
|
$dataset[] = $the_data;
|
|
}
|
|
} else {
|
|
$dataset[] = $data[$field];
|
|
}
|
|
} else {
|
|
$dataset[] = null; // If field is null, force null set
|
|
}
|
|
return $dataset;
|
|
}
|
|
|
|
public static function validate(
|
|
array $data,
|
|
array $fields,
|
|
array $messages = []
|
|
): array {
|
|
// Split the array by a separator, trim each element
|
|
// and return the array
|
|
$split = fn($str, $separator) => array_map('trim', explode($separator, $str));
|
|
|
|
// get the message rules
|
|
$rule_messages = array_filter($messages, fn($message) => is_string($message));
|
|
// overwrite the default message
|
|
$validation_errors = array_merge(self::DEFAULT_VALIDATION_ERRORS, $rule_messages);
|
|
|
|
$errors = [];
|
|
|
|
foreach ($fields as $field => $option) {
|
|
foreach(self::make_arrays($data, $field) as $index=>$v) {
|
|
$data[$field] = $v; // Force update on arrays
|
|
|
|
$rules = $split($option, '|');
|
|
|
|
foreach ($rules as $rule) {
|
|
// get rule name params
|
|
$params = [];
|
|
// if the rule has parameters e.g., min: 1
|
|
if (strpos($rule, ':')) {
|
|
[$rule_name, $param_str] = $split($rule, ':');
|
|
$params = $split($param_str, ',');
|
|
} else {
|
|
$rule_name = trim($rule);
|
|
}
|
|
// by convention, the callback should be is_<rule> e.g.,is_required
|
|
$fn = 'is_' . $rule_name;
|
|
|
|
$callable = self::class . "::{$fn}";
|
|
if (is_callable($callable)) {
|
|
$pass = $callable($data, $field, ...$params);
|
|
if (!$pass) {
|
|
// get the error message for a specific field and rule if exists
|
|
// otherwise get the error message from the $validation_errors
|
|
$errors[$field] = sprintf(
|
|
$messages[$field][$rule_name] ?? $validation_errors[$rule_name],
|
|
$field,
|
|
...$params
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
private static function is_required(array $data, string $field): bool {
|
|
if (isset($data[$field])) {
|
|
if (common::get_count($data[$field])) {
|
|
return false; // Should not be an array here
|
|
}
|
|
if (is_string($data[$field])) {
|
|
return (trim($data[$field]) !== '');
|
|
}
|
|
if (is_int($data[$field])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static function is_email(array $data, string $field): bool {
|
|
if (empty($data[$field])) {
|
|
return true;
|
|
}
|
|
return filter_var($data[$field], FILTER_VALIDATE_EMAIL);
|
|
}
|
|
|
|
private static function is_min(array $data, string $field, string $min): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
return mb_strlen($data[$field]) >= intval($min);
|
|
}
|
|
|
|
private static function is_max(array $data, string $field, string $max): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
return mb_strlen($data[$field]) <= intval($max);
|
|
}
|
|
|
|
private static function is_greater_than(array $data, string $field, string $min): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
return intval($data[$field]) > intval($min);
|
|
}
|
|
|
|
private static function is_less_than(array $data, string $field, string $max): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
return intval($data[$field]) < intval($max);
|
|
}
|
|
|
|
private static function is_number_range(array $data, string $field, string $min, string $max): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
$no = intval($data[$field]);
|
|
return $no >= intval($min) && $no <= intval($max);
|
|
}
|
|
|
|
private static function is_between(array $data, string $field, string $min, string $max): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
$len = mb_strlen($data[$field]);
|
|
return $len >= intval($min) && $len <= intval($max);
|
|
}
|
|
|
|
private static function is_same(array $data, string $field, string $other): bool {
|
|
if (isset($data[$field]) && isset($data[$other])) {
|
|
return $data[$field] === $data[$other];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static function is_alphanumeric(array $data, string $field): bool {
|
|
if (!isset($data[$field])) {
|
|
return true;
|
|
}
|
|
|
|
return ctype_alnum($data[$field]);
|
|
}
|
|
|
|
private static function is_secure(array $data, string $field): bool {
|
|
if (!isset($data[$field])) {
|
|
return false;
|
|
}
|
|
// Is 8 to 64 CHRs
|
|
$pattern = "#.*^(?=.{8,64})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\W).*$#";
|
|
return preg_match($pattern, $data[$field]);
|
|
}
|
|
|
|
private static function is_valid_email_domain(array $data, string $field): bool {
|
|
if (!isset($data[$field])) {
|
|
return false;
|
|
}
|
|
|
|
$domain = ltrim(stristr($data[$field], '@'), '@') . '.';
|
|
return checkdnsrr($domain, 'MX');
|
|
}
|
|
|
|
private static function is_valid_domain(array $data, string $field): bool {
|
|
if (!isset($data[$field])) {
|
|
return false;
|
|
}
|
|
|
|
return checkdnsrr($data[$field], 'A')
|
|
|| checkdnsrr($data[$field], 'AAAA')
|
|
|| checkdnsrr($data[$field], 'CNAME');
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
$data = ['email'=>'jim@aol.com'];
|
|
$fields = ['email' => 'required | email'];
|
|
|
|
$errors = \CodeHydrater\validator::validate($data, $fields);
|
|
print_r($errors);
|
|
*/
|
|
|
|
/*
|
|
* 'firstname' => 'required | max:255',
|
|
'lastname' => 'required | max: 255',
|
|
'address' => 'required | min: 10 | max:255',
|
|
'zipcode' => 'between: 5,6',
|
|
'username' => 'required | alphanumeric | between: 3,255',
|
|
'email' => 'required | email | valid_email_domain',
|
|
*/ |