Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Validation/ValidationRuleParser.php
Строк: 268
<?php

namespace IlluminateValidation;

use 
Closure;
use 
IlluminateContractsValidationCompilableRules;
use 
IlluminateContractsValidationInvokableRule;
use 
IlluminateContractsValidationRule as RuleContract;
use 
IlluminateContractsValidationValidationRule;
use 
IlluminateSupportArr;
use 
IlluminateSupportCollection;
use 
IlluminateSupportStr;
use 
IlluminateValidationRulesDate;
use 
IlluminateValidationRulesExists;
use 
IlluminateValidationRulesNumeric;
use 
IlluminateValidationRulesStringRule;
use 
IlluminateValidationRulesUnique;

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
     */
    
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)) {
            return 
explode('|', $rule);
        }

        if (
is_object($rule)) {
            if (
$rule instanceof Date || $rule instanceof Numeric || $rule instanceof StringRule) {
                return 
explode('|', (string) $rule);
            }

            return 
Arr::wrap($this->prepareRule($rule, $attribute));
        }

        
$rules = [];

        foreach (
$rule as $value) {
            if (
$value instanceof Date || $value instanceof Numeric || $value instanceof StringRule) {
                
$rules = array_merge($rules, explode('|', (string) $value));
            } else {
                
$rules[] = $this->prepareRule($value, $attribute);
            }
        }

        return 
$rules;
    }

    
/**
     * 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 (
$rule instanceof InvokableRule || $rule instanceof ValidationRule) {
            
$rule = InvokableValidationRule::make($rule);
        }

        if (! 
is_object($rule) ||
            
$rule instanceof RuleContract ||
            (
$rule instanceof Exists && $rule->queryCallbacks()) ||
            (
$rule instanceof Unique && $rule->queryCallbacks())) {
            return 
$rule;
        }

        if (
$rule instanceof CompilableRules) {
            return 
$rule->compile(
                
$attribute, $this->data[$attribute] ?? null, Arr::dot($this->data), $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 ((array) 
$rules as $rule) {
                    if (
$rule instanceof CompilableRules) {
                        
$context = Arr::get($this->data, Str::beforeLast($key, '.'));

                        
$compiled = $rule->compile($key, $value, $data, $context);

                        
$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 CompilableRules) {
            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, escape: '\');
    }

    /**
     * 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 the conditional rules in the given array of rules.
     *
     * @param  array  $rules
     * @param  array  $data
     * @return array
     */
    public static function filterConditionalRules($rules, array $data = [])
    {
        return (new Collection($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 => (new Collection($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();
    }
}
Онлайн: 2
Реклама