/laradock/vendor/illuminate/validation/ValidationRuleParser.php
https://gitlab.com/hoangduys4k5/laravelproject · PHP · 338 lines · 177 code · 48 blank · 113 comment · 22 complexity · f3d38dad75236d8ddf6492f85fa75b32 MD5 · raw file
- <?php
- namespace Illuminate\Validation;
- use Closure;
- use Illuminate\Contracts\Validation\Rule as RuleContract;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Str;
- use Illuminate\Validation\Rules\Exists;
- use Illuminate\Validation\Rules\Unique;
- class ValidationRuleParser
- {
- /**
- * The data being validated.
- *
- * @var array
- */
- public $data;
- /**
- * The implicit attributes.
- *
- * @var array
- */
- public $implicitAttributes = [];
- /**
- * Create a new validation rule parser.
- *
- * @param array $data
- * @return void
- */
- public function __construct(array $data)
- {
- $this->data = $data;
- }
- /**
- * Parse the human-friendly rules into a full rules array for the validator.
- *
- * @param array $rules
- * @return \stdClass
- */
- public function explode($rules)
- {
- $this->implicitAttributes = [];
- $rules = $this->explodeRules($rules);
- return (object) [
- 'rules' => $rules,
- 'implicitAttributes' => $this->implicitAttributes,
- ];
- }
- /**
- * Explode the rules into an array of explicit rules.
- *
- * @param array $rules
- * @return array
- */
- protected function explodeRules($rules)
- {
- foreach ($rules as $key => $rule) {
- if (str_contains($key, '*')) {
- $rules = $this->explodeWildcardRules($rules, $key, [$rule]);
- unset($rules[$key]);
- } else {
- $rules[$key] = $this->explodeExplicitRule($rule, $key);
- }
- }
- return $rules;
- }
- /**
- * Explode the explicit rule into an array if necessary.
- *
- * @param mixed $rule
- * @param string $attribute
- * @return array
- */
- protected function explodeExplicitRule($rule, $attribute)
- {
- if (is_string($rule)) {
- [$name] = static::parseStringRule($rule);
- return static::ruleIsRegex($name) ? [$rule] : explode('|', $rule);
- }
- if (is_object($rule)) {
- return Arr::wrap($this->prepareRule($rule, $attribute));
- }
- return array_map(
- [$this, 'prepareRule'],
- $rule,
- array_fill(array_key_first($rule), count($rule), $attribute)
- );
- }
- /**
- * Prepare the given rule for the Validator.
- *
- * @param mixed $rule
- * @param string $attribute
- * @return mixed
- */
- protected function prepareRule($rule, $attribute)
- {
- if ($rule instanceof Closure) {
- $rule = new ClosureValidationRule($rule);
- }
- if (! is_object($rule) ||
- $rule instanceof RuleContract ||
- ($rule instanceof Exists && $rule->queryCallbacks()) ||
- ($rule instanceof Unique && $rule->queryCallbacks())) {
- return $rule;
- }
- if ($rule instanceof NestedRules) {
- return $rule->compile(
- $attribute, $this->data[$attribute] ?? null, Arr::dot($this->data)
- )->rules[$attribute];
- }
- return (string) $rule;
- }
- /**
- * Define a set of rules that apply to each element in an array attribute.
- *
- * @param array $results
- * @param string $attribute
- * @param string|array $rules
- * @return array
- */
- protected function explodeWildcardRules($results, $attribute, $rules)
- {
- $pattern = str_replace('\*', '[^\.]*', preg_quote($attribute));
- $data = ValidationData::initializeAndGatherData($attribute, $this->data);
- foreach ($data as $key => $value) {
- if (Str::startsWith($key, $attribute) || (bool) preg_match('/^'.$pattern.'\z/', $key)) {
- foreach (Arr::flatten((array) $rules) as $rule) {
- if ($rule instanceof NestedRules) {
- $compiled = $rule->compile($key, $value, $data);
- $this->implicitAttributes = array_merge_recursive(
- $compiled->implicitAttributes,
- $this->implicitAttributes,
- [$attribute => [$key]]
- );
- $results = $this->mergeRules($results, $compiled->rules);
- } else {
- $this->implicitAttributes[$attribute][] = $key;
- $results = $this->mergeRules($results, $key, $rule);
- }
- }
- }
- }
- return $results;
- }
- /**
- * Merge additional rules into a given attribute(s).
- *
- * @param array $results
- * @param string|array $attribute
- * @param string|array $rules
- * @return array
- */
- public function mergeRules($results, $attribute, $rules = [])
- {
- if (is_array($attribute)) {
- foreach ((array) $attribute as $innerAttribute => $innerRules) {
- $results = $this->mergeRulesForAttribute($results, $innerAttribute, $innerRules);
- }
- return $results;
- }
- return $this->mergeRulesForAttribute(
- $results, $attribute, $rules
- );
- }
- /**
- * Merge additional rules into a given attribute.
- *
- * @param array $results
- * @param string $attribute
- * @param string|array $rules
- * @return array
- */
- protected function mergeRulesForAttribute($results, $attribute, $rules)
- {
- $merge = head($this->explodeRules([$rules]));
- $results[$attribute] = array_merge(
- isset($results[$attribute]) ? $this->explodeExplicitRule($results[$attribute], $attribute) : [], $merge
- );
- return $results;
- }
- /**
- * Extract the rule name and parameters from a rule.
- *
- * @param array|string $rule
- * @return array
- */
- public static function parse($rule)
- {
- if ($rule instanceof RuleContract || $rule instanceof NestedRules) {
- return [$rule, []];
- }
- if (is_array($rule)) {
- $rule = static::parseArrayRule($rule);
- } else {
- $rule = static::parseStringRule($rule);
- }
- $rule[0] = static::normalizeRule($rule[0]);
- return $rule;
- }
- /**
- * Parse an array based rule.
- *
- * @param array $rule
- * @return array
- */
- protected static function parseArrayRule(array $rule)
- {
- return [Str::studly(trim(Arr::get($rule, 0, ''))), array_slice($rule, 1)];
- }
- /**
- * Parse a string based rule.
- *
- * @param string $rule
- * @return array
- */
- protected static function parseStringRule($rule)
- {
- $parameters = [];
- // The format for specifying validation rules and parameters follows an
- // easy {rule}:{parameters} formatting convention. For instance the
- // rule "Max:3" states that the value may only be three letters.
- if (str_contains($rule, ':')) {
- [$rule, $parameter] = explode(':', $rule, 2);
- $parameters = static::parseParameters($rule, $parameter);
- }
- return [Str::studly(trim($rule)), $parameters];
- }
- /**
- * Parse a parameter list.
- *
- * @param string $rule
- * @param string $parameter
- * @return array
- */
- protected static function parseParameters($rule, $parameter)
- {
- return static::ruleIsRegex($rule) ? [$parameter] : str_getcsv($parameter);
- }
- /**
- * Determine if the rule is a regular expression.
- *
- * @param string $rule
- * @return bool
- */
- protected static function ruleIsRegex($rule)
- {
- return in_array(strtolower($rule), ['regex', 'not_regex', 'notregex'], true);
- }
- /**
- * Normalizes a rule so that we can accept short types.
- *
- * @param string $rule
- * @return string
- */
- protected static function normalizeRule($rule)
- {
- return match ($rule) {
- 'Int' => 'Integer',
- 'Bool' => 'Boolean',
- default => $rule,
- };
- }
- /**
- * Expand and conditional rules in the given array of rules.
- *
- * @param array $rules
- * @param array $data
- * @return array
- */
- public static function filterConditionalRules($rules, array $data = [])
- {
- return collect($rules)->mapWithKeys(function ($attributeRules, $attribute) use ($data) {
- if (! is_array($attributeRules) &&
- ! $attributeRules instanceof ConditionalRules) {
- return [$attribute => $attributeRules];
- }
- if ($attributeRules instanceof ConditionalRules) {
- return [$attribute => $attributeRules->passes($data)
- ? array_filter($attributeRules->rules($data))
- : array_filter($attributeRules->defaultRules($data)), ];
- }
- return [$attribute => collect($attributeRules)->map(function ($rule) use ($data) {
- if (! $rule instanceof ConditionalRules) {
- return [$rule];
- }
- return $rule->passes($data) ? $rule->rules($data) : $rule->defaultRules($data);
- })->filter()->flatten(1)->values()->all()];
- })->all();
- }
- }