File: /storage/v6964/2foodfactor/public_html/wp-content/plugins/site-reviews/plugin/Modules/Validator.php
<?php
namespace GeminiLabs\SiteReviews\Modules;
use GeminiLabs\SiteReviews\Defaults\ValidationStringsDefaults;
use GeminiLabs\SiteReviews\Helper;
use GeminiLabs\SiteReviews\Helpers\Arr;
use GeminiLabs\SiteReviews\Helpers\Str;
use GeminiLabs\SiteReviews\Modules\Validator\ValidationRules;
/**
* @see \Illuminate\Validation\Validator (5.3)
*/
class Validator
{
use ValidationRules;
/**
* @var array
*/
public $errors = [];
/**
* The data under validation.
*
* @var array
*/
protected $data = [];
/**
* The failed validation rules.
*
* @var array
*/
protected $failedRules = [];
/**
* The rules to be applied to the data.
*
* @var array
*/
protected $rules = [];
/**
* The size related validation rules.
*
* @var array
*/
protected $sizeRules = [
'Between', 'Max', 'Min',
];
/**
* The validation rules that imply the field is required.
*
* @var array
*/
protected $implicitRules = [
'Required',
];
/**
* The numeric related validation rules.
*
* @var array
*/
protected $numericRules = [
'Number',
];
/**
* Run the validator's rules against its data.
*
* @throws \BadMethodCallException
*/
public function validate(array $data, array $rules = []): array
{
$this->data = $data;
$this->setRules($rules);
foreach ($this->rules as $attribute => $rules) {
foreach ($rules as $rule) {
$this->validateAttribute($attribute, $rule);
if ($this->shouldStopValidating($attribute)) {
break;
}
}
}
return $this->errors;
}
/**
* Validate a given attribute against a rule.
*
* @throws \BadMethodCallException
*/
public function validateAttribute(string $attribute, string $rule): void
{
[$rule, $parameters] = $this->parseRule($rule);
if ('' === $rule) {
return;
}
$value = $this->getValue($attribute);
$method = Helper::buildMethodName('validate', $rule);
if (!method_exists($this, $method)) {
throw new \BadMethodCallException("Method [$method] does not exist.");
}
if (!$this->$method($value, $attribute, $parameters)) {
$this->addFailure($attribute, $rule, $parameters);
}
}
/**
* Add an error message to the validator's collection of errors.
*/
protected function addError(string $attribute, string $rule, array $parameters): void
{
$message = $this->getMessage($attribute, $rule, $parameters);
$this->errors[$attribute][] = $message;
}
/**
* Add a failed rule and error message to the collection.
*/
protected function addFailure(string $attribute, string $rule, array $parameters): void
{
$this->addError($attribute, $rule, $parameters);
$this->failedRules[$attribute][$rule] = $parameters;
}
/**
* Get the data type of the given attribute.
*/
protected function getAttributeType(string $attribute): string
{
$type = $this->hasRule($attribute, $this->numericRules) ? '' : 'length';
return glsr()->filterString("validation/type/{$attribute}", $type, $attribute);
}
/**
* Get the validation message for an attribute and rule.
*/
protected function getMessage(string $attribute, string $rule, array $parameters): ?string
{
if (in_array($rule, $this->sizeRules)) {
return $this->getSizeMessage($attribute, $rule, $parameters);
}
$lowerRule = Str::snakeCase($rule);
return $this->translator($lowerRule, $parameters);
}
/**
* Get a rule and its parameters for a given attribute.
*/
protected function getRule(string $attribute, array $rules): ?array
{
if (!array_key_exists($attribute, $this->rules)) {
return null;
}
$rules = (array) $rules;
foreach ($this->rules[$attribute] as $rule) {
[$rule, $parameters] = $this->parseRule($rule);
if (in_array($rule, $rules)) {
return [$rule, $parameters];
}
}
return null;
}
/**
* Get the size of an attribute.
*
* @param mixed $value
*/
protected function getSize(string $attribute, $value): int
{
$hasNumeric = $this->hasRule($attribute, $this->numericRules);
if (is_numeric($value) && $hasNumeric) {
return (int) $value;
}
if (is_array($value)) {
return count($value);
}
if (is_array($json = json_decode($value))) {
return count($json);
}
return mb_strlen((string) $value);
}
/**
* Get the proper error message for an attribute and size rule.
*/
protected function getSizeMessage(string $attribute, string $rule, array $parameters): string
{
$type = $this->getAttributeType($attribute);
$lowerRule = Str::snakeCase($rule.$type);
return $this->translator($lowerRule, $parameters);
}
/**
* Get the value of a given attribute.
*
* @return mixed
*/
protected function getValue(string $attribute)
{
return $this->data[$attribute] ?? '';
}
/**
* Determine if the given attribute has a rule in the given set.
*/
protected function hasRule(string $attribute, array $rules): bool
{
return !is_null($this->getRule($attribute, $rules));
}
/**
* Parse a parameter list.
*/
protected function parseParameters(string $rule, string $parameter): array
{
return 'regex' === strtolower($rule)
? [$parameter]
: str_getcsv($parameter);
}
/**
* Extract the rule name and parameters from a rule.
*/
protected function parseRule(string $rule): array
{
$parameters = [];
if (str_contains($rule, ':')) {
[$rule, $parameter] = explode(':', $rule, 2);
$parameters = $this->parseParameters($rule, $parameter);
}
$rule = Str::camelCase($rule);
return [$rule, $parameters];
}
/**
* Set the validation rules.
*/
protected function setRules(array $rules): void
{
foreach ($rules as $key => $rule) {
$validationRules = is_string($rule) ? explode('|', $rule) : $rule;
$validationRules = array_filter(Arr::consolidate($validationRules));
// unset rules if the attribute is not required and the value is an empty string
if (empty(array_intersect(['accepted', 'required'], $validationRules)) && '' === $this->getValue($key)) {
$validationRules = [];
}
$rules[$key] = $validationRules;
}
$this->rules = $rules;
}
/**
* Check if we should stop further validations on a given attribute.
*/
protected function shouldStopValidating(string $attribute): bool
{
return $this->hasRule($attribute, $this->implicitRules)
&& isset($this->failedRules[$attribute])
&& array_intersect(array_keys($this->failedRules[$attribute]), $this->implicitRules);
}
/**
* Returns a translated message for the attribute.
*/
protected function translator($key, array $parameters): string
{
$strings = glsr(ValidationStringsDefaults::class)->defaults();
$string = $strings[$key] ?? 'error';
return $this->replace($string, $parameters);
}
}