306 lines
7.9 KiB
PHP
306 lines
7.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Vvveb
|
|
*
|
|
* Copyright (C) 2022 Ziadin Givan
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace Vvveb\System;
|
|
|
|
use function Vvveb\__;
|
|
use function Vvveb\arrayPath;
|
|
|
|
class Validator {
|
|
private $rules;
|
|
|
|
private $defaultMessages = [];
|
|
|
|
/*
|
|
[
|
|
'notEmpty' => '%s is empty',
|
|
'allowed_values' => '%s is invalid, valid options are %s',
|
|
'maxLength' => '%s is longer than %d'
|
|
];
|
|
*/
|
|
function __construct($rules) {
|
|
$this->defaultMessages = [
|
|
'notEmpty' => __('%s is empty'),
|
|
'allowedValues' => __('%s is invalid, valid options are %s'),
|
|
'maxLength' => __('%s is longer than %d'),
|
|
'minLength' => __('%s is shorter than %d'),
|
|
'match' => __('%s does not match %s'),
|
|
'captcha' => __('%s is invalid'),
|
|
'session' => __('%s is invalid'),
|
|
'email' => __('%s invalid email'),
|
|
'integer' => __('%s not numeric'),
|
|
'passwordComplexity' => __('%s not complex enough, include uppercase letters and digits'),
|
|
];
|
|
|
|
$this->rules($rules);
|
|
}
|
|
|
|
function rules($ruleFiles) {
|
|
$rules = [];
|
|
|
|
foreach ($ruleFiles as $rule) {
|
|
if (strpos($rule,'plugins.') !== false) {
|
|
//$plugin = 'plugins.()'
|
|
$options = \Vvveb\pregMatch('/plugins\.(?<plugin>[^\.]+)\.(?<rule>[^\.]+)/', $rule);
|
|
$file = DIR_PLUGINS . $options['plugin'] . '/' . APP . '/validate/' . $options['rule'] . '.php';
|
|
} else {
|
|
$file = DIR_APP . 'validate/' . $rule . '.php';
|
|
}
|
|
$rules = array_merge($rules, include($file));
|
|
}
|
|
|
|
$this->rules = $rules;
|
|
}
|
|
|
|
//remove rule
|
|
function removeRule($rule) {
|
|
unset($this->rules[$rule]);
|
|
}
|
|
|
|
//remove keys that are not in the validation list
|
|
function filter($input) {
|
|
$validKeys = array_keys($this->rules);
|
|
$filter = [];
|
|
|
|
foreach ($validKeys as $key) {
|
|
if (strpos($key, '.') != false) {
|
|
$keys = explode('.', $key);
|
|
$filter[$keys[0]][$keys[1]] = arrayPath($input, $key);
|
|
} else {
|
|
if (isset($input[$key])) {
|
|
$filter[$key] = $input[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return $filter;
|
|
/*
|
|
return array_filter($input, function ($key) use ($validKeys) {
|
|
return in_array($key, $validKeys);
|
|
}, ARRAY_FILTER_USE_KEY);*/
|
|
}
|
|
|
|
function validate($input) {
|
|
$errors = [];
|
|
$errorMessage = false;
|
|
|
|
foreach ($this->rules as $inputName => $rules) {
|
|
$name = __(\Vvveb\humanReadable($inputName));
|
|
$value = $input[$inputName] ?? arrayPath($input, $inputName);
|
|
|
|
if ($value !== null && $value !== false) {
|
|
foreach ($rules as $rule => $options) {
|
|
if (is_array($options)) {
|
|
$ruleName = key($options);
|
|
$ruleOptions = $rule[$ruleName] ?? [];
|
|
} else {
|
|
$ruleName = $rule;
|
|
$ruleOptions = $options;
|
|
}
|
|
|
|
$ruleMethod = 'rule' . $ruleName;
|
|
|
|
$message = '';
|
|
|
|
if (isset($this->defaultMessages[$ruleName])) {
|
|
$message = $this->defaultMessages[$ruleName];
|
|
}
|
|
|
|
if (isset($options['message'])) {
|
|
$message = $options['message'];
|
|
}
|
|
|
|
if (isset($options['name'])) {
|
|
$name = $options['name'];
|
|
}
|
|
|
|
if (method_exists($this, $ruleMethod)) {
|
|
$errorMessage = $this->$ruleMethod($value, $ruleOptions, $name, $message, $input);
|
|
}
|
|
|
|
if ($errorMessage) {
|
|
$errors[$inputName] = $errorMessage;
|
|
}
|
|
}
|
|
} else {
|
|
//if (isset($rules['notEmpty'])) {
|
|
//$rule = $rules['notEmpty'];
|
|
$message = $this->defaultMessages['notEmpty']; // $rule['message'] ?? __('%s is empty');
|
|
$name = $rule['name'] ?? $name;
|
|
//}
|
|
|
|
$errors[$inputName] = sprintf($message, $name);
|
|
}
|
|
}
|
|
|
|
return (empty($errors) ? true : $errors);
|
|
}
|
|
|
|
function getJSON() {
|
|
foreach ($this->rules as $inputName => &$rules) {
|
|
foreach ($rules as $rule => &$value) {
|
|
$ruleName = $rule;
|
|
|
|
if (! is_array($value)) {
|
|
if (empty($value)) {
|
|
$value = [];
|
|
} else {
|
|
$value = [$value];
|
|
}
|
|
}
|
|
|
|
if (! isset($value['message']) && isset($this->defaultMessages[$ruleName])) {
|
|
$rules[$ruleName]['message'] = $this->defaultMessages[$ruleName];
|
|
}
|
|
}
|
|
}
|
|
|
|
return json_encode($this->rules);
|
|
}
|
|
|
|
/* rules */
|
|
|
|
function ruleOptional($value, $options, $name, $message, $input) {
|
|
return false;
|
|
}
|
|
|
|
function ruleNotEmpty($value, $options, $name, $message, $input) {
|
|
if ($value === '' || $value === false || $value === null) {
|
|
return sprintf(__($message), $name);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleEmail($value, $options, $name, $message, $input) {
|
|
if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
|
return sprintf(__($message), $name);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function rule($value, $options, $name, $message, $input) {
|
|
if (! in_array($value, $options)) {
|
|
return sprintf(__($message), $name, implode(', ',$options));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleMaxLength($value, $options, $name, $message, $input) {
|
|
if (! is_string($value) || (strlen($value) > $options)) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleMinLength($value, $options, $name, $message, $input) {
|
|
if (! is_string($value) || (strlen($value) < $options)) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleAllowedValues($value, $options, $name, $message, $input) {
|
|
if (! is_string($value) || (strlen($value) > $options)) {
|
|
return sprintf(__($message), $name, implode(', ' ,$options));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleSession($value, $options, $name, $message, $input) {
|
|
if (\Vvveb\session($options) != $value) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleCaptcha($value, $options, $name, $message, $input) {
|
|
if ($input[$options] != $value) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleMatch($value, $options, $name, $message, $input) {
|
|
if ($input[$options] != $value) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ruleNumeric($value, $options, $name, $message, $input) {
|
|
if (! is_numeric($value)) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function rulePasswordComplexity($value, $options, $name, $message, $input) {
|
|
switch ($options) {
|
|
case 'low':
|
|
$regex =
|
|
'/^' . // Start anchor
|
|
'(?=.*[A-Z])' . // Ensure string has one uppercase letters.
|
|
'(?=.*[0-9])' . // Ensure string has one digits.
|
|
'(?=.*[a-z].*[a-z].*[a-z])' . // Ensure string has three lowercase letters.
|
|
'.*$/';
|
|
|
|
break;
|
|
|
|
case 'medium':
|
|
$regex =
|
|
'/^' . // Start anchor
|
|
'(?=.*[A-Z].*[A-Z])' . // Ensure string has two uppercase letters.
|
|
'(?=.*[!@#$&*%])' . // Ensure string has one special case letter.
|
|
'(?=.*[0-9].*[0-9])' . // Ensure string has two digits.
|
|
'(?=.*[a-z].*[a-z].*[a-z])' . // Ensure string has three lowercase letters.
|
|
'.*$/';
|
|
|
|
case 'high':
|
|
$regex =
|
|
'/^' . // Start anchor
|
|
'(?=.*[A-Z].*[A-Z])' . // Ensure string has two uppercase letters.
|
|
'(?=.*[!@#$&*%])' . // Ensure string has one special case letter.
|
|
'(?=.*[0-9].*[0-9])' . // Ensure string has two digits.
|
|
'(?=.*[a-z].*[a-z].*[a-z])' . // Ensure string has three lowercase letters.
|
|
'.*$/';
|
|
|
|
break;
|
|
}
|
|
|
|
if (($result = preg_match($regex, $value)) == false) {
|
|
return sprintf(__($message), $name, $options);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|