. * */ 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\.(?[^\.]+)\.(?[^\.]+)/', $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; } }