From c1ab9c418a78377e73f2202756b4382fc548d903 Mon Sep 17 00:00:00 2001 From: davitbek Date: Mon, 15 Jan 2018 08:46:22 +0400 Subject: [PATCH 1/2] add some default rules, existsIf, multiExists, multiExistsIf new custom rules --- src/Contracts/ArrayRuleInterface.php | 48 + src/Contracts/CoreValidatorInterface.php | 34 + src/Contracts/DBRuleInterface.php | 51 + src/Contracts/DateRuleInterface.php | 49 + src/Contracts/FileRuleInterface.php | 31 + src/Contracts/GeneralRuleInterface.php | 172 ++ .../LaraValidatorInterface.php | 34 +- src/Contracts/NumericRuleInterface.php | 41 + src/{Rules => Contracts}/RuleInterface.php | 14 +- src/Contracts/StringRuleInterface.php | 58 + src/CoreValidator.php | 1452 ++++++++++++----- src/CoreValidatorInterface.php | 94 -- src/LaraValidator.php | 216 +-- src/Rules/ExistsIfRule.php | 36 + src/Rules/MultiExistsIfRule.php | 40 + src/Rules/MultiExistsRule.php | 41 + src/Rules/UniqRule.php | 125 +- src/Rules/ValidationRules.php | 3 + src/Traits/DBParameterGetter.php | 39 + 19 files changed, 1881 insertions(+), 697 deletions(-) create mode 100644 src/Contracts/ArrayRuleInterface.php create mode 100644 src/Contracts/CoreValidatorInterface.php create mode 100644 src/Contracts/DBRuleInterface.php create mode 100644 src/Contracts/DateRuleInterface.php create mode 100644 src/Contracts/FileRuleInterface.php create mode 100644 src/Contracts/GeneralRuleInterface.php rename src/{ => Contracts}/LaraValidatorInterface.php (88%) create mode 100644 src/Contracts/NumericRuleInterface.php rename src/{Rules => Contracts}/RuleInterface.php (74%) create mode 100644 src/Contracts/StringRuleInterface.php delete mode 100644 src/CoreValidatorInterface.php create mode 100644 src/Rules/ExistsIfRule.php create mode 100644 src/Rules/MultiExistsIfRule.php create mode 100644 src/Rules/MultiExistsRule.php create mode 100644 src/Traits/DBParameterGetter.php diff --git a/src/Contracts/ArrayRuleInterface.php b/src/Contracts/ArrayRuleInterface.php new file mode 100644 index 0000000..e44ad2a --- /dev/null +++ b/src/Contracts/ArrayRuleInterface.php @@ -0,0 +1,48 @@ +rules(); - $messages = $this->messages(); - $v = self::make($input, $rules, $messages); - - if (!empty($this->_sometimes)) { - foreach ($this->_sometimes as $col => $data) { - reset($data); - $key = key($data); - $v->sometimes($col, $key, $data[$key]); - } - } - - return $v; - } - - /** - * returns the rules in Laravel format - * - * @return array - */ - public function rules() - { - $rules = []; - foreach ($this->_rules as $name => $ruleList) { - $rules[$name] = implode("|", $ruleList); - } - - return $rules; - } - - /** - * returns the rules in array format - * - * @return array - */ - protected function _rules() - { - return $this->_rules; - } - - /** - * return list of messages - * - * @return array - */ - public function messages() - { - return $this->_messages; - } - - - /** - * @param $name - * @param null $message - * @return $this - */ - public function requiredIfIsset($name, $message = null) - { - return $this->required($name, $message, 'isset'); - } - - - /** - * @param array|string $name - * @param string $message - * @param null $when - * @return $this - */ - public function required($name, $message = '', $when = null) - { - if (is_string($name)) { - $name = [ - $name - ]; - } - - // prevent duplicate validation rules - $name = array_unique($name); - - // when array is provided - // [ 'name', 'title', 'first_name' => 'First Name is Required', 'last_name', 'gender' => 'Gender is Required' ] - foreach ($name as $n => $m) { - // if $n is int, means no custom message is provided - so use the default one - // and the message is actually the name - if (is_int($n)) { - $n = $m; - $m = $message; - } - - $this->add($n, 'required', $m, $when); - } - - return $this; - } - - /** - * @param $name - * @param $length - * @param string $message - * @param null $when - * @return $this - */ - public function minLength($name, $length, $message = '', $when = null) - { - return $this->add($name, 'min:' . $length, $message); - } - - /** - * @param $name - * @param $length - * @param string $message - * @param null $when - * @return $this - * @throws \Exception - */ - public function maxLength($name, $length, $message = '', $when = null) - { - $length = $this->getTextLength($length); - return $this->add($name, 'max:' . $length, $message, $when); - } - - /** - * @param $name - * @param string $message - * @param $when - * @return $this - */ - public function email($name, $message = '', $when = null) - { - return $this->add($name, 'email', $message, $when); - } - - /** - * @param $name - * @param string $message - * @param null $when - * @return $this - */ - public function numeric($name, $message = '', $when = null) - { - return $this->add($name, 'numeric', $message, $when); - } - - public function confirmed($name, $message = '', $when = null) - { - return $this->add($name, 'confirmed', $message, $when); - } - - /** - * @param $name - * @param $params - * @param $message - * @param null $when - * @return $this - */ - public function unique($name, $params = [], $message = '', $when = null) - { - if (is_string($params)) { - $params = [ - $params - ]; - } - - return $this->add($name, 'uniq:'.implode(',', $params), $message, $when); - } - - - /** - * alias for bail - * - * @return CoreValidator - */ - public function last() - { - return $this->bail(); - } - - /** - * if the previous rule fails, does not validate other rules of this attr - * - * @return $this - */ - public function bail() - { - $attrs = array_keys($this->_rules()); - $name = end($attrs); - - $this->add($name, 'bail'); - return $this; - } - - /** - * @param $name - * @param $rule - * @param string $message - * @param null $when - * @return $this - */ - public function add($name, $rule, $message = '', $when = null) - { - if (!isset($this->_rules[$name])) { - $this->_rules[$name] = []; - } - - // for custom rules - if (is_array($rule)) { - $rule = $this->addCustomRule($name, $rule); - } - - $when = $this->checkWhen($name, $when); - - if (is_callable($when)) { - $this->_sometimes[$name][$rule] = $when; - } elseif (in_array($when, ['create', 'update'])) { - $this->_sometimes[$name][$rule] = function ($input) use ($when) { - if ($when == 'create') { - return empty($input['id']); - } - - return !empty($input['id']); - }; - } else { - $this->_rules[$name][] = $rule; - } - - $ruleName = $this->getRuleName($rule); - $messageRule = $name . '.' . $ruleName; - if (!empty($message)) { - $this->_messages[$messageRule] = $message; - } - - return $this; - } - - /** - * remove an existing rule - * - * @param $name - * @param $ruleName - if not provided all rules of the given field will be removed - * @return bool - */ - public function remove($name, $ruleName = null) - { - if (!isset($this->_rules[$name]) && !isset($this->_sometimes[$name])) { - return $this; - } - - // reset all rules for this field - if ($ruleName === null) { - unset($this->_rules[$name]); - unset($this->_sometimes[$name]); - return $this; - } - - // for rules - if (!empty($this->_rules[$name])) { - $rules = $this->_rules[$name]; - foreach ($rules as &$thisRule) { - if ($ruleName == $this->getRuleName($thisRule)) { - $thisRule = null; - } - } - unset($thisRule); - - $this->_rules[$name] = array_filter($rules); - $this->_rules = array_filter($this->_rules); - } - - if (!empty($this->_sometimes[$name])) { - // for conditional rules - $conditionalRules = $this->_sometimes[$name]; - - foreach ($conditionalRules as $k => &$condRule) { - if ($k == $ruleName) { - $condRule = null; - } - } - unset($condRule); - $this->_sometimes[$name] = array_filter($conditionalRules); - $this->_sometimes = array_filter($this->_sometimes); - } - - return $this; - } - - - /** - * TINYTEXT 256 bytes - * TEXT 65,535 bytes ~64kb - * MEDIUMTEXT 16,777,215 bytes ~16MB - * LONGTEXT 4,294,967,295 bytes ~4GB - * - * @param $length - * @return mixed - * @throws \Exception - */ - private function getTextLength($length) - { - if (is_numeric($length)) { - return $length; - } - - // @TODO - this is for MYSQL only - $types = [ - 'tinytext' => 256, - 'text' => 65535, - 'mediumtext' => 16777215, - 'longtext' => 4294967295 - ]; - if (isset($types[$length])) { - return $types[$length]; - } - - throw new \Exception('Invalid length attribute'); - } - - - /** - * @param $name - * @param array $data - * @return string - */ - private function addCustomRule($name, $data = []) - { - if (!empty($data['name'])) { - $validationName = $data['name']; - } else { - $validationName = md5($name.microtime(true)); - } - - if (!empty($data['implicit'])) { - self::extendImplicit($validationName, $data['rule']); - } else { - self::extend($validationName, $data['rule']); - } - - return $validationName; - } - - - /** - * Checks $when's string values - * - * @param $name - * @param null $when - * @return \Closure|null - */ - private function checkWhen($name, $when = null) - { - // if "isset" is provided - validate only if the given value is set - if ($when === 'isset') { - return function($input) use ($name) { - return array_key_exists($name, $input->toArray()); - }; - } - - // if "notempty" is provided - validate only if the given value is not empty - if ($when === 'notempty') { - return function($input) use ($name) { - $arr = $input->toArray(); - return !empty($arr[$name]); - }; - } - - return $when; - } - - -} +rules(); + $messages = $this->messages(); + $v = self::make($input, $rules, $messages); + + if (!empty($this->_sometimes)) { + foreach ($this->_sometimes as $col => $data) { + reset($data); + $key = key($data); + $v->sometimes($col, $key, $data[$key]); + } + } + + return $v; + } + + /** + * returns the rules in Laravel format + * + * @return array + */ + public function rules() + { + $rules = []; + foreach ($this->_rules as $name => $ruleList) { + $rules[$name] = implode("|", $ruleList); + } + + return $rules; + } + + /** + * returns the rules in array format + * + * @return array + */ + protected function _rules() + { + return $this->_rules; + } + + /** + * return list of messages + * + * @return array + */ + public function messages() + { + return $this->_messages; + } + + /******************** + * General rules * + *******************/ + + /** + * @param array|string $name + * @param string $message + * @param null $when + * @return $this + */ + public function required($name, $message = '', $when = null) + { + if (is_string($name)) { + $name = [ + $name + ]; + } + + // prevent duplicate validation rules + $name = array_unique($name); + + // when array is provided + // [ 'name', 'title', 'first_name' => 'First Name is Required', 'last_name', 'gender' => 'Gender is Required' ] + foreach ($name as $n => $m) { + // if $n is int, means no custom message is provided - so use the default one + // and the message is actually the name + if (is_int($n)) { + $n = $m; + $m = $message; + } + + $this->add($n, 'required', $m, $when); + } + + return $this; + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredIf($name, $data, $message = '', $when = null) + { + return $this->fixMultiRuleStructure($name, 'required_if', $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredUnless($name, $data, $message = '', $when = null) + { + return $this->fixMultiRuleStructure($name, 'required_unless', $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredWith($name, $data, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'required_with', $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredWithAll($name, $data, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'required_with_all', $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredWithout($name, $data, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'required_without', $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function requiredWithoutAll($name, $data, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'required_without_all', $data, $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function present($name, $message = '', $when = null) + { + return $this->add($name, 'present', $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function filled($name, $message = '', $when = null) + { + return $this->add($name, 'filled', $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function accepted($name, $message = '', $when = null) + { + return $this->add($name, 'accepted', $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function nullable($name, $message = '', $when = null) + { + return $this->add($name, 'nullable', $message, $when); + } + + /** + * @param $name + * @param $size + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function size($name, $size, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'size', $size, $message, $when); + } + + /** + * @param $name + * @param $length + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function minLength($name, $length, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'min', $length, $message, $when); + } + + /** + * @param $name + * @param $length + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function maxLength($name, $length, $message = '', $when = null) + { + $length = $this->getTextLength($length); + return $this->fixRuleStructure($name, 'max', $length, $message, $when); + } + + /** + * @param $name + * @param $min + * @param $max + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function between($name, $min, $max, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'between', [$min, $max], $message, $when); + } + + /** + * @param $name + * @param $value + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function different($name, $value, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'different', $value, $message, $when); + } + + /** + * alias for bail + * + * @return CoreValidator + */ + public function last() + { + return $this->bail(); + } + + /** + * if the previous rule fails, does not validate other rules of this attr + * + * @return $this + */ + public function bail() + { + return $this->add($this->_lastField, 'bail'); + } + + /** + * @param $name + * @param $rule + * @param string $message + * @param null $when + * @return $this + */ + public function add($name, $rule, $message = '', $when = null) + { + if (!isset($this->_rules[$name])) { + $this->_rules[$name] = []; + } + + // for custom rules + if (is_array($rule)) { + $rule = $this->addCustomRule($name, $rule); + } + + $when = $this->checkWhen($name, $when); + + if (is_callable($when)) { + $this->_sometimes[$name][$rule] = $when; + } elseif (in_array($when, ['create', 'update'])) { + $this->_sometimes[$name][$rule] = function ($input) use ($when) { + if ($when == 'create') { + return empty($input['id']); + } + + return !empty($input['id']); + }; + } else { + $this->_rules[$name][] = $rule; + } + + $ruleName = $this->getRuleName($rule); + $messageRule = $name . '.' . $ruleName; + if (!empty($message)) { + $this->_messages[$messageRule] = $message; + } + + $this->_lastField = $name; + return $this; + } + + /** + * remove an existing rule + * + * @param $name + * @param $ruleName - if not provided all rules of the given field will be removed + * @return $this + */ + public function remove($name, $ruleName = null) + { + if (!isset($this->_rules[$name]) && !isset($this->_sometimes[$name])) { + return $this; + } + + // reset all rules for this field + if ($ruleName === null) { + unset($this->_rules[$name]); + unset($this->_sometimes[$name]); + return $this; + } + + // for rules + if (!empty($this->_rules[$name])) { + $rules = $this->_rules[$name]; + foreach ($rules as &$thisRule) { + if ($ruleName == $this->getRuleName($thisRule)) { + $thisRule = null; + } + } + unset($thisRule); + + $this->_rules[$name] = array_filter($rules); + $this->_rules = array_filter($this->_rules); + } + + if (!empty($this->_sometimes[$name])) { + // for conditional rules + $conditionalRules = $this->_sometimes[$name]; + + foreach ($conditionalRules as $k => &$condRule) { + if ($k == $ruleName) { + $condRule = null; + } + } + unset($condRule); + $this->_sometimes[$name] = array_filter($conditionalRules); + $this->_sometimes = array_filter($this->_sometimes); + } + + return $this; + } + + + /******************** + * Numeric rules * + *******************/ + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function numeric($name, $message = '', $when = null) + { + return $this->add($name, 'numeric', $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function integer($name, $message = '', $when = null) + { + return $this->add($name, 'integer', $message, $when); + } + + /** + * @param $name + * @param $value + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function digits($name, $value, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'digits', $value, $message, $when); + } + + /** + * @param $name + * @param $min + * @param $max + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function digitsBetween($name, $min, $max, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'digits_between', [$min, $max], $message, $when); + } + + + /******************** + * String rules * + *******************/ + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function email($name, $message = '', $when = null) + { + return $this->add($name, 'email', $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function startsWith($name, $data, $message = '', $when = null) + { + return $this->addStringMethodRule($name, 'starts_with', $data, $message = '', $when = null); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function endsWith($name, $data, $message = '', $when = null) + { + return $this->addStringMethodRule($name, 'ends_with', $data, $message = '', $when = null); + } + + /** + * @param $name + * @param $pattern + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function is($name, $pattern, $message = '', $when = null) + { + if (empty($message)) { + $message = sprintf('The %s must be is pattern of %s ' , $name, $pattern); + } + + return $this->add($name, [ + 'rule' => function ($attribute, $value, $parameters, $validator) use ($pattern) { + if (empty($value)) { + return true; + } + + return str_is($pattern, $value); + }], $message, $when); + } + + /** + * @param $name + * @param $regex + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function regex($name, $regex, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'regex' , $regex, $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function confirmed($name, $message = '', $when = null) + { + return $this->add($name, 'confirmed', $message, $when); + } + + /******************** + * Array rules * + *******************/ + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function isArray($name, $message = '', $when = null) + { + return $this->add($name, 'array', $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function in($name, $data, $message = '', $when = null) + { + if (is_array($data)) { + $data = implode(',', $data); + } + return $this->add($name, 'in:' . $data, $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function notIn($name, $data, $message = '', $when = null) + { + if (is_array($data)) { + $data = implode(',', $data); + } + return $this->add($name, 'note_in:' . $data, $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function isCheckbox($name, $message = '', $when = null) + { + return $this->in($name, [0, 1], $message, $when); + } + + /** + * @param $name + * @param $class + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function inClassConstant($name, $class, $message = '', $when = null) + { + $refl = new \ReflectionClass($class); + $data = $refl->getConstants(); + return $this->in($name, $data, $message, $when); + } + + /******************** + * Date rules * + *******************/ + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function date($name, $message = '', $when = null) + { + return $this->add($name, 'date', $message, $when); + } + + /** + * @param $name + * @param $format + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function dateFormat($name, $format, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'date_format', $format, $message, $when); + } + + /** + * @param $name + * @param $date + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function before($name, $date, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'before', $date, $message, $when); + } + + /** + * @param $name + * @param $date + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function after($name, $date, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'after' . $date, $message, $when); + } + + /** + * @param $name + * @param $date + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function afterOrEqual($name, $date, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'after_or_equal', $date, $message, $when); + } + + /******************** + * File rules * + *******************/ + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function file($name, $message = '', $when = null) + { + return $this->add($name, 'file', $message, $when); + } + + /** + * @param $name + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function mimes($name, $data, $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'mimes' ,$data, $message, $when); + } + + /** + * @param $name + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function image($name, $message = '', $when = null) + { + return $this->add($name, 'image', $message, $when); + } + + /******************** + * DB rules * + *******************/ + /** + * @param $name + * @param array $params + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function exists($name, $params = [], $message = '', $when = null) + { + $this->makeArray($params); + + $model = array_shift($params); + $table = class_exists($model) ? app($model)->getTable() : $model; + $column = !empty($params) ? array_shift($params) : $name; + $connection = !empty($params) ? array_shift($params) : ''; + + $ruleStr = $connection ? $connection . '.' : ''; + $ruleStr .= $table . ',' . $column; + + return $this->fixRuleStructure($name, 'exists', $ruleStr, $message, $when); + } + + /** + * @param $name + * @param array $params + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function multiExists($name, $params = [], $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'multiExists', $params, $message, $when); + } + + /** + * @param $name + * @param array $params + * @param string $message + * @param null $when + * @return CoreValidator + * + * [class, ['column' => value]] + * [class, column1, ['column2' => value2]] + * [class, column1, ['column2' => value2, column3 => value3]] + * [class, column1, ['column2' => value2], [column3 => value3]] + */ + public function existsIf($name, $params = [], $message = '', $when = null) + { + return $this->fixDbIfRuleStructure($name, 'existsIf', $params, $message, $when); + } + + /** + * @param $name + * @param array $params + * @param string $message + * @param null $when + * @return CoreValidator + */ + public function multiExistsIf($name, $params = [], $message = '', $when = null) + { + return $this->fixDbIfRuleStructure($name, 'multiExistsIf', $params, $message, $when); + } + + /** + * @param $name + * @param $params + * @param $message + * @param null $when + * @return $this + */ + public function unique($name, $params = [], $message = '', $when = null) + { + return $this->fixRuleStructure($name, 'uniq', $params, $message, $when); + } + + /** + * TINYTEXT 256 bytes + * TEXT 65,535 bytes ~64kb + * MEDIUMTEXT 16,777,215 bytes ~16MB + * LONGTEXT 4,294,967,295 bytes ~4GB + * + * @param $length + * @return mixed + * @throws \Exception + */ + private function getTextLength($length) + { + if (is_numeric($length)) { + return $length; + } + + // @TODO - this is for MYSQL only + $types = [ + 'tinytext' => 256, + 'text' => 65535, + 'mediumtext' => 16777215, + 'longtext' => 4294967295 + ]; + + if (isset($types[$length])) { + return $types[$length]; + } + + throw new \Exception('Invalid length attribute'); + } + + /** + * @param $name + * @param array $data + * @return string + */ + private function addCustomRule($name, $data = []) + { + if (!empty($data['name'])) { + $validationName = $data['name']; + } else { + $validationName = md5($name.microtime(true)); + } + + if (!empty($data['implicit'])) { + self::extendImplicit($validationName, $data['rule']); + } else { + self::extend($validationName, $data['rule']); + } + + return $validationName; + } + + /** + * Checks $when's string values + * + * @param $name + * @param null $when + * @return \Closure|null + */ + protected function checkWhen($name, $when = null) + { + // if "isset" is provided - validate only if the given value is set + if ($when === 'isset') { + return function($input) use ($name) { + return array_key_exists($name, $input->toArray()); + }; + } + + // if "notempty" is provided - validate only if the given value is not empty + if ($when === 'notempty') { + return function($input) use ($name) { + $arr = $input->toArray(); + return !empty($arr[$name]); + }; + } + + return $when; + } + + + /** + * @param $name + * @param $rule + * @param $data + * @param string $message + * @param null $when + * @return $this|CoreValidator + * + * $data = 'field,value1,value2,value3' + * $data = [field, value1,value2,value3] + * $data = [ + * field1 => value1 + * field2 => [value1, value2] + * ] + */ + protected function fixMultiRuleStructure($name, $rule, $data, $message = '', $when = null) + { + if (is_string($data) || is_numeric(head(array_keys($data)))) { + return $this->fixRuleStructure($name, $rule, $data, $message, $when); + } + + foreach ($data as $filed => $values) { + $this->makeArray($values); + array_unshift($values, $filed); + $this->fixRuleStructure($name, $rule, $values, $message, $when); + } + + return $this; + } + + /** + * @param $name + * @param $rule + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + * + * $data = 'field1,field2,field3' + * $data = [field1, field2, field3] + */ + protected function fixRuleStructure($name, $rule, $data, $message = '', $when = null) + { + $this->makeArray($data); + $rule = sprintf('%s:%s', $rule, implode(',', $data)); + return $this->add($name, $rule, $message, $when); + } + + /** + * @param $name + * @param $rule + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + protected function fixDbIfRuleStructure($name, $rule, $data, $message = '', $when = null) + { + $this->makeArray($data); + $rule .= ':'; + + foreach ($data as $datum) { + if (is_array($datum)) { + foreach ($datum as $key => $value) { + $rule .= $key . '=>' . $value . ','; + } + } else { + + $rule .= $datum . ','; + } + } + + $rule = rtrim($rule, ','); + return $this->add($name, $rule, $message, $when); + } + + /** + * @param $name + * @param $method + * @param $data + * @param string $message + * @param null $when + * @return CoreValidator + */ + protected function addStringMethodRule($name, $method, $data , $message = '', $when = null) { + $this->makeArray($data); + + if (empty($message)) { + $message = sprintf('The %s must be %s ' , $name, str_replace('_', ' ', $method)); + $message .= count($data) == 1 ? '' : 'one of '; + $message .= implode(', ', $data); + } + + return $this->add($name, [ + 'rule' => function ($attribute, $value, $parameters, $validator) use ($method, $data) { + if (empty($value)) { + return true; + } + + return $method($value, $data); + }], $message, $when); + } + + /** + * @param $array + */ + protected function makeArray(&$array) + { + if (!is_array($array)) { + $array = [$array]; + } + } +} diff --git a/src/CoreValidatorInterface.php b/src/CoreValidatorInterface.php deleted file mode 100644 index 9181687..0000000 --- a/src/CoreValidatorInterface.php +++ /dev/null @@ -1,94 +0,0 @@ -initialize(); - $this->validator = $validator; - } - - /** - * - */ - public function initialize() - { - - } - - /** - * @param array $attributes - * @param array $options - * @return bool - */ - public function isValid(array $attributes, $options = []) - { - if (is_string($options)) { - $options = [ - 'rule' => $options - ]; - } - - $defaults = [ - 'rule' => 'default' - ]; - $options += $defaults; - - try { - $validationName = 'validation' . camel_case($options['rule']); - $validator = $this->{$validationName}(); - } catch (\Exception $e) { - - } - - $v = $validator->validate($attributes); - - if ($v->passes()) { - $this->setErrors(null); - return true; - } - - $this->setErrors($v->errors()); - return false; - } - - /** - * return error messages from last validation - * @return mixed - */ - public function getErrors() - { - return $this->errors; - } - - /** - * @param $errors - */ - protected function setErrors($errors) - { - $this->errors = $errors; - } -} +initialize(); + $this->validator = $validator; + } + +// public function setCustomRule($rule, $ruleName = '') +// { +// if (!ends_with($rule, 'Rule')) { +// //TODO not show exception +// throw new \Exception('The Rule Must be ends with "Rule"'); +// } +// +// $refl = new \ReflectionClass($rule); +// if (!in_array(RuleInterface::class, $refl->getInterfaceNames())) { +// //TODO not show exception +// throw new \Exception(sprintf('The Rule Must be implements %s interface', RuleInterface::class)); +// } +// +// if (empty($ruleName)) { +// $ruleName = last(explode(DIRECTORY_SEPARATOR, $rule)); +// $ruleName = str_replace('Rule', '', $ruleName); +// $ruleName = lcfirst($ruleName); +// } +// +// Validator::extend($ruleName, $rule . '@get'); +// } + + /** + * + */ + public function initialize() + { + + } + + /** + * @param array $attributes + * @param array $options + * @return bool + */ + public function isValid(array $attributes, $options = []) + { + if (is_string($options)) { + $options = [ + 'rule' => $options + ]; + } + + $defaults = [ + 'rule' => 'default' + ]; + $options += $defaults; + + try { + $validationName = 'validation' . camel_case($options['rule']); + $validator = $this->{$validationName}(); + } catch (\Exception $e) { + + } + + $v = $validator->validate($attributes); + + if ($v->passes()) { + $this->setErrors(null); + return true; + } + + $this->setErrors($v->errors()); + return false; + } + + /** + * return error messages from last validation + * @return mixed + */ + public function getErrors() + { + return $this->errors; + } + + /** + * @param $errors + */ + protected function setErrors($errors) + { + $this->errors = $errors; + } +} diff --git a/src/Rules/ExistsIfRule.php b/src/Rules/ExistsIfRule.php new file mode 100644 index 0000000..e192db8 --- /dev/null +++ b/src/Rules/ExistsIfRule.php @@ -0,0 +1,36 @@ +table($table)->select($column)->where($conditions); + + return $query->count(); + } + +} diff --git a/src/Rules/MultiExistsIfRule.php b/src/Rules/MultiExistsIfRule.php new file mode 100644 index 0000000..c03946d --- /dev/null +++ b/src/Rules/MultiExistsIfRule.php @@ -0,0 +1,40 @@ +table($table)->select($column)->where($conditions)->whereIn($column, $value); + + return $query->count(); + } + +} diff --git a/src/Rules/MultiExistsRule.php b/src/Rules/MultiExistsRule.php new file mode 100644 index 0000000..408776f --- /dev/null +++ b/src/Rules/MultiExistsRule.php @@ -0,0 +1,41 @@ +getTable() : $model; + $column = !empty($parameters) ? array_shift($parameters) : $attribute; + $connection= !empty($parameters) ? array_shift($parameters) : ''; + + $query = DB::connection($connection)->table($table)->select($column)->whereIn($column, $value); + $count = $query->count(); + return ($count == count($value)) ? true : false; + } + +} diff --git a/src/Rules/UniqRule.php b/src/Rules/UniqRule.php index a45cadf..1bf8116 100644 --- a/src/Rules/UniqRule.php +++ b/src/Rules/UniqRule.php @@ -1,62 +1,63 @@ -getData(); - if (empty($parameters[0])) { - throw new \InvalidArgumentException('Second parameter is required for unique validation'); - } - - $param1 = $parameters[0]; - unset($parameters[0]); - - if (class_exists($param1)) { - $model = App::make($param1); - $primaryKey = $model->getKeyName(); - $query = $model->newQuery(); - } else { - $primaryKey = 'id'; - $table = $param1; - $query = DB::table($table); - } - - // set main uniqueness condition - $query->where($attribute, '=', $value); - - // if primary key exists - set to NOT be equal (for updating case) - if (!empty($data[$primaryKey])) { - $query->where($primaryKey, '!=', $data[$primaryKey]); - } - - // check conditional columns - if (!empty($parameters)) { - foreach ($parameters as $column) { - if (isset($data[$column])) { - $query->where($column, '=', $data[$column]); - } - } - } - - $count = $query->count(); - return ($count == 0) ? true : false; - } - -} +getData(); + if (empty($parameters[0])) { + throw new \InvalidArgumentException('Second parameter is required for unique validation'); + } + + $param1 = $parameters[0]; + unset($parameters[0]); + + if (class_exists($param1)) { + $model = App::make($param1); + $primaryKey = $model->getKeyName(); + $query = $model->newQuery(); + } else { + $primaryKey = 'id'; + $table = $param1; + $query = DB::table($table); + } + + // set main uniqueness condition + $query->where($attribute, '=', $value); + + // if primary key exists - set to NOT be equal (for updating case) + if (!empty($data[$primaryKey])) { + $query->where($primaryKey, '!=', $data[$primaryKey]); + } + + // check conditional columns + if (!empty($parameters)) { + foreach ($parameters as $column) { + if (isset($data[$column])) { + $query->where($column, '=', $data[$column]); + } + } + } + + $count = $query->count(); + return ($count == 0) ? true : false; + } + +} diff --git a/src/Rules/ValidationRules.php b/src/Rules/ValidationRules.php index cf84f15..8fdec10 100644 --- a/src/Rules/ValidationRules.php +++ b/src/Rules/ValidationRules.php @@ -15,6 +15,9 @@ public static function execute() * Custom Rule for unique validation */ Validator::extend('uniq', 'LaraValidation\Rules\UniqRule@get'); + Validator::extend('multiExists', 'LaraValidation\Rules\MultiExistsRule@get'); + Validator::extend('existsIf', 'LaraValidation\Rules\ExistsIfRule@get'); + Validator::extend('multiExistsIf', 'LaraValidation\Rules\multiExistsIfRule@get'); // other rules should be added here diff --git a/src/Traits/DBParameterGetter.php b/src/Traits/DBParameterGetter.php new file mode 100644 index 0000000..d9b00fc --- /dev/null +++ b/src/Traits/DBParameterGetter.php @@ -0,0 +1,39 @@ +getTable() : $modelName; + $param = array_shift($parameters); + + if (str_contains($param, '=>')) { + $column = $attribute; + array_unshift($parameters, $param); + } else { + $column = $param; + $param = array_shift($parameters); + + if (str_contains($param, '=>')) { + array_unshift($parameters, $param); + } else { + $connection = $param; + } + } + + $conditions = []; + foreach ($parameters as $parameter) { + $condition = explode('=>', $parameter); + $conditions[array_shift($condition)] = array_shift($condition); + } + + return [$table, $column, $connection, $conditions]; + } +} \ No newline at end of file From a2e22ae5628acf5986ae01b81019db54e18cdd09 Mon Sep 17 00:00:00 2001 From: davitbek Date: Tue, 16 Jan 2018 16:31:28 +0400 Subject: [PATCH 2/2] improvement --- src/CoreValidator.php | 66 ++++++++++---- src/LaraValidator.php | 23 ----- src/Rules/DbRule.php | 147 +++++++++++++++++++++++++++++++ src/Rules/ExistsDbRule.php | 21 +++++ src/Rules/ExistsIfRule.php | 20 +---- src/Rules/MultiExistsIfRule.php | 23 +---- src/Rules/MultiExistsRule.php | 24 +---- src/Rules/ValidationRules.php | 7 +- src/Traits/DBParameterGetter.php | 39 -------- 9 files changed, 226 insertions(+), 144 deletions(-) create mode 100644 src/Rules/DbRule.php create mode 100644 src/Rules/ExistsDbRule.php delete mode 100644 src/Traits/DBParameterGetter.php diff --git a/src/CoreValidator.php b/src/CoreValidator.php index e9102e4..dd8e5e0 100644 --- a/src/CoreValidator.php +++ b/src/CoreValidator.php @@ -391,7 +391,6 @@ public function add($name, $rule, $message = '', $when = null) if (!empty($message)) { $this->_messages[$messageRule] = $message; } - $this->_lastField = $name; return $this; } @@ -765,20 +764,21 @@ public function image($name, $message = '', $when = null) * @param string $message * @param null $when * @return CoreValidator + * + * all time table or model full name + * + * $params = 'table' + * $params = ['table', 'column'] + * $params = ['table', 'column', 'connection'] + * + * if 'name' ends with '_id' auto 'column' => id */ public function exists($name, $params = [], $message = '', $when = null) { - $this->makeArray($params); - - $model = array_shift($params); - $table = class_exists($model) ? app($model)->getTable() : $model; - $column = !empty($params) ? array_shift($params) : $name; - $connection = !empty($params) ? array_shift($params) : ''; - - $ruleStr = $connection ? $connection . '.' : ''; - $ruleStr .= $table . ',' . $column; - - return $this->fixRuleStructure($name, 'exists', $ruleStr, $message, $when); + if (empty($message)) { + $message = 'Invalid argument is supplied'; + } + return $this->fixRuleStructure($name, 'exists_db', $params, $message, $when); } /** @@ -787,10 +787,20 @@ public function exists($name, $params = [], $message = '', $when = null) * @param string $message * @param null $when * @return CoreValidator + * + * all time table or model full name + * + * $params = 'table' + * $params = ['table'] + * $params = ['table', 'column'] + * $params = ['table', 'column', 'connection'] */ public function multiExists($name, $params = [], $message = '', $when = null) { - return $this->fixRuleStructure($name, 'multiExists', $params, $message, $when); + if (empty($message)) { + $message = 'Invalid argument is supplied'; + } + return $this->fixRuleStructure($name, 'multi_exists', $params, $message, $when); } /** @@ -800,14 +810,27 @@ public function multiExists($name, $params = [], $message = '', $when = null) * @param null $when * @return CoreValidator * - * [class, ['column' => value]] - * [class, column1, ['column2' => value2]] - * [class, column1, ['column2' => value2, column3 => value3]] - * [class, column1, ['column2' => value2], [column3 => value3]] + * all time table or model full name + * + * $params = ['table', ['column' => value]] + * $params = ['table', 'column', ['column1' => value1]] + * $params = ['table', 'column', 'connection', ['column1' => value1]] + * + * $params = ['table', ['column1' => 'value1', 'column2' => 'value2']] + * $params = ['table', 'column', ['column1' => 'value1', 'column2' => 'value2']] + * $params = ['table', 'column', 'connection', ['column1' => 'value1', 'column2' => 'value2']] + * + * $params = ['table', ['column1' => 'value1'], ['column2' => 'value2']] + * $params = ['table', 'column', ['column1' => 'value1'], ['column2' => 'value2']] + * $params = ['table', 'column', 'connection', ['column1' => 'value1'], ['column2' => 'value2']] + * */ public function existsIf($name, $params = [], $message = '', $when = null) { - return $this->fixDbIfRuleStructure($name, 'existsIf', $params, $message, $when); + if (empty($message)) { + $message = 'Invalid argument is supplied'; + } + return $this->fixDbIfRuleStructure($name, 'exists_if', $params, $message, $when); } /** @@ -816,10 +839,15 @@ public function existsIf($name, $params = [], $message = '', $when = null) * @param string $message * @param null $when * @return CoreValidator + * + * parameters see exist if */ public function multiExistsIf($name, $params = [], $message = '', $when = null) { - return $this->fixDbIfRuleStructure($name, 'multiExistsIf', $params, $message, $when); + if (empty($message)) { + $message = 'Invalid argument is supplied'; + } + return $this->fixDbIfRuleStructure($name, 'multi_exists_if', $params, $message, $when); } /** diff --git a/src/LaraValidator.php b/src/LaraValidator.php index f546169..b793b48 100644 --- a/src/LaraValidator.php +++ b/src/LaraValidator.php @@ -36,28 +36,6 @@ public function __construct(CoreValidator $validator) $this->validator = $validator; } -// public function setCustomRule($rule, $ruleName = '') -// { -// if (!ends_with($rule, 'Rule')) { -// //TODO not show exception -// throw new \Exception('The Rule Must be ends with "Rule"'); -// } -// -// $refl = new \ReflectionClass($rule); -// if (!in_array(RuleInterface::class, $refl->getInterfaceNames())) { -// //TODO not show exception -// throw new \Exception(sprintf('The Rule Must be implements %s interface', RuleInterface::class)); -// } -// -// if (empty($ruleName)) { -// $ruleName = last(explode(DIRECTORY_SEPARATOR, $rule)); -// $ruleName = str_replace('Rule', '', $ruleName); -// $ruleName = lcfirst($ruleName); -// } -// -// Validator::extend($ruleName, $rule . '@get'); -// } - /** * */ @@ -97,7 +75,6 @@ public function isValid(array $attributes, $options = []) $this->setErrors(null); return true; } - $this->setErrors($v->errors()); return false; } diff --git a/src/Rules/DbRule.php b/src/Rules/DbRule.php new file mode 100644 index 0000000..84158e1 --- /dev/null +++ b/src/Rules/DbRule.php @@ -0,0 +1,147 @@ +', $parameter); + $conditions[array_shift($condition)] = array_shift($condition); + } + + if (empty($conditions)) { + throw new \Exception('The Params must be contain [attribute => value] value'); + } + + $query = self::getQueryBased($tableParam, $column, $connection); + $query->where($conditions); + return self::fixIsMulti($isMulti, $query, $column, $value); + } + + /** + * @param $field + * @param $parameters + * @param $param + */ + protected static function fixField(&$field, &$parameters, $param) + { + if (!empty($param)) { + if (str_contains($param, '=>')) { + array_unshift($parameters, $param); + } else { + $field = $param; + } + } + } + + /** + * @param $tableParam + * @param $column + * @param $connection + * @return mixed + */ + protected static function getQueryBased($tableParam, $column, $connection) + { + if (class_exists($tableParam)) { + $model = app($tableParam); + $model->setConnection($connection); + $query = $model->newQuery(); + } else { + $query = DB::connection($connection)->table($tableParam)->select($column); + } + + return $query; + } + + /** + * @param $isMulti + * @param $query + * @param $column + * @param $value + * @return bool + */ + protected static function fixIsMulti($isMulti, $query, $column, $value) + { + + if (!$isMulti) { + return $query->where($column, $value)->count(); + } + + if (!is_array($value )) { + $value = [$value ]; + } + + $count = $query->whereIn($column, $value)->count(); + return ($count == count($value)) ? true : false; + } + +} diff --git a/src/Rules/ExistsDbRule.php b/src/Rules/ExistsDbRule.php new file mode 100644 index 0000000..23fa5ec --- /dev/null +++ b/src/Rules/ExistsDbRule.php @@ -0,0 +1,21 @@ +table($table)->select($column)->where($conditions); - - return $query->count(); + return self::getForExistsIf($attribute, $value, $parameters, $validator, 'exists'); } } diff --git a/src/Rules/MultiExistsIfRule.php b/src/Rules/MultiExistsIfRule.php index c03946d..0211e4d 100644 --- a/src/Rules/MultiExistsIfRule.php +++ b/src/Rules/MultiExistsIfRule.php @@ -1,13 +1,10 @@ table($table)->select($column)->where($conditions)->whereIn($column, $value); - - return $query->count(); + return self::getForExistsIf($attribute, $value, $parameters, $validator, 'multiExistsIf', true); } } diff --git a/src/Rules/MultiExistsRule.php b/src/Rules/MultiExistsRule.php index 408776f..9f4acbb 100644 --- a/src/Rules/MultiExistsRule.php +++ b/src/Rules/MultiExistsRule.php @@ -1,10 +1,9 @@ getTable() : $model; - $column = !empty($parameters) ? array_shift($parameters) : $attribute; - $connection= !empty($parameters) ? array_shift($parameters) : ''; - - $query = DB::connection($connection)->table($table)->select($column)->whereIn($column, $value); - $count = $query->count(); - return ($count == count($value)) ? true : false; + return self::getForExists($attribute, $value, $parameters, $validator, 'multyExists', true); } } diff --git a/src/Rules/ValidationRules.php b/src/Rules/ValidationRules.php index 8fdec10..05f360b 100644 --- a/src/Rules/ValidationRules.php +++ b/src/Rules/ValidationRules.php @@ -15,9 +15,10 @@ public static function execute() * Custom Rule for unique validation */ Validator::extend('uniq', 'LaraValidation\Rules\UniqRule@get'); - Validator::extend('multiExists', 'LaraValidation\Rules\MultiExistsRule@get'); - Validator::extend('existsIf', 'LaraValidation\Rules\ExistsIfRule@get'); - Validator::extend('multiExistsIf', 'LaraValidation\Rules\multiExistsIfRule@get'); + Validator::extend('exists_db', 'LaraValidation\Rules\ExistsDbRule@get'); + Validator::extend('exists_if', 'LaraValidation\Rules\ExistsIfRule@get'); + Validator::extend('multi_exists', 'LaraValidation\Rules\MultiExistsRule@get'); + Validator::extend('multi_exists_if', 'LaraValidation\Rules\multiExistsIfRule@get'); // other rules should be added here diff --git a/src/Traits/DBParameterGetter.php b/src/Traits/DBParameterGetter.php deleted file mode 100644 index d9b00fc..0000000 --- a/src/Traits/DBParameterGetter.php +++ /dev/null @@ -1,39 +0,0 @@ -getTable() : $modelName; - $param = array_shift($parameters); - - if (str_contains($param, '=>')) { - $column = $attribute; - array_unshift($parameters, $param); - } else { - $column = $param; - $param = array_shift($parameters); - - if (str_contains($param, '=>')) { - array_unshift($parameters, $param); - } else { - $connection = $param; - } - } - - $conditions = []; - foreach ($parameters as $parameter) { - $condition = explode('=>', $parameter); - $conditions[array_shift($condition)] = array_shift($condition); - } - - return [$table, $column, $connection, $conditions]; - } -} \ No newline at end of file