各个验证器的提示消息
@param  string|\Closure $validator 验证器
@param  string          $field
@param  array           $args
@param  string|array    $message 自定义提示消息
@return string
321890
public function getMessage($validator, string $field, array $args = [], $message = null): string
    {
        $rawName = \is_string($validator) ? $validator : 'callback';
        $params  = [
            '{attr}' => $this->getTranslate($field)
        ];

        // get message from built in dict.
        if (!$message) {
            $message = $this->findMessage($field, $rawName) ?: GlobalMessage::getDefault();
            // is array. It's defined multi error messages
        } elseif (\is_array($message)) {
            $message = $message[$rawName] ?? $this->findMessage($field, $rawName);

            if (!$message) { // use default
                return \strtr(GlobalMessage::getDefault(), $params);
            }
        } else {
            $message = (string)$message;
        }

        /** @see GlobalMessage::$messages['size'] */
        if (\is_array($message)) {
            $msgKey  = \count($args);
            $message = $message[$msgKey] ?? $message[0];
        }

        if (false === \strpos($message, '{')) {
            return $message;
        }

        foreach ($args as $key => $value) {
            $key = \is_int($key) ? "value{$key}" : $key;
            // build params
            $params['{' . $key . '}'] = \is_array($value) ? \implode(',', $value) : $value;
        }

        return \strtr($message, $params);
    }
135716
function validate($value, $key, $fields, $options, $exists, \CharlotteDunois\Validation\Validator $validator) {
        $finfo = \finfo_open(\FILEINFO_MIME);
        
        if(isset($_FILES[$key])) {
            if(!\file_exists($_FILES[$key]['tmp_name'])) {
                return 'formvalidator_make_invalid_file';
            }
            
            $mime = \finfo_file($finfo, $_FILES[$key]['tmp_name']);
        } else {
            if(!$exists) {
                return false;
            }
            
            $mime = \finfo_buffer($finfo, $value);
        }
        
        \finfo_close($finfo);
        
        if(!$mime) {
            return 'formvalidator_make_invalid_file'; // @codeCoverageIgnore
        }
        
        $mime = \explode(';', $mime);
        $mime = \array_shift($mime);
        
        $val = \explode(',', $options);
        $result = \explode('/', $mime);
        
        foreach($val as $mimet) {
            $mimee = \explode('/', $mimet);
            if(\count($mimee) == 2 && \count($result) == 2) {
                if(($mimee[0] == "*" || $mimee[0] == $result[0]) && ($mimee[1] == "*" || $mimee[1] == $result[1])) {
                    return true;
                }
            }
        }
        
        return 'formvalidator_make_invalid_file';
    }
72965
protected function validateArray($value, string $parameter, array $args = [], array $rules = null, array $context = null): ?string
    {
        $count = $args[0] ?? null;

        if ($count !== null) {
            if ($count == '' || !is_numeric($count)) {
                throw new ValidatorConfigException("Invalid array count definition for parameter {$parameter}");
            }

            $count = (int)$count;

            if ($count < 0) {
                throw new ValidatorConfigException("Invalid array count definition for parameter {$parameter}, argument can not be negative");
            }
        }

        //$value = $this->getValue($parameter);

        if ($value === null) {
            return null;
        }

        if (is_string($value) && $value === '') {
            return null;
        }

        if (!is_array($value)) {
            return Message::getMessage(Message::IS_NOT_ARRAY, [
                'param' => $parameter
            ]);
        }

        if ($count !== null) {
            $currentCount = count($value);

            if ($currentCount != $count) {
                if (ctype_digit($parameter)) {
                    $parameter = "Element on position {$parameter}";
                }

                return Message::getMessage(Message::ARRAY_WRONG_COUNT, [
                    'param' => $parameter,
                    'requiredCount' => $count,
                    'currentCount' => $currentCount
                ]);
            }
        }

        return null;
    }
1200520
protected function applyValidator($validator, $key, $value, $messages = [])
    {
        try {
            if ($this->isString($validator)) {
                $params = $this->arr(explode(':', $validator));
                $vName = '';
                $validatorParams = [$this, $value, $params->removeFirst($vName)->val()];
                $validator = Entity::getInstance()->getValidator($vName);
                if (!$validator) {
                    throw new ValidationException('Validator does not exist');
                }
                $validator->validate(...$validatorParams);
            } elseif ($this->isCallable($validator)) {
                $vName = 'callable';
                $validator($value, $this);
            }
        } catch (ValidationException $e) {
            $msg = isset($messages[$vName]) ? $messages[$vName] : $e->getMessage();

            $ex = new ValidationException($msg);
            $ex->addError($key, $msg);

            throw $ex;
        }
    }
