Primo Committ

This commit is contained in:
paoloar77
2024-05-07 12:17:25 +02:00
commit e73d0e5113
7204 changed files with 884387 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
<?php
namespace Illuminate\Validation;
use Illuminate\Contracts\Validation\Rule as RuleContract;
class ClosureValidationRule implements RuleContract
{
/**
* The callback that validates the attribute.
*
* @var \Closure
*/
public $callback;
/**
* Indicates if the validation callback failed.
*
* @var bool
*/
public $failed = false;
/**
* The validation error message.
*
* @var string|null
*/
public $message;
/**
* Create a new Closure based validation rule.
*
* @param \Closure $callback
* @return void
*/
public function __construct($callback)
{
$this->callback = $callback;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$this->failed = false;
$this->callback->__invoke($attribute, $value, function ($message) {
$this->failed = true;
$this->message = $message;
});
return ! $this->failed;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return $this->message;
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Illuminate\Validation\Concerns;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Validation\EmailValidation;
class FilterEmailValidation implements EmailValidation
{
/**
* The flags to pass to the filter_var function.
*
* @var int|null
*/
protected $flags;
/**
* Create a new validation instance.
*
* @param int $flags
* @return void
*/
public function __construct($flags = null)
{
$this->flags = $flags;
}
/**
* Create a new instance which allows any unicode characters in local-part.
*
* @return static
*/
public static function unicode()
{
return new static(FILTER_FLAG_EMAIL_UNICODE);
}
/**
* Returns true if the given email is valid.
*
* @param string $email
* @param \Egulias\EmailValidator\EmailLexer $emailLexer
* @return bool
*/
public function isValid($email, EmailLexer $emailLexer)
{
return is_null($this->flags)
? filter_var($email, FILTER_VALIDATE_EMAIL) !== false
: filter_var($email, FILTER_VALIDATE_EMAIL, $this->flags) !== false;
}
/**
* Returns the validation error.
*
* @return \Egulias\EmailValidator\Exception\InvalidEmail|null
*/
public function getError()
{
//
}
/**
* Returns the validation warnings.
*
* @return \Egulias\EmailValidator\Warning\Warning[]
*/
public function getWarnings()
{
return [];
}
}

View File

@@ -0,0 +1,400 @@
<?php
namespace Illuminate\Validation\Concerns;
use Closure;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\File\UploadedFile;
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)
{
$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);
$customMessage = $this->getCustomMessageFromTranslator(
$customKey = "validation.custom.{$attribute}.{$lowerRule}"
);
// 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($attribute, $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($attribute, Str::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];
// 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 (strpos($sourceKey, '*') !== false) {
$pattern = str_replace('\*', '([^.]*)', preg_quote($sourceKey, '#'));
if (preg_match('#^'.$pattern.'\z#u', $key) === 1) {
return $source[$sourceKey];
}
continue;
}
if (Str::is($sourceKey, $key)) {
return $source[$sourceKey];
}
}
}
}
/**
* Get the custom error message from translator.
*
* @param string $key
* @return string
*/
protected function getCustomMessageFromTranslator($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
);
return $this->getWildcardCustomMessages(Arr::dot(
(array) $this->translator->get('validation.custom')
), $shortKey, $key);
}
/**
* 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.
if ($this->hasRule($attribute, $this->numericRules)) {
return 'numeric';
} elseif ($this->hasRule($attribute, ['Array'])) {
return 'array';
} elseif ($this->getValue($attribute) instanceof UploadedFile) {
return 'file';
}
return '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);
if (isset($this->replacers[Str::snake($rule)])) {
return $this->callReplacer($message, $attribute, Str::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'],
[$value, Str::upper($value), Str::ucfirst($value)],
$message
);
}
/**
* 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];
}
$key = "validation.values.{$attribute}.{$value}";
if (($line = $this->translator->get($key)) !== $key) {
return $line;
}
if (is_bool($value)) {
return $value ? 'true' : 'false';
}
return $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 \Illuminate\Validation\Validator $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 \Illuminate\Validation\Validator $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));
}
}

View File

@@ -0,0 +1,508 @@
<?php
namespace Illuminate\Validation\Concerns;
use Illuminate\Support\Arr;
trait ReplacesAttributes
{
/**
* Replace all place-holders for the between rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceBetween($message, $attribute, $rule, $parameters)
{
return str_replace([':min', ':max'], $parameters, $message);
}
/**
* Replace all place-holders for the date_format rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDateFormat($message, $attribute, $rule, $parameters)
{
return str_replace(':format', $parameters[0], $message);
}
/**
* Replace all place-holders for the different rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDifferent($message, $attribute, $rule, $parameters)
{
return $this->replaceSame($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the digits rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDigits($message, $attribute, $rule, $parameters)
{
return str_replace(':digits', $parameters[0], $message);
}
/**
* Replace all place-holders for the digits (between) rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDigitsBetween($message, $attribute, $rule, $parameters)
{
return $this->replaceBetween($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the min rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceMin($message, $attribute, $rule, $parameters)
{
return str_replace(':min', $parameters[0], $message);
}
/**
* Replace all place-holders for the max rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceMax($message, $attribute, $rule, $parameters)
{
return str_replace(':max', $parameters[0], $message);
}
/**
* Replace all place-holders for the in rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceIn($message, $attribute, $rule, $parameters)
{
foreach ($parameters as &$parameter) {
$parameter = $this->getDisplayableValue($attribute, $parameter);
}
return str_replace(':values', implode(', ', $parameters), $message);
}
/**
* Replace all place-holders for the not_in rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceNotIn($message, $attribute, $rule, $parameters)
{
return $this->replaceIn($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the in_array rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceInArray($message, $attribute, $rule, $parameters)
{
return str_replace(':other', $this->getDisplayableAttribute($parameters[0]), $message);
}
/**
* Replace all place-holders for the mimetypes rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceMimetypes($message, $attribute, $rule, $parameters)
{
return str_replace(':values', implode(', ', $parameters), $message);
}
/**
* Replace all place-holders for the mimes rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceMimes($message, $attribute, $rule, $parameters)
{
return str_replace(':values', implode(', ', $parameters), $message);
}
/**
* Replace all place-holders for the required_with rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredWith($message, $attribute, $rule, $parameters)
{
return str_replace(':values', implode(' / ', $this->getAttributeList($parameters)), $message);
}
/**
* Replace all place-holders for the required_with_all rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredWithAll($message, $attribute, $rule, $parameters)
{
return $this->replaceRequiredWith($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the required_without rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredWithout($message, $attribute, $rule, $parameters)
{
return $this->replaceRequiredWith($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the required_without_all rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredWithoutAll($message, $attribute, $rule, $parameters)
{
return $this->replaceRequiredWith($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the size rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceSize($message, $attribute, $rule, $parameters)
{
return str_replace(':size', $parameters[0], $message);
}
/**
* Replace all place-holders for the gt rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceGt($message, $attribute, $rule, $parameters)
{
if (is_null($value = $this->getValue($parameters[0]))) {
return str_replace(':value', $this->getDisplayableAttribute($parameters[0]), $message);
}
return str_replace(':value', $this->getSize($attribute, $value), $message);
}
/**
* Replace all place-holders for the lt rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceLt($message, $attribute, $rule, $parameters)
{
if (is_null($value = $this->getValue($parameters[0]))) {
return str_replace(':value', $this->getDisplayableAttribute($parameters[0]), $message);
}
return str_replace(':value', $this->getSize($attribute, $value), $message);
}
/**
* Replace all place-holders for the gte rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceGte($message, $attribute, $rule, $parameters)
{
if (is_null($value = $this->getValue($parameters[0]))) {
return str_replace(':value', $this->getDisplayableAttribute($parameters[0]), $message);
}
return str_replace(':value', $this->getSize($attribute, $value), $message);
}
/**
* Replace all place-holders for the lte rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceLte($message, $attribute, $rule, $parameters)
{
if (is_null($value = $this->getValue($parameters[0]))) {
return str_replace(':value', $this->getDisplayableAttribute($parameters[0]), $message);
}
return str_replace(':value', $this->getSize($attribute, $value), $message);
}
/**
* Replace all place-holders for the required_if rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredIf($message, $attribute, $rule, $parameters)
{
$parameters[1] = $this->getDisplayableValue($parameters[0], Arr::get($this->data, $parameters[0]));
$parameters[0] = $this->getDisplayableAttribute($parameters[0]);
return str_replace([':other', ':value'], $parameters, $message);
}
/**
* Replace all place-holders for the required_unless rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceRequiredUnless($message, $attribute, $rule, $parameters)
{
$other = $this->getDisplayableAttribute($parameters[0]);
$values = [];
foreach (array_slice($parameters, 1) as $value) {
$values[] = $this->getDisplayableValue($parameters[0], $value);
}
return str_replace([':other', ':values'], [$other, implode(', ', $values)], $message);
}
/**
* Replace all place-holders for the same rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceSame($message, $attribute, $rule, $parameters)
{
return str_replace(':other', $this->getDisplayableAttribute($parameters[0]), $message);
}
/**
* Replace all place-holders for the before rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceBefore($message, $attribute, $rule, $parameters)
{
if (! strtotime($parameters[0])) {
return str_replace(':date', $this->getDisplayableAttribute($parameters[0]), $message);
}
return str_replace(':date', $this->getDisplayableValue($attribute, $parameters[0]), $message);
}
/**
* Replace all place-holders for the before_or_equal rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceBeforeOrEqual($message, $attribute, $rule, $parameters)
{
return $this->replaceBefore($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the after rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceAfter($message, $attribute, $rule, $parameters)
{
return $this->replaceBefore($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the after_or_equal rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceAfterOrEqual($message, $attribute, $rule, $parameters)
{
return $this->replaceBefore($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the date_equals rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDateEquals($message, $attribute, $rule, $parameters)
{
return $this->replaceBefore($message, $attribute, $rule, $parameters);
}
/**
* Replace all place-holders for the dimensions rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceDimensions($message, $attribute, $rule, $parameters)
{
$parameters = $this->parseNamedParameters($parameters);
if (is_array($parameters)) {
foreach ($parameters as $key => $value) {
$message = str_replace(':'.$key, $value, $message);
}
}
return $message;
}
/**
* Replace all place-holders for the ends_with rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceEndsWith($message, $attribute, $rule, $parameters)
{
foreach ($parameters as &$parameter) {
$parameter = $this->getDisplayableValue($attribute, $parameter);
}
return str_replace(':values', implode(', ', $parameters), $message);
}
/**
* Replace all place-holders for the starts_with rule.
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
protected function replaceStartsWith($message, $attribute, $rule, $parameters)
{
foreach ($parameters as &$parameter) {
$parameter = $this->getDisplayableValue($attribute, $parameter);
}
return str_replace(':values', implode(', ', $parameters), $message);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
<?php
namespace Illuminate\Validation;
use Closure;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Support\Str;
class DatabasePresenceVerifier implements DatabasePresenceVerifierInterface
{
/**
* The database connection instance.
*
* @var \Illuminate\Database\ConnectionResolverInterface
*/
protected $db;
/**
* The database connection to use.
*
* @var string
*/
protected $connection;
/**
* Create a new database presence verifier.
*
* @param \Illuminate\Database\ConnectionResolverInterface $db
* @return void
*/
public function __construct(ConnectionResolverInterface $db)
{
$this->db = $db;
}
/**
* Count the number of objects in a collection having the given value.
*
* @param string $collection
* @param string $column
* @param string $value
* @param int|null $excludeId
* @param string|null $idColumn
* @param array $extra
* @return int
*/
public function getCount($collection, $column, $value, $excludeId = null, $idColumn = null, array $extra = [])
{
$query = $this->table($collection)->where($column, '=', $value);
if (! is_null($excludeId) && $excludeId !== 'NULL') {
$query->where($idColumn ?: 'id', '<>', $excludeId);
}
return $this->addConditions($query, $extra)->count();
}
/**
* Count the number of objects in a collection with the given values.
*
* @param string $collection
* @param string $column
* @param array $values
* @param array $extra
* @return int
*/
public function getMultiCount($collection, $column, array $values, array $extra = [])
{
$query = $this->table($collection)->whereIn($column, $values);
return $this->addConditions($query, $extra)->distinct()->count($column);
}
/**
* Add the given conditions to the query.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $conditions
* @return \Illuminate\Database\Query\Builder
*/
protected function addConditions($query, $conditions)
{
foreach ($conditions as $key => $value) {
if ($value instanceof Closure) {
$query->where(function ($query) use ($value) {
$value($query);
});
} else {
$this->addWhere($query, $key, $value);
}
}
return $query;
}
/**
* Add a "where" clause to the given query.
*
* @param \Illuminate\Database\Query\Builder $query
* @param string $key
* @param string $extraValue
* @return void
*/
protected function addWhere($query, $key, $extraValue)
{
if ($extraValue === 'NULL') {
$query->whereNull($key);
} elseif ($extraValue === 'NOT_NULL') {
$query->whereNotNull($key);
} elseif (Str::startsWith($extraValue, '!')) {
$query->where($key, '!=', mb_substr($extraValue, 1));
} else {
$query->where($key, $extraValue);
}
}
/**
* Get a query builder for the given table.
*
* @param string $table
* @return \Illuminate\Database\Query\Builder
*/
protected function table($table)
{
return $this->db->connection($this->connection)->table($table)->useWritePdo();
}
/**
* Set the connection to be used.
*
* @param string $connection
* @return void
*/
public function setConnection($connection)
{
$this->connection = $connection;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Illuminate\Validation;
interface DatabasePresenceVerifierInterface extends PresenceVerifierInterface
{
/**
* Set the connection to be used.
*
* @param string $connection
* @return void
*/
public function setConnection($connection);
}

View File

@@ -0,0 +1,283 @@
<?php
namespace Illuminate\Validation;
use Closure;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Translation\Translator;
use Illuminate\Contracts\Validation\Factory as FactoryContract;
use Illuminate\Support\Str;
class Factory implements FactoryContract
{
/**
* The Translator implementation.
*
* @var \Illuminate\Contracts\Translation\Translator
*/
protected $translator;
/**
* The Presence Verifier implementation.
*
* @var \Illuminate\Validation\PresenceVerifierInterface
*/
protected $verifier;
/**
* The IoC container instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;
/**
* All of the custom validator extensions.
*
* @var array
*/
protected $extensions = [];
/**
* All of the custom implicit validator extensions.
*
* @var array
*/
protected $implicitExtensions = [];
/**
* All of the custom dependent validator extensions.
*
* @var array
*/
protected $dependentExtensions = [];
/**
* All of the custom validator message replacers.
*
* @var array
*/
protected $replacers = [];
/**
* All of the fallback messages for custom rules.
*
* @var array
*/
protected $fallbackMessages = [];
/**
* The Validator resolver instance.
*
* @var \Closure
*/
protected $resolver;
/**
* Create a new Validator factory instance.
*
* @param \Illuminate\Contracts\Translation\Translator $translator
* @param \Illuminate\Contracts\Container\Container|null $container
* @return void
*/
public function __construct(Translator $translator, Container $container = null)
{
$this->container = $container;
$this->translator = $translator;
}
/**
* Create a new Validator instance.
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return \Illuminate\Validation\Validator
*/
public function make(array $data, array $rules, array $messages = [], array $customAttributes = [])
{
$validator = $this->resolve(
$data, $rules, $messages, $customAttributes
);
// The presence verifier is responsible for checking the unique and exists data
// for the validator. It is behind an interface so that multiple versions of
// it may be written besides database. We'll inject it into the validator.
if (! is_null($this->verifier)) {
$validator->setPresenceVerifier($this->verifier);
}
// Next we'll set the IoC container instance of the validator, which is used to
// resolve out class based validator extensions. If it is not set then these
// types of extensions will not be possible on these validation instances.
if (! is_null($this->container)) {
$validator->setContainer($this->container);
}
$this->addExtensions($validator);
return $validator;
}
/**
* Validate the given data against the provided rules.
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return array
*
* @throws \Illuminate\Validation\ValidationException
*/
public function validate(array $data, array $rules, array $messages = [], array $customAttributes = [])
{
return $this->make($data, $rules, $messages, $customAttributes)->validate();
}
/**
* Resolve a new Validator instance.
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return \Illuminate\Validation\Validator
*/
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
{
if (is_null($this->resolver)) {
return new Validator($this->translator, $data, $rules, $messages, $customAttributes);
}
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
}
/**
* Add the extensions to a validator instance.
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*/
protected function addExtensions(Validator $validator)
{
$validator->addExtensions($this->extensions);
// Next, we will add the implicit extensions, which are similar to the required
// and accepted rule in that they are run even if the attributes is not in a
// array of data that is given to a validator instances via instantiation.
$validator->addImplicitExtensions($this->implicitExtensions);
$validator->addDependentExtensions($this->dependentExtensions);
$validator->addReplacers($this->replacers);
$validator->setFallbackMessages($this->fallbackMessages);
}
/**
* Register a custom validator extension.
*
* @param string $rule
* @param \Closure|string $extension
* @param string|null $message
* @return void
*/
public function extend($rule, $extension, $message = null)
{
$this->extensions[$rule] = $extension;
if ($message) {
$this->fallbackMessages[Str::snake($rule)] = $message;
}
}
/**
* Register a custom implicit validator extension.
*
* @param string $rule
* @param \Closure|string $extension
* @param string|null $message
* @return void
*/
public function extendImplicit($rule, $extension, $message = null)
{
$this->implicitExtensions[$rule] = $extension;
if ($message) {
$this->fallbackMessages[Str::snake($rule)] = $message;
}
}
/**
* Register a custom dependent validator extension.
*
* @param string $rule
* @param \Closure|string $extension
* @param string|null $message
* @return void
*/
public function extendDependent($rule, $extension, $message = null)
{
$this->dependentExtensions[$rule] = $extension;
if ($message) {
$this->fallbackMessages[Str::snake($rule)] = $message;
}
}
/**
* Register a custom validator message replacer.
*
* @param string $rule
* @param \Closure|string $replacer
* @return void
*/
public function replacer($rule, $replacer)
{
$this->replacers[$rule] = $replacer;
}
/**
* Set the Validator instance resolver.
*
* @param \Closure $resolver
* @return void
*/
public function resolver(Closure $resolver)
{
$this->resolver = $resolver;
}
/**
* Get the Translator implementation.
*
* @return \Illuminate\Contracts\Translation\Translator
*/
public function getTranslator()
{
return $this->translator;
}
/**
* Get the Presence Verifier implementation.
*
* @return \Illuminate\Validation\PresenceVerifierInterface
*/
public function getPresenceVerifier()
{
return $this->verifier;
}
/**
* Set the Presence Verifier implementation.
*
* @param \Illuminate\Validation\PresenceVerifierInterface $presenceVerifier
* @return void
*/
public function setPresenceVerifier(PresenceVerifierInterface $presenceVerifier)
{
$this->verifier = $presenceVerifier;
}
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,30 @@
<?php
namespace Illuminate\Validation;
interface PresenceVerifierInterface
{
/**
* Count the number of objects in a collection having the given value.
*
* @param string $collection
* @param string $column
* @param string $value
* @param int|null $excludeId
* @param string|null $idColumn
* @param array $extra
* @return int
*/
public function getCount($collection, $column, $value, $excludeId = null, $idColumn = null, array $extra = []);
/**
* Count the number of objects in a collection with the given values.
*
* @param string $collection
* @param string $column
* @param array $values
* @param array $extra
* @return int
*/
public function getMultiCount($collection, $column, array $values, array $extra = []);
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Illuminate\Validation;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Validation\Rules\Dimensions;
use Illuminate\Validation\Rules\Exists;
use Illuminate\Validation\Rules\In;
use Illuminate\Validation\Rules\NotIn;
use Illuminate\Validation\Rules\RequiredIf;
use Illuminate\Validation\Rules\Unique;
class Rule
{
use Macroable;
/**
* Get a dimensions constraint builder instance.
*
* @param array $constraints
* @return \Illuminate\Validation\Rules\Dimensions
*/
public static function dimensions(array $constraints = [])
{
return new Dimensions($constraints);
}
/**
* Get an exists constraint builder instance.
*
* @param string $table
* @param string $column
* @return \Illuminate\Validation\Rules\Exists
*/
public static function exists($table, $column = 'NULL')
{
return new Exists($table, $column);
}
/**
* Get an in constraint builder instance.
*
* @param \Illuminate\Contracts\Support\Arrayable|array|string $values
* @return \Illuminate\Validation\Rules\In
*/
public static function in($values)
{
if ($values instanceof Arrayable) {
$values = $values->toArray();
}
return new In(is_array($values) ? $values : func_get_args());
}
/**
* Get a not_in constraint builder instance.
*
* @param \Illuminate\Contracts\Support\Arrayable|array|string $values
* @return \Illuminate\Validation\Rules\NotIn
*/
public static function notIn($values)
{
if ($values instanceof Arrayable) {
$values = $values->toArray();
}
return new NotIn(is_array($values) ? $values : func_get_args());
}
/**
* Get a required_if constraint builder instance.
*
* @param callable|bool $callback
* @return \Illuminate\Validation\Rules\RequiredIf
*/
public static function requiredIf($callback)
{
return new RequiredIf($callback);
}
/**
* Get a unique constraint builder instance.
*
* @param string $table
* @param string $column
* @return \Illuminate\Validation\Rules\Unique
*/
public static function unique($table, $column = 'NULL')
{
return new Unique($table, $column);
}
}

View File

@@ -0,0 +1,202 @@
<?php
namespace Illuminate\Validation\Rules;
use Closure;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
trait DatabaseRule
{
/**
* The table to run the query against.
*
* @var string
*/
protected $table;
/**
* The column to check on.
*
* @var string
*/
protected $column;
/**
* The extra where clauses for the query.
*
* @var array
*/
protected $wheres = [];
/**
* The array of custom query callbacks.
*
* @var array
*/
protected $using = [];
/**
* Create a new rule instance.
*
* @param string $table
* @param string $column
* @return void
*/
public function __construct($table, $column = 'NULL')
{
$this->column = $column;
$this->table = $this->resolveTableName($table);
}
/**
* Resolves the name of the table from the given string.
*
* @param string $table
* @return string
*/
public function resolveTableName($table)
{
if (! Str::contains($table, '\\') || ! class_exists($table)) {
return $table;
}
if (is_subclass_of($table, Model::class)) {
$model = new $table;
return implode('.', array_filter(
[$model->getConnectionName(), $model->getTable()]
));
}
return $table;
}
/**
* Set a "where" constraint on the query.
*
* @param \Closure|string $column
* @param array|string|null $value
* @return $this
*/
public function where($column, $value = null)
{
if (is_array($value)) {
return $this->whereIn($column, $value);
}
if ($column instanceof Closure) {
return $this->using($column);
}
if (is_null($value)) {
return $this->whereNull($column);
}
$this->wheres[] = compact('column', 'value');
return $this;
}
/**
* Set a "where not" constraint on the query.
*
* @param string $column
* @param array|string $value
* @return $this
*/
public function whereNot($column, $value)
{
if (is_array($value)) {
return $this->whereNotIn($column, $value);
}
return $this->where($column, '!'.$value);
}
/**
* Set a "where null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNull($column)
{
return $this->where($column, 'NULL');
}
/**
* Set a "where not null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNotNull($column)
{
return $this->where($column, 'NOT_NULL');
}
/**
* Set a "where in" constraint on the query.
*
* @param string $column
* @param array $values
* @return $this
*/
public function whereIn($column, array $values)
{
return $this->where(function ($query) use ($column, $values) {
$query->whereIn($column, $values);
});
}
/**
* Set a "where not in" constraint on the query.
*
* @param string $column
* @param array $values
* @return $this
*/
public function whereNotIn($column, array $values)
{
return $this->where(function ($query) use ($column, $values) {
$query->whereNotIn($column, $values);
});
}
/**
* Register a custom query callback.
*
* @param \Closure $callback
* @return $this
*/
public function using(Closure $callback)
{
$this->using[] = $callback;
return $this;
}
/**
* Get the custom query callbacks for the rule.
*
* @return array
*/
public function queryCallbacks()
{
return $this->using;
}
/**
* Format the where clauses.
*
* @return string
*/
protected function formatWheres()
{
return collect($this->wheres)->map(function ($where) {
return $where['column'].','.'"'.str_replace('"', '""', $where['value']).'"';
})->implode(',');
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace Illuminate\Validation\Rules;
class Dimensions
{
/**
* The constraints for the dimensions rule.
*
* @var array
*/
protected $constraints = [];
/**
* Create a new dimensions rule instance.
*
* @param array $constraints
* @return void
*/
public function __construct(array $constraints = [])
{
$this->constraints = $constraints;
}
/**
* Set the "width" constraint.
*
* @param int $value
* @return $this
*/
public function width($value)
{
$this->constraints['width'] = $value;
return $this;
}
/**
* Set the "height" constraint.
*
* @param int $value
* @return $this
*/
public function height($value)
{
$this->constraints['height'] = $value;
return $this;
}
/**
* Set the "min width" constraint.
*
* @param int $value
* @return $this
*/
public function minWidth($value)
{
$this->constraints['min_width'] = $value;
return $this;
}
/**
* Set the "min height" constraint.
*
* @param int $value
* @return $this
*/
public function minHeight($value)
{
$this->constraints['min_height'] = $value;
return $this;
}
/**
* Set the "max width" constraint.
*
* @param int $value
* @return $this
*/
public function maxWidth($value)
{
$this->constraints['max_width'] = $value;
return $this;
}
/**
* Set the "max height" constraint.
*
* @param int $value
* @return $this
*/
public function maxHeight($value)
{
$this->constraints['max_height'] = $value;
return $this;
}
/**
* Set the "ratio" constraint.
*
* @param float $value
* @return $this
*/
public function ratio($value)
{
$this->constraints['ratio'] = $value;
return $this;
}
/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
$result = '';
foreach ($this->constraints as $key => $value) {
$result .= "$key=$value,";
}
return 'dimensions:'.substr($result, 0, -1);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Illuminate\Validation\Rules;
class Exists
{
use DatabaseRule;
/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
return rtrim(sprintf('exists:%s,%s,%s',
$this->table,
$this->column,
$this->formatWheres()
), ',');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Illuminate\Validation\Rules;
class In
{
/**
* The name of the rule.
*/
protected $rule = 'in';
/**
* The accepted values.
*
* @var array
*/
protected $values;
/**
* Create a new in rule instance.
*
* @param array $values
* @return void
*/
public function __construct(array $values)
{
$this->values = $values;
}
/**
* Convert the rule to a validation string.
*
* @return string
*
* @see \Illuminate\Validation\ValidationRuleParser::parseParameters
*/
public function __toString()
{
$values = array_map(function ($value) {
return '"'.str_replace('"', '""', $value).'"';
}, $this->values);
return $this->rule.':'.implode(',', $values);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Illuminate\Validation\Rules;
class NotIn
{
/**
* The name of the rule.
*/
protected $rule = 'not_in';
/**
* The accepted values.
*
* @var array
*/
protected $values;
/**
* Create a new "not in" rule instance.
*
* @param array $values
* @return void
*/
public function __construct(array $values)
{
$this->values = $values;
}
/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
$values = array_map(function ($value) {
return '"'.str_replace('"', '""', $value).'"';
}, $this->values);
return $this->rule.':'.implode(',', $values);
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Illuminate\Validation\Rules;
class RequiredIf
{
/**
* The condition that validates the attribute.
*
* @var callable|bool
*/
public $condition;
/**
* Create a new required validation rule based on a condition.
*
* @param callable|bool $condition
* @return void
*/
public function __construct($condition)
{
$this->condition = $condition;
}
/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
if (is_callable($this->condition)) {
return call_user_func($this->condition) ? 'required' : '';
}
return $this->condition ? 'required' : '';
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Illuminate\Validation\Rules;
use Illuminate\Database\Eloquent\Model;
class Unique
{
use DatabaseRule;
/**
* The ID that should be ignored.
*
* @var mixed
*/
protected $ignore;
/**
* The name of the ID column.
*
* @var string
*/
protected $idColumn = 'id';
/**
* Ignore the given ID during the unique check.
*
* @param mixed $id
* @param string|null $idColumn
* @return $this
*/
public function ignore($id, $idColumn = null)
{
if ($id instanceof Model) {
return $this->ignoreModel($id, $idColumn);
}
$this->ignore = $id;
$this->idColumn = $idColumn ?? 'id';
return $this;
}
/**
* Ignore the given model during the unique check.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string|null $idColumn
* @return $this
*/
public function ignoreModel($model, $idColumn = null)
{
$this->idColumn = $idColumn ?? $model->getKeyName();
$this->ignore = $model->{$this->idColumn};
return $this;
}
/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
return rtrim(sprintf('unique:%s,%s,%s,%s,%s',
$this->table,
$this->column,
$this->ignore ? '"'.addslashes($this->ignore).'"' : 'NULL',
$this->idColumn,
$this->formatWheres()
), ',');
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Illuminate\Validation;
use RuntimeException;
class UnauthorizedException extends RuntimeException
{
//
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Illuminate\Validation;
/**
* Provides default implementation of ValidatesWhenResolved contract.
*/
trait ValidatesWhenResolvedTrait
{
/**
* Validate the class instance.
*
* @return void
*/
public function validateResolved()
{
$this->prepareForValidation();
if (! $this->passesAuthorization()) {
$this->failedAuthorization();
}
$instance = $this->getValidatorInstance();
if ($instance->fails()) {
$this->failedValidation($instance);
}
$this->passedValidation();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
//
}
/**
* Get the validator instance for the request.
*
* @return \Illuminate\Validation\Validator
*/
protected function getValidatorInstance()
{
return $this->validator();
}
/**
* Handle a passed validation attempt.
*
* @return void
*/
protected function passedValidation()
{
//
}
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
protected function failedValidation(Validator $validator)
{
throw new ValidationException($validator);
}
/**
* Determine if the request passes the authorization check.
*
* @return bool
*/
protected function passesAuthorization()
{
if (method_exists($this, 'authorize')) {
return $this->authorize();
}
return true;
}
/**
* Handle a failed authorization attempt.
*
* @return void
*
* @throws \Illuminate\Validation\UnauthorizedException
*/
protected function failedAuthorization()
{
throw new UnauthorizedException;
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace Illuminate\Validation;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class ValidationData
{
/**
* Initialize and gather data for given attribute.
*
* @param string $attribute
* @param array $masterData
* @return array
*/
public static function initializeAndGatherData($attribute, $masterData)
{
$data = Arr::dot(static::initializeAttributeOnData($attribute, $masterData));
return array_merge($data, static::extractValuesForWildcards(
$masterData, $data, $attribute
));
}
/**
* Gather a copy of the attribute data filled with any missing attributes.
*
* @param string $attribute
* @param array $masterData
* @return array
*/
protected static function initializeAttributeOnData($attribute, $masterData)
{
$explicitPath = static::getLeadingExplicitAttributePath($attribute);
$data = static::extractDataFromPath($explicitPath, $masterData);
if (! Str::contains($attribute, '*') || Str::endsWith($attribute, '*')) {
return $data;
}
return data_set($data, $attribute, null, true);
}
/**
* Get all of the exact attribute values for a given wildcard attribute.
*
* @param array $masterData
* @param array $data
* @param string $attribute
* @return array
*/
protected static function extractValuesForWildcards($masterData, $data, $attribute)
{
$keys = [];
$pattern = str_replace('\*', '[^\.]+', preg_quote($attribute));
foreach ($data as $key => $value) {
if ((bool) preg_match('/^'.$pattern.'/', $key, $matches)) {
$keys[] = $matches[0];
}
}
$keys = array_unique($keys);
$data = [];
foreach ($keys as $key) {
$data[$key] = Arr::get($masterData, $key);
}
return $data;
}
/**
* Extract data based on the given dot-notated path.
*
* Used to extract a sub-section of the data for faster iteration.
*
* @param string $attribute
* @param array $masterData
* @return array
*/
public static function extractDataFromPath($attribute, $masterData)
{
$results = [];
$value = Arr::get($masterData, $attribute, '__missing__');
if ($value !== '__missing__') {
Arr::set($results, $attribute, $value);
}
return $results;
}
/**
* Get the explicit part of the attribute name.
*
* E.g. 'foo.bar.*.baz' -> 'foo.bar'
*
* Allows us to not spin through all of the flattened data for some operations.
*
* @param string $attribute
* @return string
*/
public static function getLeadingExplicitAttributePath($attribute)
{
return rtrim(explode('*', $attribute)[0], '.') ?: null;
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace Illuminate\Validation;
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator as ValidatorFacade;
class ValidationException extends Exception
{
/**
* The validator instance.
*
* @var \Illuminate\Contracts\Validation\Validator
*/
public $validator;
/**
* The recommended response to send to the client.
*
* @var \Symfony\Component\HttpFoundation\Response|null
*/
public $response;
/**
* The status code to use for the response.
*
* @var int
*/
public $status = 422;
/**
* The name of the error bag.
*
* @var string
*/
public $errorBag;
/**
* The path the client should be redirected to.
*
* @var string
*/
public $redirectTo;
/**
* Create a new exception instance.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @param \Symfony\Component\HttpFoundation\Response|null $response
* @param string $errorBag
* @return void
*/
public function __construct($validator, $response = null, $errorBag = 'default')
{
parent::__construct('The given data was invalid.');
$this->response = $response;
$this->errorBag = $errorBag;
$this->validator = $validator;
}
/**
* Create a new validation exception from a plain array of messages.
*
* @param array $messages
* @return static
*/
public static function withMessages(array $messages)
{
return new static(tap(ValidatorFacade::make([], []), function ($validator) use ($messages) {
foreach ($messages as $key => $value) {
foreach (Arr::wrap($value) as $message) {
$validator->errors()->add($key, $message);
}
}
}));
}
/**
* Get all of the validation error messages.
*
* @return array
*/
public function errors()
{
return $this->validator->errors()->messages();
}
/**
* Set the HTTP status code to be used for the response.
*
* @param int $status
* @return $this
*/
public function status($status)
{
$this->status = $status;
return $this;
}
/**
* Set the error bag on the exception.
*
* @param string $errorBag
* @return $this
*/
public function errorBag($errorBag)
{
$this->errorBag = $errorBag;
return $this;
}
/**
* Set the URL to redirect to on a validation error.
*
* @param string $url
* @return $this
*/
public function redirectTo($url)
{
$this->redirectTo = $url;
return $this;
}
/**
* Get the underlying response instance.
*
* @return \Symfony\Component\HttpFoundation\Response|null
*/
public function getResponse()
{
return $this->response;
}
}

View File

@@ -0,0 +1,277 @@
<?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);
}
}
return $rules;
}
/**
* Explode the explicit rule into an array if necessary.
*
* @param mixed $rule
* @return array
*/
protected function explodeExplicitRule($rule)
{
if (is_string($rule)) {
return explode('|', $rule);
} elseif (is_object($rule)) {
return [$this->prepareRule($rule)];
}
return array_map([$this, 'prepareRule'], $rule);
}
/**
* Prepare the given rule for the Validator.
*
* @param mixed $rule
* @return mixed
*/
protected function prepareRule($rule)
{
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;
}
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) {
$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]) : [], $merge
);
return $results;
}
/**
* Extract the rule name and parameters from a rule.
*
* @param array|string $rules
* @return array
*/
public static function parse($rules)
{
if ($rules instanceof RuleContract) {
return [$rules, []];
}
if (is_array($rules)) {
$rules = static::parseArrayRule($rules);
} else {
$rules = static::parseStringRule($rules);
}
$rules[0] = static::normalizeRule($rules[0]);
return $rules;
}
/**
* Parse an array based rule.
*
* @param array $rules
* @return array
*/
protected static function parseArrayRule(array $rules)
{
return [Str::studly(trim(Arr::get($rules, 0))), array_slice($rules, 1)];
}
/**
* Parse a string based rule.
*
* @param string $rules
* @return array
*/
protected static function parseStringRule($rules)
{
$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 (strpos($rules, ':') !== false) {
[$rules, $parameter] = explode(':', $rules, 2);
$parameters = static::parseParameters($rules, $parameter);
}
return [Str::studly(trim($rules)), $parameters];
}
/**
* Parse a parameter list.
*
* @param string $rule
* @param string $parameter
* @return array
*/
protected static function parseParameters($rule, $parameter)
{
$rule = strtolower($rule);
if (in_array($rule, ['regex', 'not_regex', 'notregex'], true)) {
return [$parameter];
}
return str_getcsv($parameter);
}
/**
* Normalizes a rule so that we can accept short types.
*
* @param string $rule
* @return string
*/
protected static function normalizeRule($rule)
{
switch ($rule) {
case 'Int':
return 'Integer';
case 'Bool':
return 'Boolean';
default:
return $rule;
}
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Illuminate\Validation;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
class ValidationServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerPresenceVerifier();
$this->registerValidationFactory();
}
/**
* Register the validation factory.
*
* @return void
*/
protected function registerValidationFactory()
{
$this->app->singleton('validator', function ($app) {
$validator = new Factory($app['translator'], $app);
// The validation presence verifier is responsible for determining the existence of
// values in a given data collection which is typically a relational database or
// other persistent data stores. It is used to check for "uniqueness" as well.
if (isset($app['db'], $app['validation.presence'])) {
$validator->setPresenceVerifier($app['validation.presence']);
}
return $validator;
});
}
/**
* Register the database presence verifier.
*
* @return void
*/
protected function registerPresenceVerifier()
{
$this->app->singleton('validation.presence', function ($app) {
return new DatabasePresenceVerifier($app['db']);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [
'validator', 'validation.presence',
];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
{
"name": "illuminate/validation",
"description": "The Illuminate Validation package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": "^7.2.5|^8.0",
"ext-json": "*",
"egulias/email-validator": "^2.1.10",
"illuminate/container": "^7.0",
"illuminate/contracts": "^7.0",
"illuminate/support": "^7.0",
"illuminate/translation": "^7.0",
"symfony/http-foundation": "^5.0",
"symfony/mime": "^5.0"
},
"autoload": {
"psr-4": {
"Illuminate\\Validation\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"suggest": {
"illuminate/database": "Required to use the database presence verifier (^7.0)."
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}