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

namespace IlluminateValidationConcerns;

use 
Closure;
use 
IlluminateSupportArr;
use 
IlluminateSupportStr;
use 
SymfonyComponentHttpFoundationFileFile;
use 
SymfonyComponentHttpFoundationFileUploadedFile;

trait 
FormatsMessages
{
    use 
ReplacesAttributes;

    
/**
     * Get the validation message for an attribute and rule.
     *
     * @param  string  $attribute
     * @param  string  $rule
     * @return string
     */
    
protected function getMessage($attribute$rule)
    {
        
$attributeWithPlaceholders $attribute;

        
$attribute $this->replacePlaceholderInString($attribute);

        
$inlineMessage $this->getInlineMessage($attribute$rule);

        
// First we will retrieve the custom message for the validation rule if one
        // exists. If a custom validation message is being used we'll return the
        // custom message, otherwise we'll keep searching for a valid message.
        
if (! is_null($inlineMessage)) {
            return 
$inlineMessage;
        }

        
$lowerRule Str::snake($rule);

        
$customKey "validation.custom.{$attribute}.{$lowerRule}";

        
$customMessage $this->getCustomMessageFromTranslator(
            
in_array($rule$this->sizeRules)
                ? [
$customKey.".{$this->getAttributeType($attribute)}"$customKey]
                : 
$customKey
        
);

        
// First we check for a custom defined validation message for the attribute
        // and rule. This allows the developer to specify specific messages for
        // only some attributes and rules that need to get specially formed.
        
if ($customMessage !== $customKey) {
            return 
$customMessage;
        }

        
// If the rule being validated is a "size" rule, we will need to gather the
        // specific error message for the type of attribute being validated such
        // as a number, file or string which all have different message types.
        
elseif (in_array($rule$this->sizeRules)) {
            return 
$this->getSizeMessage($attributeWithPlaceholders$rule);
        }

        
// Finally, if no developer specified messages have been set, and no other
        // special messages apply for this rule, we will just pull the default
        // messages out of the translator service for this validation rule.
        
$key "validation.{$lowerRule}";

        if (
$key !== ($value $this->translator->get($key))) {
            return 
$value;
        }

        return 
$this->getFromLocalArray(
            
$attribute$lowerRule$this->fallbackMessages
        
) ?: $key;
    }

    
/**
     * Get the proper inline error message for standard and size rules.
     *
     * @param  string  $attribute
     * @param  string  $rule
     * @return string|null
     */
    
protected function getInlineMessage($attribute$rule)
    {
        
$inlineEntry $this->getFromLocalArray($attributeStr::snake($rule));

        return 
is_array($inlineEntry) && in_array($rule$this->sizeRules)
                    ? 
$inlineEntry[$this->getAttributeType($attribute)]
                    : 
$inlineEntry;
    }

    
/**
     * Get the inline message for a rule if it exists.
     *
     * @param  string  $attribute
     * @param  string  $lowerRule
     * @param  array|null  $source
     * @return string|null
     */
    
protected function getFromLocalArray($attribute$lowerRule$source null)
    {
        
$source $source ?: $this->customMessages;

        
$keys = ["{$attribute}.{$lowerRule}"$lowerRule$attribute];

        
// First we will check for a custom message for an attribute specific rule
        // message for the fields, then we will check for a general custom line
        // that is not attribute specific. If we find either we'll return it.
        
foreach ($keys as $key) {
            foreach (
array_keys($source) as $sourceKey) {
                if (
str_contains($sourceKey'*')) {
                    
$pattern str_replace('*''([^.]*)'preg_quote($sourceKey'#'));

                    if (
preg_match('#^'.$pattern.'z#u'$key) === 1) {
                        
$message $source[$sourceKey];

                        if (
is_array($message) && isset($message[$lowerRule])) {
                            return 
$message[$lowerRule];
                        }

                        return 
$message;
                    }

                    continue;
                }

                if (
Str::is($sourceKey$key)) {
                    
$message $source[$sourceKey];

                    if (
$sourceKey === $attribute && is_array($message) && isset($message[$lowerRule])) {
                        return 
$message[$lowerRule];
                    }

                    return 
$message;
                }
            }
        }
    }

    
/**
     * Get the custom error message from the translator.
     *
     * @param  array|string  $keys
     * @return string
     */
    
protected function getCustomMessageFromTranslator($keys)
    {
        foreach (
Arr::wrap($keys) as $key) {
            if ((
$message $this->translator->get($key)) !== $key) {
                return 
$message;
            }

            
// If an exact match was not found for the key, we will collapse all of these
            // messages and loop through them and try to find a wildcard match for the
            // given key. Otherwise, we will simply return the key's value back out.
            
$shortKey preg_replace(
                
'/^validation.custom./'''$key
            
);

            
$message $this->getWildcardCustomMessages(Arr::dot(
                (array) 
$this->translator->get('validation.custom')
            ), 
$shortKey$key);

            if (
$message !== $key) {
                return 
$message;
            }
        }

        return 
Arr::last(Arr::wrap($keys));
    }

    
/**
     * Check the given messages for a wildcard key.
     *
     * @param  array  $messages
     * @param  string  $search
     * @param  string  $default
     * @return string
     */
    
protected function getWildcardCustomMessages($messages$search$default)
    {
        foreach (
$messages as $key => $message) {
            if (
$search === $key || (Str::contains($key, ['*']) && Str::is($key$search))) {
                return 
$message;
            }
        }

        return 
$default;
    }

    
/**
     * Get the proper error message for an attribute and size rule.
     *
     * @param  string  $attribute
     * @param  string  $rule
     * @return string
     */
    
protected function getSizeMessage($attribute$rule)
    {
        
$lowerRule Str::snake($rule);

        
// There are three different types of size validations. The attribute may be
        // either a number, file, or string so we will check a few things to know
        // which type of value it is and return the correct line for that type.
        
$type $this->getAttributeType($attribute);

        
$key "validation.{$lowerRule}.{$type}";

        return 
$this->translator->get($key);
    }

    
/**
     * Get the data type of the given attribute.
     *
     * @param  string  $attribute
     * @return string
     */
    
protected function getAttributeType($attribute)
    {
        
// We assume that the attributes present in the file array are files so that
        // means that if the attribute does not have a numeric rule and the files
        // list doesn't have it we'll just consider it a string by elimination.
        
return match (true) {
            
$this->hasRule($attribute$this->numericRules) => 'numeric',
            
$this->hasRule($attribute, ['Array']) => 'array',
            
$this->getValue($attribute) instanceof UploadedFile,
            
$this->getValue($attribute) instanceof File => 'file',
            default => 
'string',
        };
    }

    
/**
     * Replace all error message place-holders with actual values.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array  $parameters
     * @return string
     */
    
public function makeReplacements($message$attribute$rule$parameters)
    {
        
$message $this->replaceAttributePlaceholder(
            
$message$this->getDisplayableAttribute($attribute)
        );

        
$message $this->replaceInputPlaceholder($message$attribute);
        
$message $this->replaceIndexPlaceholder($message$attribute);
        
$message $this->replacePositionPlaceholder($message$attribute);

        if (isset(
$this->replacers[Str::snake($rule)])) {
            return 
$this->callReplacer($message$attributeStr::snake($rule), $parameters$this);
        } elseif (
method_exists($this$replacer "replace{$rule}")) {
            return 
$this->$replacer($message$attribute$rule$parameters);
        }

        return 
$message;
    }

    
/**
     * Get the displayable name of the attribute.
     *
     * @param  string  $attribute
     * @return string
     */
    
public function getDisplayableAttribute($attribute)
    {
        
$primaryAttribute $this->getPrimaryAttribute($attribute);

        
$expectedAttributes $attribute != $primaryAttribute
                    
? [$attribute$primaryAttribute] : [$attribute];

        foreach (
$expectedAttributes as $name) {
            
// The developer may dynamically specify the array of custom attributes on this
            // validator instance. If the attribute exists in this array it is used over
            // the other ways of pulling the attribute name for this given attributes.
            
if (isset($this->customAttributes[$name])) {
                return 
$this->customAttributes[$name];
            }

            
// We allow for a developer to specify language lines for any attribute in this
            // application, which allows flexibility for displaying a unique displayable
            // version of the attribute name instead of the name used in an HTTP POST.
            
if ($line $this->getAttributeFromTranslations($name)) {
                return 
$line;
            }
        }

        
// When no language line has been specified for the attribute and it is also
        // an implicit attribute we will display the raw attribute's name and not
        // modify it with any of these replacements before we display the name.
        
if (isset($this->implicitAttributes[$primaryAttribute])) {
            return (
$formatter $this->implicitAttributesFormatter)
                            ? 
$formatter($attribute)
                            : 
$attribute;
        }

        return 
str_replace('_'' 'Str::snake($attribute));
    }

    
/**
     * Get the given attribute from the attribute translations.
     *
     * @param  string  $name
     * @return string
     */
    
protected function getAttributeFromTranslations($name)
    {
        return 
Arr::get($this->translator->get('validation.attributes'), $name);
    }

    
/**
     * Replace the :attribute placeholder in the given message.
     *
     * @param  string  $message
     * @param  string  $value
     * @return string
     */
    
protected function replaceAttributePlaceholder($message$value)
    {
        return 
str_replace(
            [
':attribute'':ATTRIBUTE'':Attribute'],
            [
$valueStr::upper($value), Str::ucfirst($value)],
            
$message
        
);
    }

    
/**
     * Replace the :index placeholder in the given message.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @return string
     */
    
protected function replaceIndexPlaceholder($message$attribute)
    {
        return 
$this->replaceIndexOrPositionPlaceholder(
            
$message$attribute'index'
        
);
    }

    
/**
     * Replace the :position placeholder in the given message.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @return string
     */
    
protected function replacePositionPlaceholder($message$attribute)
    {
        return 
$this->replaceIndexOrPositionPlaceholder(
            
$message$attribute'position'fn ($segment) => $segment 1
        
);
    }

    
/**
     * Replace the :index or :position placeholder in the given message.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $placeholder
     * @param  Closure|null  $modifier
     * @return string
     */
    
protected function replaceIndexOrPositionPlaceholder($message$attribute$placeholder, ?Closure $modifier null)
    {
        
$segments explode('.'$attribute);

        
$modifier ??= fn ($value) => $value;

        
$numericIndex 1;

        foreach (
$segments as $segment) {
            if (
is_numeric($segment)) {
                if (
$numericIndex === 1) {
                    
$message str_ireplace(':'.$placeholder$modifier((int) $segment), $message);
                }

                
$message str_ireplace(
                    
':'.$this->numberToIndexOrPositionWord($numericIndex).'-'.$placeholder,
                    
$modifier((int) $segment),
                    
$message
                
);

                
$numericIndex++;
            }
        }

        return 
$message;
    }

    
/**
     * Get the word for a index or position segment.
     *
     * @param  int  $value
     * @return string
     */
    
protected function numberToIndexOrPositionWord(int $value)
    {
        return [
            
=> 'first',
            
=> 'second',
            
=> 'third',
            
=> 'fourth',
            
=> 'fifth',
            
=> 'sixth',
            
=> 'seventh',
            
=> 'eighth',
            
=> 'ninth',
            
10 => 'tenth',
        ][(int) 
$value] ?? 'other';
    }

    
/**
     * Replace the :input placeholder in the given message.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @return string
     */
    
protected function replaceInputPlaceholder($message$attribute)
    {
        
$actualValue $this->getValue($attribute);

        if (
is_scalar($actualValue) || is_null($actualValue)) {
            
$message str_replace(':input'$this->getDisplayableValue($attribute$actualValue), $message);
        }

        return 
$message;
    }

    
/**
     * Get the displayable name of the value.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return string
     */
    
public function getDisplayableValue($attribute$value)
    {
        if (isset(
$this->customValues[$attribute][$value])) {
            return 
$this->customValues[$attribute][$value];
        }

        if (
is_array($value)) {
            return 
'array';
        }

        
$key "validation.values.{$attribute}.{$value}";

        if ((
$line $this->translator->get($key)) !== $key) {
            return 
$line;
        }

        if (
is_bool($value)) {
            return 
$value 'true' 'false';
        }

        if (
is_null($value)) {
            return 
'empty';
        }

        return (string) 
$value;
    }

    
/**
     * Transform an array of attributes to their displayable form.
     *
     * @param  array  $values
     * @return array
     */
    
protected function getAttributeList(array $values)
    {
        
$attributes = [];

        
// For each attribute in the list we will simply get its displayable form as
        // this is convenient when replacing lists of parameters like some of the
        // replacement functions do when formatting out the validation message.
        
foreach ($values as $key => $value) {
            
$attributes[$key] = $this->getDisplayableAttribute($value);
        }

        return 
$attributes;
    }

    
/**
     * Call a custom validator message replacer.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array  $parameters
     * @param  IlluminateValidationValidator  $validator
     * @return string|null
     */
    
protected function callReplacer($message$attribute$rule$parameters$validator)
    {
        
$callback $this->replacers[$rule];

        if (
$callback instanceof Closure) {
            return 
$callback(...func_get_args());
        } elseif (
is_string($callback)) {
            return 
$this->callClassBasedReplacer($callback$message$attribute$rule$parameters$validator);
        }
    }

    
/**
     * Call a class based validator message replacer.
     *
     * @param  string  $callback
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array  $parameters
     * @param  IlluminateValidationValidator  $validator
     * @return string
     */
    
protected function callClassBasedReplacer($callback$message$attribute$rule$parameters$validator)
    {
        [
$class$method] = Str::parseCallback($callback'replace');

        return 
$this->container->make($class)->{$method}(...array_slice(func_get_args(), 1));
    }
}
Онлайн: 0
Реклама