721765
protected function validateIs($value, string $parameter, array $args = [], array $rules = null, array $context = null): ?string
    {
        if (count($args) == 0) {
            throw new ValidatorConfigException("Validator 'is' must have argument in validator list for parameter {$parameter}");
        }

        //$value = $this->getValue($parameter);

        if ($value === null) {
            return null;
        }

        if (!is_scalar($value)) {
            return Message::getMessage(Message::PRIMITIVE, [
                'param' => $parameter
            ]);
        }

        $value = trim((string)$value);

        if ($value === '') {
            return null;
        }

        if ($value !== $args[0]) {
            return Message::getMessage(Message::IS, [
                'param' => $parameter,
                'value' => $value
            ]);
        }

        return null;
    }
1333171
public static function translate(string $message, ...$args): string
    {
        $message = self::$translator->translate($message);

        return sprintf($message, ...$args);
    }
241260
public function matches($field, $label, $message = null)
    {
        $this->setRule(__FUNCTION__, function($val, $args)
                       {
                           return ((string) $args[0] == (string) $val);
                       }, $message, array($this->_getVal($field), $label));
        return $this;
    }
568489
public static function getValidatorErrorMessage($validator)
    {
        $messages = $validator->errors();
        $msgArr = $messages->all();
        $arr = [];
        foreach ($msgArr as $k => $v) {
            $arr[] = $v;
        }
        $ret = implode(",", $arr);
        return $ret;
    }
417528
protected function validateEndsWith($value, string $parameter, array $args = [], array $rules = null, array $context = null): ?string
    {
        if (count($args) == 0) {
            throw new ValidatorConfigException("Validator 'endsWith' must have argument in validator list for parameter {$parameter}");
        }

        $endsWith = $args[0] ?? '';

        if (strlen($endsWith) == 0) {
            throw new ValidatorConfigException("Validator 'endsWith' have empty argument in validator list for parameter {$parameter}");
        }

        //$value = $this->getValue($parameter);

        if ($value === null) {
            return null;
        }

        if (!is_scalar($value)) {
            return Message::getMessage(Message::PRIMITIVE, [
                'param' => $parameter
            ]);
        }

        $value = trim((string)$value);

        if ($value === '') {
            return null;
        }

        if (!Util::endsWith($value, $endsWith)) {
            return Message::getMessage(Message::ENDS_WITH, [
            	'endsWith' => $endsWith,
                'param' => $parameter,
                'value' => $value
            ]);
        }

        return null;
    }
193413
public function eachValidator(array $values, ...$args): bool
    {
        if (!$validator = \array_shift($args)) {
            throw new \InvalidArgumentException('must setting a validator for \'each\' validate.');
        }

        foreach ($values as $value) {
            $passed = false;

            if (\is_object($validator) && \method_exists($validator, '__invoke')) {
                $passed = $validator($value, ...$args);
            } elseif (\is_string($validator)) {
                // special for required
                if ('required' === $validator) {
                    $passed = !Validators::isEmpty($value);

                } elseif (isset($this->_validators[$validator])) {
                    $callback = $this->_validators[$validator];
                    $passed   = $callback($value, ...$args);

                } elseif (\method_exists($this, $method = $validator . 'Validator')) {
                    $passed = $this->$method($value, ...$args);

                } elseif (\method_exists(Validators::class, $validator)) {
                    $passed = Validators::$validator($value, ...$args);

                    // it is function name
                } elseif (\function_exists($validator)) {
                    $passed = $validator($value, ...$args);
                } else {
                    throw new \InvalidArgumentException("The validator [$validator] don't exists!");
                }
            }

            if (!$passed) {
                return false;
            }
        }

        return true;
    }
1198831
protected function callMessageBuilder( $callback, $message )
	{
		if ( $callback instanceof Closure )
			return call_user_func( $callback, $message );

		if ( is_string( $callback ) )
			return UniversalBuilder::resolve( $callback )->mail( $message );

		throw new InvalidArgumentException( 'Callback is not valid.' );
	}
1066769
public function validate($field, $value, $validator) {
		if(empty($value)) return true;
		return (bool) preg_match($this->regex, $value);
	}
1322676
private function callValidators($value, ValidationField $field) {
        $valid = true;

        // Strip array references in the name except for the last one.
        $key = $field->getSchemaPath();
        if (!empty($this->validators[$key])) {
            foreach ($this->validators[$key] as $validator) {
                $r = call_user_func($validator, $value, $field);

                if ($r === false || Invalid::isInvalid($r)) {
                    $valid = false;
                }
            }
        }

        // Add an error on the field if the validator hasn't done so.
        if (!$valid && $field->isValid()) {
            $field->addError('invalid', ['messageCode' => 'The value is invalid.']);
        }
    }
427933
public function setValidationRules($table, string $field, Validator $validator, array $options = []) : Validator
    {
        $handler = self::getByTableField($table, $field);
        $validator = $handler->setValidationRules($validator, $options);
        if (! $validator instanceof Validator) {
            throw new RuntimeException(
                sprintf('Field Handler returned value must be an instance of %s.', Validator::class)
            );
        }

        return $validator;
    }
