<?php
namespace Illuminate\Validation;
use Closure;
use Illuminate\Contracts\Validation\InvokableRule;
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)) {
return explode('|', $rule);
}
if (is_object($rule)) {
return Arr::wrap($this->prepareRule($rule, $attribute));
}
return array_map(
[$this, 'prepareRule'],
$rule,
array_fill((int) 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 ($rule instanceof InvokableRule) {
$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 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 ((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();
}
}
If you encounter any issues or need assistance, please reach out to our dedicated developer support team Contact Us
Thank you for choosing Kueue Pay Payment Gateway Solutions! We look forward to seeing your integration thrive and provide a seamless payment experience for your valued customers.