/src/Nucleus/Library/Validator/Validator.php
https://bitbucket.org/jonbiard/nucleus · PHP · 249 lines · 105 code · 21 blank · 123 comment · 17 complexity · 38757934217c0b5413c9d147f1f6391f MD5 · raw file
- <?php
- /**
- * Class Validator
- *
- * @package Nucleus\Library
- * @subpackage Validator
- *
- * @author Jonathan Biard <info@jonathanbiard.com>
- */
- namespace Nucleus\Library\Validator;
- use Nucleus\Library\Validator\Rule\AbstractRule;
- use Nucleus\Library\Validator\Rule\BlankRule;
- /**
- * Class Validator
- *
- * Usage example:
- * <code>
- * // Preparation of error messages for each rule
- * $errEmailRequired = $locales['emailRequired'];
- * $errPasswordRequired = $locales['passwordRequired'];
- * $errRememberInvalid = $locales['rememberInvalid'];
- * $errTimezoneInvalid = $locales['timezoneInvalid'];
- *
- * // Associative array of inputs to filter
- * $inputs = [
- * 'email' => 'email@domain.com',
- * 'password' => 'abcd1234',
- * 'remember' => '1',
- * 'timezone' => 'America/New_York',
- * ];
- *
- * // Get the Nucleus Validator
- * $f = new \Nucleus\Library\Validator\InputValidator($inputs, false);
- *
- * // Get some rules ready-to-use
- * $stringRule = new \Nucleus\Library\Validator\Rule\StringRule();
- * $blankRule = new \Nucleus\Library\Validator\Rule\BlankRule();
- * $intRule = new \Nucleus\Library\Validator\Rule\IntRule();
- * $inValuesRule = new \Nucleus\Library\Validator\Rule\InValuesRule();
- * $timezoneRule = new \Nucleus\Library\Validator\Rule\TimezoneRule();
- *
- * // Add rules
- * $f->addRule('email', $stringRule, $errEmailRequired, $f::FIX);
- * $f->addRule('email', $blankRule, $errEmailRequired, $f::IS_NOT);
- *
- * $f->addRule('password', $stringRule, $errPasswordRequired, $f::FIX);
- * $f->addRule('password', $blankRule, $errPasswordRequired, $f::IS_NOT);
- *
- * $f->addRule('remember', $intRule, $errRememberInvalid, $f::FIX);
- * $f->addRule('remember', $inValuesRule, $errRememberInvalid, $f::IS, [0, 1]);
- *
- * $f->addRule('timezone', $stringRule, $errTimezoneInvalid, $f::FIX);
- * $f->addRule('timezone', $blankRule, $errTimezoneInvalid, $f::IS_NOT);
- * $f->addRule('timezone', $timezoneRule, $errTimezoneInvalid, $f::IS);
- *
- * // Validate the inputs with the rules that have been set
- * if (!$f->validate()) {
- * // Report the errors that occurred and exit
- * die(print_r($f->getErrors(), true));
- * }
- *
- * // Fetch the safe data
- * $safeInputs = $f->getValidated();
- *
- * // ... do your work safely
- * </code>
- *
- * @package Nucleus\Library
- * @subpackage Validator
- */
- class Validator
- {
- const IS = 0b1;
- const IS_NOT = 0b10;
- const FIX = 0b100;
- const IS_BLANK_OR = 0b1000;
- const FIX_BLANK_OR = 0b11000; // Contains the IS_BLANK_OR flag
- /**
- * Holds the original unsafe array of variables
- * @var array
- */
- private $data = [];
- /**
- * Holds the error messages for the rules that failed
- * @var string[]
- */
- private $failedErrors = [];
- /**
- * Whether to stop at the first error or not
- * @var bool
- */
- private $haltOnError = [];
- /**
- * Holds the ValidatorData to use for validation
- * @var array
- */
- private $validatorData = [];
- /**
- * Constructor
- *
- * @param array $data The array to validate
- * @param bool $haltOnError Whether to stop at the first error or not
- */
- public function __construct($data, $haltOnError = false)
- {
- $this->data = $data;
- $this->haltOnError = $haltOnError;
- }
- /**
- * Adds a rule for this input
- *
- * Required options:
- * is, isNot, fix
- *
- * Optional options:
- * isBlankOr, fixBlankOr
- *
- * Explanation:
- * - One required type is necessary for all rules
- * - To simply allow blanks but let them through as-is: isBlankOr
- * - To allow blanks but force them to null: fixBlankOr
- *
- * @param string $key The key to validate on the original array
- * @param AbstractRule $rule The ValidatorRule to use
- * @param string $errorMessage The error message if $rule returns false
- * @param int $options The options (constants) as flags
- */
- public function addRule($key, AbstractRule $rule, $errorMessage, $options)
- {
- if (!isset($this->validatorData[$key])) {
- $this->validatorData[$key] = [];
- }
- $validatorData = new ValidatorData();
- $validatorData->setRule($rule);
- $validatorData->setErrorMessage($errorMessage);
- $validatorData->setOptions($options);
- $validatorData->setArgs(array_slice(func_get_args(), 4));
- $this->validatorData[$key][] = $validatorData;
- }
- /**
- * Gets the error messages for the rules that failed
- *
- * @return string[] The error messages array for the rules that failed
- */
- public function getErrors()
- {
- return $this->failedErrors;
- }
- /**
- * Gets the validated array
- *
- * @return array The array validated as per the rules
- */
- public function getValidated()
- {
- return $this->data;
- }
- /**
- * Validates all rules attached to this instance
- *
- * @return bool Success status as true or false
- */
- public function validate()
- {
- $blankRule = new BlankRule();
- $is = $this::IS;
- $isNot = $this::IS_NOT;
- $fix = $this::FIX;
- $isBlankOr = $this::IS_BLANK_OR;
- $fixBlankOr = $this::FIX_BLANK_OR;
- /** @var ValidatorData[] $validatorData */
- foreach ($this->validatorData as $key => $validatorData) {
- foreach ($validatorData as $data) {
- $success = false;
- $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : null;
- $value = $this->data[$key];
- $rule = $data->getRule();
- $options = $data->getOptions();
- $errorMessage = $data->getErrorMessage();
- $args = $data->getArgs();
- if ($options & $isBlankOr) {
- if ($blankRule->validate($this->data[$key])) {
- $success = true;
- } else {
- if ($options & $is) {
- if ($rule->is($value, $args)) {
- $success = true;
- }
- } elseif ($options & $isNot) {
- if ($rule->isNot($value, $args)) {
- $success = true;
- }
- } elseif ($options & $fix) {
- $success = true;
- }
- }
- } else {
- if ($options & $is) {
- if ($rule->is($value, $args)) {
- $success = true;
- }
- } elseif ($options & $isNot) {
- if ($rule->isNot($value, $args)) {
- $success = true;
- }
- } elseif ($options & $fix) {
- $success = true;
- }
- }
- if ($success) {
- if ($options & $fixBlankOr && $blankRule->validate($this->data[$key])) {
- $this->data[$key] = null;
- } elseif ($options & $fix) {
- $this->data[$key] = $rule->fix($value, $args);
- }
- } else {
- $this->failedErrors[$key] = $errorMessage;
- if ($this->haltOnError) {
- break 2;
- } else {
- break;
- }
- }
- }
- }
- return empty($this->failedErrors) ? true : false;
- }
- }