953352
function validate() {
        $rules = [];
        foreach ($this->rules as $field => $_rules) {
            $this->rules[$field] = array_values($_rules);
        }

        $replacers = [];
        $id        = (int)Arr::get($this->data, $this->field_id);

        foreach ($this->rules as $field => $_rules) {
            foreach ($_rules as $rule) {
                if (is_string($rule)) {
                    $rules[$field][]           = str_replace('{id}', $id, $rule);
                    $replacer_name             = explode(":", $rule);
                    $replacer_rule             = array_shift($replacer_name);
                    $replacers[$replacer_rule] = [];
                }
                else {
                    $rules[$field][] = $rule;
                }

            }
        }
        if (count($replacers)) {
            /*foreach ($replacers as $rule => $vb) {
//                dd($replacers);
                \Validator::replacer(
                    $rule,
                    function ($message, $attribute, $rule, $parameters) {
                        $fields    = array_keys($this->data);
                        $replacers = array_map(
                            function ($value) {
                                return ':value=' . $value;
                            },
                            $fields
                        );
                        $replacers = array_merge(
                            $replacers,
                            array_map(
                                function ($value) {
                                    return ':label=' . $value;
                                },
                                $fields
                            )
                        );
                        return str_replace($replacers, $this->data + $this->labels, $message);
                    }
                );
            }*/
        }
        //        dd($this->messages);
        //        dd($this->labels);
        //        dump($this->labels);
        $this->validator = \Validator::make($this->data, $rules, $this->messages, $this->labels);
        foreach ($this->data as $k => $v) {
            $values['value__' . $k] = $v;
        }
        $this->validator->setValueNames($values);
        //        dd($this->validator);

        //        $this->validator->addReplacer()
        return !$this->validator->fails();
    }
760063
protected function getPickItemsHtml(Field $field, ValidationParser $parser)
    {
        $fields = '';

        if ($field->isBoolean()) {
            // At this point we know this is a boolean field, we only need one option
            $fields .= $this->getPickItemsHtmlField($field, $field->getTrueBooleanOption(), $parser) . PHP_EOL;
        } else {
            if (is_null($field->getOptionsByLang())) {
                throw new Exception('The field "' . $field->name . '" has no options!');
            }

            foreach ($field->getOptionsByLang() as $index => $option) {
                $fields .= $this->getPickItemsHtmlField($field, $option, $parser) . PHP_EOL;
            }
        }

        $this->wrapField($fields, $field, true, (($field->htmlType == 'checkbox') && !$field->isBoolean()) ? 'required' : '');

        return $fields;
    }
879260
function validate($value, $key, $fields, $options, $exists, \CharlotteDunois\Validation\Validator $validator) {
        if(isset($_FILES[$key])) {
            if(!\file_exists($_FILES[$key]['tmp_name'])) {
                return 'formvalidator_make_invalid_file';
            }
            
            $size = \getimagesize($_FILES[$key]['tmp_name']);
        } else {
            if(!$exists) {
                return false;
            }
            
            $size = @\getimagesizefromstring($value);
        }
        
        if(!$size) {
            return 'formvalidator_make_invalid_file';
        }
        
        $n = \explode(',', $options);
        foreach($n as $x) {
            $k = \explode('=', $x);
            switch($k[0]) {
                case 'min_width': // @codeCoverageIgnore
                    if($k[1] > $size[0]) {
                        return array('formvalidator_make_min_width', array('{0}' => $options));
                    }
                break;
                case 'min_height': // @codeCoverageIgnore
                    if($k[1] > $size[1]) {
                        return array('formvalidator_make_min_height', array('{0}' => $options));
                    }
                break;
                case 'width': // @codeCoverageIgnore
                    if($k[1] != $size[0]) {
                        return array('formvalidator_make_width', array('{0}' => $options));
                    }
                break;
                case 'height': // @codeCoverageIgnore
                    if($k[1] != $size[1]) {
                        return array('formvalidator_make_height', array('{0}' => $options));
                    }
                break;
                case 'max_width': // @codeCoverageIgnore
                    if($k[1] < $size[0]) {
                        return array('formvalidator_make_max_width', array('{0}' => $options));
                    }
                break;
                case 'max_height': // @codeCoverageIgnore
                    if($k[1] < $size[1]) {
                        return array('formvalidator_make_max_height', array('{0}' => $options));
                    }
                break;
                case 'ratio': // @codeCoverageIgnore
                    if(\mb_strpos($k[1], '/') !== false) {
                        $k[1] = \explode('/', $k[1]);
                        $k[1] = $k[1][0] / $k[1][1];
                    }
                    
                    if(\number_format(($size[0] / $size[1]), 1) != \number_format($k[1], 1)) {
                        return array('formvalidator_make_ratio', array('{0}' => $options));
                    }
                break;
            }
        }
        
        return true;
    }