Initial Commit

This commit is contained in:
David Stone
2024-11-30 18:24:12 -07:00
commit e8f7955c1c
5432 changed files with 1397750 additions and 0 deletions

View File

@ -0,0 +1,271 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class Attribute
{
/** @var array */
protected $rules = [];
/** @var string */
protected $key;
/** @var string|null */
protected $alias;
/** @var \Rakit\Validation\Validation */
protected $validation;
/** @var bool */
protected $required = \false;
/** @var \Rakit\Validation\Validation|null */
protected $primaryAttribute = null;
/** @var array */
protected $otherAttributes = [];
/** @var array */
protected $keyIndexes = [];
/**
* Constructor
*
* @param \Rakit\Validation\Validation $validation
* @param string $key
* @param string|null $alias
* @param array $rules
* @return void
*/
public function __construct(Validation $validation, string $key, $alias = null, array $rules = [])
{
$this->validation = $validation;
$this->alias = $alias;
$this->key = $key;
foreach ($rules as $rule) {
$this->addRule($rule);
}
}
/**
* Set the primary attribute
*
* @param \Rakit\Validation\Attribute $primaryAttribute
* @return void
*/
public function setPrimaryAttribute(Attribute $primaryAttribute)
{
$this->primaryAttribute = $primaryAttribute;
}
/**
* Set key indexes
*
* @param array $keyIndexes
* @return void
*/
public function setKeyIndexes(array $keyIndexes)
{
$this->keyIndexes = $keyIndexes;
}
/**
* Get primary attributes
*
* @return \Rakit\Validation\Attribute|null
*/
public function getPrimaryAttribute()
{
return $this->primaryAttribute;
}
/**
* Set other attributes
*
* @param array $otherAttributes
* @return void
*/
public function setOtherAttributes(array $otherAttributes)
{
$this->otherAttributes = [];
foreach ($otherAttributes as $otherAttribute) {
$this->addOtherAttribute($otherAttribute);
}
}
/**
* Add other attributes
*
* @param \Rakit\Validation\Attribute $otherAttribute
* @return void
*/
public function addOtherAttribute(Attribute $otherAttribute)
{
$this->otherAttributes[] = $otherAttribute;
}
/**
* Get other attributes
*
* @return array
*/
public function getOtherAttributes() : array
{
return $this->otherAttributes;
}
/**
* Add rule
*
* @param \Rakit\Validation\Rule $rule
* @return void
*/
public function addRule(Rule $rule)
{
$rule->setAttribute($this);
$rule->setValidation($this->validation);
$this->rules[$rule->getKey()] = $rule;
}
/**
* Get rule
*
* @param string $ruleKey
* @return void
*/
public function getRule(string $ruleKey)
{
return $this->hasRule($ruleKey) ? $this->rules[$ruleKey] : null;
}
/**
* Get rules
*
* @return array
*/
public function getRules() : array
{
return $this->rules;
}
/**
* Check the $ruleKey has in the rule
*
* @param string $ruleKey
* @return bool
*/
public function hasRule(string $ruleKey) : bool
{
return isset($this->rules[$ruleKey]);
}
/**
* Set required
*
* @param boolean $required
* @return void
*/
public function setRequired(bool $required)
{
$this->required = $required;
}
/**
* Set rule is required
*
* @return boolean
*/
public function isRequired() : bool
{
return $this->required;
}
/**
* Get key
*
* @return string
*/
public function getKey() : string
{
return $this->key;
}
/**
* Get key indexes
*
* @return array
*/
public function getKeyIndexes() : array
{
return $this->keyIndexes;
}
/**
* Get value
*
* @param string|null $key
* @return mixed
*/
public function getValue(string $key = null)
{
if ($key && $this->isArrayAttribute()) {
$key = $this->resolveSiblingKey($key);
}
if (!$key) {
$key = $this->getKey();
}
return $this->validation->getValue($key);
}
/**
* Get that is array attribute
*
* @return boolean
*/
public function isArrayAttribute() : bool
{
return \count($this->getKeyIndexes()) > 0;
}
/**
* Check this attribute is using dot notation
*
* @return boolean
*/
public function isUsingDotNotation() : bool
{
return \strpos($this->getKey(), '.') !== \false;
}
/**
* Resolve sibling key
*
* @param string $key
* @return string
*/
public function resolveSiblingKey(string $key) : string
{
$indexes = $this->getKeyIndexes();
$keys = \explode("*", $key);
$countAsterisks = \count($keys) - 1;
if (\count($indexes) < $countAsterisks) {
$indexes = \array_merge($indexes, \array_fill(0, $countAsterisks - \count($indexes), "*"));
}
$args = \array_merge([\str_replace("*", "%s", $key)], $indexes);
return \call_user_func_array('sprintf', $args);
}
/**
* Get humanize key
*
* @return string
*/
public function getHumanizedKey()
{
$primaryAttribute = $this->getPrimaryAttribute();
$key = \str_replace('_', ' ', $this->key);
// Resolve key from array validation
if ($primaryAttribute) {
$split = \explode('.', $key);
$key = \implode(' ', \array_map(function ($word) {
if (\is_numeric($word)) {
$word = $word + 1;
}
return Helper::snakeCase($word, ' ');
}, $split));
}
return \ucfirst($key);
}
/**
* Set alias
*
* @param string $alias
* @return void
*/
public function setAlias(string $alias)
{
$this->alias = $alias;
}
/**
* Get alias
*
* @return string|null
*/
public function getAlias()
{
return $this->alias;
}
}

View File

@ -0,0 +1,224 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class ErrorBag
{
/** @var array */
protected $messages = [];
/**
* Constructor
*
* @param array $messages
* @return void
*/
public function __construct(array $messages = [])
{
$this->messages = $messages;
}
/**
* Add message for given key and rule
*
* @param string $key
* @param string $rule
* @param string $message
* @return void
*/
public function add(string $key, string $rule, string $message)
{
if (!isset($this->messages[$key])) {
$this->messages[$key] = [];
}
$this->messages[$key][$rule] = $message;
}
/**
* Get messages count
*
* @return int
*/
public function count() : int
{
return \count($this->all());
}
/**
* Check given key is existed
*
* @param string $key
* @return bool
*/
public function has(string $key) : bool
{
list($key, $ruleName) = $this->parsekey($key);
if ($this->isWildcardKey($key)) {
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
return \count(Helper::arrayDot($messages)) > 0;
} else {
$messages = isset($this->messages[$key]) ? $this->messages[$key] : null;
if (!$ruleName) {
return !empty($messages);
} else {
return !empty($messages) and isset($messages[$ruleName]);
}
}
}
/**
* Get the first value of array
*
* @param string $key
* @return mixed
*/
public function first(string $key)
{
list($key, $ruleName) = $this->parsekey($key);
if ($this->isWildcardKey($key)) {
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
$flattenMessages = Helper::arrayDot($messages);
return \array_shift($flattenMessages);
} else {
$keyMessages = isset($this->messages[$key]) ? $this->messages[$key] : [];
if (empty($keyMessages)) {
return null;
}
if ($ruleName) {
return isset($keyMessages[$ruleName]) ? $keyMessages[$ruleName] : null;
} else {
return \array_shift($keyMessages);
}
}
}
/**
* Get messages from given key, can be use custom format
*
* @param string $key
* @param string $format
* @return array
*/
public function get(string $key, string $format = ':message') : array
{
list($key, $ruleName) = $this->parsekey($key);
$results = [];
if ($this->isWildcardKey($key)) {
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
foreach ($messages as $explicitKey => $keyMessages) {
foreach ($keyMessages as $rule => $message) {
$results[$explicitKey][$rule] = $this->formatMessage($message, $format);
}
}
} else {
$keyMessages = isset($this->messages[$key]) ? $this->messages[$key] : [];
foreach ($keyMessages as $rule => $message) {
if ($ruleName and $ruleName != $rule) {
continue;
}
$results[$rule] = $this->formatMessage($message, $format);
}
}
return $results;
}
/**
* Get all messages
*
* @param string $format
* @return array
*/
public function all(string $format = ':message') : array
{
$messages = $this->messages;
$results = [];
foreach ($messages as $key => $keyMessages) {
foreach ($keyMessages as $message) {
$results[] = $this->formatMessage($message, $format);
}
}
return $results;
}
/**
* Get the first message from existing keys
*
* @param string $format
* @param boolean $dotNotation
* @return array
*/
public function firstOfAll(string $format = ':message', bool $dotNotation = \false) : array
{
$messages = $this->messages;
$results = [];
foreach ($messages as $key => $keyMessages) {
if ($dotNotation) {
$results[$key] = $this->formatMessage(\array_shift($messages[$key]), $format);
} else {
Helper::arraySet($results, $key, $this->formatMessage(\array_shift($messages[$key]), $format));
}
}
return $results;
}
/**
* Get plain array messages
*
* @return array
*/
public function toArray() : array
{
return $this->messages;
}
/**
* Parse $key to get the array of $key and $ruleName
*
* @param string $key
* @return array
*/
protected function parseKey(string $key) : array
{
$expl = \explode(':', $key, 2);
$key = $expl[0];
$ruleName = isset($expl[1]) ? $expl[1] : null;
return [$key, $ruleName];
}
/**
* Check the $key is wildcard
*
* @param mixed $key
* @return bool
*/
protected function isWildcardKey(string $key) : bool
{
return \false !== \strpos($key, '*');
}
/**
* Filter messages with wildcard key
*
* @param string $key
* @param mixed $ruleName
* @return array
*/
protected function filterMessagesForWildcardKey(string $key, $ruleName = null) : array
{
$messages = $this->messages;
$pattern = \preg_quote($key, '#');
$pattern = \str_replace('\\*', '.*', $pattern);
$filteredMessages = [];
foreach ($messages as $k => $keyMessages) {
if ((bool) \preg_match('#^' . $pattern . '\\z#u', $k) === \false) {
continue;
}
foreach ($keyMessages as $rule => $message) {
if ($ruleName and $rule != $ruleName) {
continue;
}
$filteredMessages[$k][$rule] = $message;
}
}
return $filteredMessages;
}
/**
* Get formatted message
*
* @param string $message
* @param string $format
* @return string
*/
protected function formatMessage(string $message, string $format) : string
{
return \str_replace(':message', $message, $format);
}
}

View File

@ -0,0 +1,226 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class Helper
{
/**
* Determine if a given string matches a given pattern.
* Adapted from: https://github.com/illuminate/support/blob/v5.3.23/Str.php#L119
*
* @param string $pattern
* @param string $value
* @return bool
*/
public static function strIs(string $pattern, string $value) : bool
{
if ($pattern == $value) {
return \true;
}
$pattern = \preg_quote($pattern, '#');
// Asterisks are translated into zero-or-more regular expression wildcards
// to make it convenient to check if the strings starts with the given
// pattern such as "library/*", making any string check convenient.
$pattern = \str_replace('\\*', '.*', $pattern);
return (bool) \preg_match('#^' . $pattern . '\\z#u', $value);
}
/**
* Check if an item or items exist in an array using "dot" notation.
* Adapted from: https://github.com/illuminate/support/blob/v5.3.23/Arr.php#L81
*
* @param array $array
* @param string $key
* @return bool
*/
public static function arrayHas(array $array, string $key) : bool
{
if (\array_key_exists($key, $array)) {
return \true;
}
foreach (\explode('.', $key) as $segment) {
if (\is_array($array) && \array_key_exists($segment, $array)) {
$array = $array[$segment];
} else {
return \false;
}
}
return \true;
}
/**
* Get an item from an array using "dot" notation.
* Adapted from: https://github.com/illuminate/support/blob/v5.3.23/Arr.php#L246
*
* @param array $array
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public static function arrayGet(array $array, $key, $default = null)
{
if (\is_null($key)) {
return $array;
}
if (\array_key_exists($key, $array)) {
return $array[$key];
}
foreach (\explode('.', $key) as $segment) {
if (\is_array($array) && \array_key_exists($segment, $array)) {
$array = $array[$segment];
} else {
return $default;
}
}
return $array;
}
/**
* Flatten a multi-dimensional associative array with dots.
* Adapted from: https://github.com/illuminate/support/blob/v5.3.23/Arr.php#L81
*
* @param array $array
* @param string $prepend
* @return array
*/
public static function arrayDot(array $array, string $prepend = '') : array
{
$results = [];
foreach ($array as $key => $value) {
if (\is_array($value) && !empty($value)) {
$results = \array_merge($results, static::arrayDot($value, $prepend . $key . '.'));
} else {
$results[$prepend . $key] = $value;
}
}
return $results;
}
/**
* Set an item on an array or object using dot notation.
* Adapted from: https://github.com/illuminate/support/blob/v5.3.23/helpers.php#L437
*
* @param mixed $target
* @param string|array|null $key
* @param mixed $value
* @param bool $overwrite
* @return mixed
*/
public static function arraySet(&$target, $key, $value, $overwrite = \true) : array
{
if (\is_null($key)) {
if ($overwrite) {
return $target = \array_merge($target, $value);
}
return $target = \array_merge($value, $target);
}
$segments = \is_array($key) ? $key : \explode('.', $key);
if (($segment = \array_shift($segments)) === '*') {
if (!\is_array($target)) {
$target = [];
}
if ($segments) {
foreach ($target as &$inner) {
static::arraySet($inner, $segments, $value, $overwrite);
}
} elseif ($overwrite) {
foreach ($target as &$inner) {
$inner = $value;
}
}
} elseif (\is_array($target)) {
if ($segments) {
if (!\array_key_exists($segment, $target)) {
$target[$segment] = [];
}
static::arraySet($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite || !\array_key_exists($segment, $target)) {
$target[$segment] = $value;
}
} else {
$target = [];
if ($segments) {
static::arraySet($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite) {
$target[$segment] = $value;
}
}
return $target;
}
/**
* Unset an item on an array or object using dot notation.
*
* @param mixed $target
* @param string|array $key
* @return mixed
*/
public static function arrayUnset(&$target, $key)
{
if (!\is_array($target)) {
return $target;
}
$segments = \is_array($key) ? $key : \explode('.', $key);
$segment = \array_shift($segments);
if ($segment == '*') {
$target = [];
} elseif ($segments) {
if (\array_key_exists($segment, $target)) {
static::arrayUnset($target[$segment], $segments);
}
} elseif (\array_key_exists($segment, $target)) {
unset($target[$segment]);
}
return $target;
}
/**
* Get snake_case format from given string
*
* @param string $value
* @param string $delimiter
* @return string
*/
public static function snakeCase(string $value, string $delimiter = '_') : string
{
if (!\ctype_lower($value)) {
$value = \preg_replace('/\\s+/u', '', \ucwords($value));
$value = \strtolower(\preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
}
return $value;
}
/**
* Join string[] to string with given $separator and $lastSeparator.
*
* @param array $pieces
* @param string $separator
* @param string|null $lastSeparator
* @return string
*/
public static function join(array $pieces, string $separator, string $lastSeparator = null) : string
{
if (\is_null($lastSeparator)) {
$lastSeparator = $separator;
}
$last = \array_pop($pieces);
switch (\count($pieces)) {
case 0:
return $last ?: '';
case 1:
return $pieces[0] . $lastSeparator . $last;
default:
return \implode($separator, $pieces) . $lastSeparator . $last;
}
}
/**
* Wrap string[] by given $prefix and $suffix
*
* @param array $strings
* @param string $prefix
* @param string|null $suffix
* @return array
*/
public static function wraps(array $strings, string $prefix, string $suffix = null) : array
{
if (\is_null($suffix)) {
$suffix = $prefix;
}
return \array_map(function ($str) use($prefix, $suffix) {
return $prefix . $str . $suffix;
}, $strings);
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class MissingRequiredParameterException extends \Exception
{
}

View File

@ -0,0 +1,206 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
use WP_Ultimo\Dependencies\Rakit\Validation\MissingRequiredParameterException;
abstract class Rule
{
/** @var string */
protected $key;
/** @var \Rakit\Validation\Attribute|null */
protected $attribute;
/** @var \Rakit\Validation\Validation|null */
protected $validation;
/** @var bool */
protected $implicit = \false;
/** @var array */
protected $params = [];
/** @var array */
protected $paramsTexts = [];
/** @var array */
protected $fillableParams = [];
/** @var string */
protected $message = "The :attribute is invalid";
public abstract function check($value) : bool;
/**
* Set Validation class instance
*
* @param \Rakit\Validation\Validation $validation
* @return void
*/
public function setValidation(Validation $validation)
{
$this->validation = $validation;
}
/**
* Set key
*
* @param string $key
* @return void
*/
public function setKey(string $key)
{
$this->key = $key;
}
/**
* Get key
*
* @return string
*/
public function getKey()
{
return $this->key ?: \get_class($this);
}
/**
* Set attribute
*
* @param \Rakit\Validation\Attribute $attribute
* @return void
*/
public function setAttribute(Attribute $attribute)
{
$this->attribute = $attribute;
}
/**
* Get attribute
*
* @return \Rakit\Validation\Attribute|null
*/
public function getAttribute()
{
return $this->attribute;
}
/**
* Get parameters
*
* @return array
*/
public function getParameters() : array
{
return $this->params;
}
/**
* Set params
*
* @param array $params
* @return \Rakit\Validation\Rule
*/
public function setParameters(array $params) : Rule
{
$this->params = \array_merge($this->params, $params);
return $this;
}
/**
* Set parameters
*
* @param string $key
* @param mixed $value
* @return \Rakit\Validation\Rule
*/
public function setParameter(string $key, $value) : Rule
{
$this->params[$key] = $value;
return $this;
}
/**
* Fill $params to $this->params
*
* @param array $params
* @return \Rakit\Validation\Rule
*/
public function fillParameters(array $params) : Rule
{
foreach ($this->fillableParams as $key) {
if (empty($params)) {
break;
}
$this->params[$key] = \array_shift($params);
}
return $this;
}
/**
* Get parameter from given $key, return null if it not exists
*
* @param string $key
* @return mixed
*/
public function parameter(string $key)
{
return isset($this->params[$key]) ? $this->params[$key] : null;
}
/**
* Set parameter text that can be displayed in error message using ':param_key'
*
* @param string $key
* @param string $text
* @return void
*/
public function setParameterText(string $key, string $text)
{
$this->paramsTexts[$key] = $text;
}
/**
* Get $paramsTexts
*
* @return array
*/
public function getParametersTexts() : array
{
return $this->paramsTexts;
}
/**
* Check whether this rule is implicit
*
* @return boolean
*/
public function isImplicit() : bool
{
return $this->implicit;
}
/**
* Just alias of setMessage
*
* @param string $message
* @return \Rakit\Validation\Rule
*/
public function message(string $message) : Rule
{
return $this->setMessage($message);
}
/**
* Set message
*
* @param string $message
* @return \Rakit\Validation\Rule
*/
public function setMessage(string $message) : Rule
{
$this->message = $message;
return $this;
}
/**
* Get message
*
* @return string
*/
public function getMessage() : string
{
return $this->message;
}
/**
* Check given $params must be exists
*
* @param array $params
* @return void
* @throws \Rakit\Validation\MissingRequiredParameterException
*/
protected function requireParameters(array $params)
{
foreach ($params as $param) {
if (!isset($this->params[$param])) {
$rule = $this->getKey();
throw new MissingRequiredParameterException("Missing required parameter '{$param}' on rule '{$rule}'");
}
}
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
use Exception;
class RuleNotFoundException extends Exception
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class RuleQuashException extends \Exception
{
}

View File

@ -0,0 +1,23 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Accepted extends Rule
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute must be accepted";
/**
* Check the $value is accepted
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$acceptables = ['yes', 'on', '1', 1, \true, 'true'];
return \in_array($value, $acceptables, \true);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class After extends Rule
{
use Traits\DateUtilsTrait;
/** @var string */
protected $message = "The :attribute must be a date after :time.";
/** @var array */
protected $fillableParams = ['time'];
/**
* Check the value is valid
*
* @param mixed $value
* @return bool
* @throws \Exception
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$time = $this->parameter('time');
if (!$this->isValidDate($value)) {
throw $this->throwException($value);
}
if (!$this->isValidDate($time)) {
throw $this->throwException($time);
}
return $this->getTimeStamp($time) < $this->getTimeStamp($value);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Alpha extends Rule
{
/** @var string */
protected $message = "The :attribute only allows alphabet characters";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \is_string($value) && \preg_match('/^[\\pL\\pM]+$/u', $value);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class AlphaDash extends Rule
{
/** @var string */
protected $message = "The :attribute only allows a-z, 0-9, _ and -";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
if (!\is_string($value) && !\is_numeric($value)) {
return \false;
}
return \preg_match('/^[\\pL\\pM\\pN_-]+$/u', $value) > 0;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class AlphaNum extends Rule
{
/** @var string */
protected $message = "The :attribute only allows alphabet and numeric";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
if (!\is_string($value) && !\is_numeric($value)) {
return \false;
}
return \preg_match('/^[\\pL\\pM\\pN]+$/u', $value) > 0;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class AlphaSpaces extends Rule
{
/** @var string */
protected $message = "The :attribute may only allows alphabet and spaces";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
if (!\is_string($value)) {
return \false;
}
return \preg_match('/^[\\pL\\pM\\s]+$/u', $value) > 0;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Before extends Rule
{
use Traits\DateUtilsTrait;
/** @var string */
protected $message = "The :attribute must be a date before :time.";
/** @var array */
protected $fillableParams = ['time'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
* @throws \Exception
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$time = $this->parameter('time');
if (!$this->isValidDate($value)) {
throw $this->throwException($value);
}
if (!$this->isValidDate($time)) {
throw $this->throwException($time);
}
return $this->getTimeStamp($time) > $this->getTimeStamp($value);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Between extends Rule
{
use Traits\SizeTrait;
/** @var string */
protected $message = "The :attribute must be between :min and :max";
/** @var array */
protected $fillableParams = ['min', 'max'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$min = $this->getBytesSize($this->parameter('min'));
$max = $this->getBytesSize($this->parameter('max'));
$valueSize = $this->getValueSize($value);
if (!\is_numeric($valueSize)) {
return \false;
}
return $valueSize >= $min && $valueSize <= $max;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Boolean extends Rule
{
/** @var string */
protected $message = "The :attribute must be a boolean";
/**
* Check the value is valid
*
* @param mixed $value
* @return bool
* @throws \Exception
*/
public function check($value) : bool
{
return \in_array($value, [\true, \false, "true", "false", 1, 0, "0", "1", "y", "n"], \true);
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
use InvalidArgumentException;
use Closure;
class Callback extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid";
/** @var array */
protected $fillableParams = ['callback'];
/**
* Set the Callback closure
*
* @param Closure $callback
* @return self
*/
public function setCallback(Closure $callback) : Rule
{
return $this->setParameter('callback', $callback);
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
* @throws \Exception
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$callback = $this->parameter('callback');
if (\false === $callback instanceof Closure) {
$key = $this->attribute->getKey();
throw new InvalidArgumentException("Callback rule for '{$key}' is not callable.");
}
$callback = $callback->bindTo($this);
$invalidMessage = $callback($value);
if (\is_string($invalidMessage)) {
$this->setMessage($invalidMessage);
return \false;
} elseif (\false === $invalidMessage) {
return \false;
}
return \true;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Date extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid date format";
/** @var array */
protected $fillableParams = ['format'];
/** @var array */
protected $params = ['format' => 'Y-m-d'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$format = $this->parameter('format');
return \date_create_from_format($format, $value) !== \false;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
use WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces\ModifyValue;
class Defaults extends Rule implements ModifyValue
{
/** @var string */
protected $message = "The :attribute default is :default";
/** @var array */
protected $fillableParams = ['default'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$default = $this->parameter('default');
return \true;
}
/**
* {@inheritDoc}
*/
public function modifyValue($value)
{
return $this->isEmptyValue($value) ? $this->parameter('default') : $value;
}
/**
* Check $value is empty value
*
* @param mixed $value
* @return boolean
*/
protected function isEmptyValue($value) : bool
{
$requiredValidator = new Required();
return \false === $requiredValidator->check($value, []);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Different extends Rule
{
/** @var string */
protected $message = "The :attribute must be different with :field";
/** @var array */
protected $fillableParams = ['field'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$field = $this->parameter('field');
$anotherValue = $this->validation->getValue($field);
return $value != $anotherValue;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Digits extends Rule
{
/** @var string */
protected $message = "The :attribute must be numeric and must have an exact length of :length";
/** @var array */
protected $fillableParams = ['length'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$length = (int) $this->parameter('length');
return !\preg_match('/[^0-9]/', $value) && \strlen((string) $value) == $length;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class DigitsBetween extends Rule
{
/** @var string */
protected $message = "The :attribute must have a length between the given :min and :max";
/** @var array */
protected $fillableParams = ['min', 'max'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$min = (int) $this->parameter('min');
$max = (int) $this->parameter('max');
$length = \strlen((string) $value);
return !\preg_match('/[^0-9]/', $value) && $length >= $min && $length <= $max;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Email extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid email";
/**
* Check $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_EMAIL) !== \false;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Extension extends Rule
{
/** @var string */
protected $message = "The :attribute must be a :allowed_extensions file";
/**
* Given $params and assign the $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
if (\count($params) == 1 && \is_array($params[0])) {
$params = $params[0];
}
$this->params['allowed_extensions'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['allowed_extensions']);
$allowedExtensions = $this->parameter('allowed_extensions');
foreach ($allowedExtensions as $key => $ext) {
$allowedExtensions[$key] = \ltrim($ext, '.');
}
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$allowedExtensionsText = Helper::join(Helper::wraps($allowedExtensions, ".", ""), ', ', ", {$or} ");
$this->setParameterText('allowed_extensions', $allowedExtensionsText);
$ext = \strtolower(\pathinfo($value, \PATHINFO_EXTENSION));
return $ext && \in_array($ext, $allowedExtensions) ? \true : \false;
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class In extends Rule
{
/** @var string */
protected $message = "The :attribute only allows :allowed_values";
/** @var bool */
protected $strict = \false;
/**
* Given $params and assign the $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
if (\count($params) == 1 && \is_array($params[0])) {
$params = $params[0];
}
$this->params['allowed_values'] = $params;
return $this;
}
/**
* Set strict value
*
* @param bool $strict
* @return void
*/
public function strict(bool $strict = \true)
{
$this->strict = $strict;
}
/**
* Check $value is existed
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['allowed_values']);
$allowedValues = $this->parameter('allowed_values');
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$allowedValuesText = Helper::join(Helper::wraps($allowedValues, "'"), ', ', ", {$or} ");
$this->setParameterText('allowed_values', $allowedValuesText);
return \in_array($value, $allowedValues, $this->strict);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Integer extends Rule
{
/** @var string */
protected $message = "The :attribute must be integer";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_INT) !== \false;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces;
interface BeforeValidate
{
/**
* Before validate hook
*
* @return void
*/
public function beforeValidate();
}

View File

@ -0,0 +1,15 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces;
interface ModifyValue
{
/**
* Modify given value
* so in current and next rules returned value will be used
*
* @param mixed $value
* @return mixed
*/
public function modifyValue($value);
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Ip extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid IP Address";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_IP) !== \false;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Ipv4 extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid IPv4 Address";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4) !== \false;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Ipv6 extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid IPv6 Address";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) !== \false;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Json extends Rule
{
/** @var string */
protected $message = "The :attribute must be a valid JSON string";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
if (!\is_string($value) || empty($value)) {
return \false;
}
\json_decode($value);
if (\json_last_error() !== \JSON_ERROR_NONE) {
return \false;
}
return \true;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Lowercase extends Rule
{
/** @var string */
protected $message = "The :attribute must be lowercase";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \mb_strtolower($value, \mb_detect_encoding($value)) === $value;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Max extends Rule
{
use Traits\SizeTrait;
/** @var string */
protected $message = "The :attribute maximum is :max";
/** @var array */
protected $fillableParams = ['max'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$max = $this->getBytesSize($this->parameter('max'));
$valueSize = $this->getValueSize($value);
if (!\is_numeric($valueSize)) {
return \false;
}
return $valueSize <= $max;
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
use WP_Ultimo\Dependencies\Rakit\Validation\MimeTypeGuesser;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Mimes extends Rule
{
use Traits\FileTrait;
/** @var string */
protected $message = "The :attribute file type must be :allowed_types";
/** @var string|int */
protected $maxSize = null;
/** @var string|int */
protected $minSize = null;
/** @var array */
protected $allowedTypes = [];
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->allowTypes($params);
return $this;
}
/**
* Given $types and assign $this->params
*
* @param mixed $types
* @return self
*/
public function allowTypes($types) : Rule
{
if (\is_string($types)) {
$types = \explode('|', $types);
}
$this->params['allowed_types'] = $types;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$allowedTypes = $this->parameter('allowed_types');
if ($allowedTypes) {
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$this->setParameterText('allowed_types', Helper::join(Helper::wraps($allowedTypes, "'"), ', ', ", {$or} "));
}
// below is Required rule job
if (!$this->isValueFromUploadedFiles($value) or $value['error'] == \UPLOAD_ERR_NO_FILE) {
return \true;
}
if (!$this->isUploadedFile($value)) {
return \false;
}
// just make sure there is no error
if ($value['error']) {
return \false;
}
if (!empty($allowedTypes)) {
$guesser = new MimeTypeGuesser();
$ext = $guesser->getExtension($value['type']);
unset($guesser);
if (!\in_array($ext, $allowedTypes)) {
return \false;
}
}
return \true;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Min extends Rule
{
use Traits\SizeTrait;
/** @var string */
protected $message = "The :attribute minimum is :min";
/** @var array */
protected $fillableParams = ['min'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$min = $this->getBytesSize($this->parameter('min'));
$valueSize = $this->getValueSize($value);
if (!\is_numeric($valueSize)) {
return \false;
}
return $valueSize >= $min;
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class NotIn extends Rule
{
/** @var string */
protected $message = "The :attribute is not allowing :disallowed_values";
/** @var bool */
protected $strict = \false;
/**
* Given $params and assign the $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
if (\count($params) == 1 and \is_array($params[0])) {
$params = $params[0];
}
$this->params['disallowed_values'] = $params;
return $this;
}
/**
* Set strict value
*
* @param bool $strict
* @return void
*/
public function strict($strict = \true)
{
$this->strict = $strict;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['disallowed_values']);
$disallowedValues = (array) $this->parameter('disallowed_values');
$and = $this->validation ? $this->validation->getTranslation('and') : 'and';
$disallowedValuesText = Helper::join(Helper::wraps($disallowedValues, "'"), ', ', ", {$and} ");
$this->setParameterText('disallowed_values', $disallowedValuesText);
return !\in_array($value, $disallowedValues, $this->strict);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Nullable extends Rule
{
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \true;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Numeric extends Rule
{
/** @var string */
protected $message = "The :attribute must be numeric";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \is_numeric($value);
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Present extends Rule
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute must be present";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->setAttributeAsRequired();
return $this->validation->hasValue($this->attribute->getKey());
}
/**
* Set attribute is required if $this->attribute is set
*
* @return void
*/
protected function setAttributeAsRequired()
{
if ($this->attribute) {
$this->attribute->setRequired(\true);
}
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Regex extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid format";
/** @var array */
protected $fillableParams = ['regex'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$regex = $this->parameter('regex');
return \preg_match($regex, $value) > 0;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Required extends Rule
{
use Traits\FileTrait;
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->setAttributeAsRequired();
if ($this->attribute and $this->attribute->hasRule('uploaded_file')) {
return $this->isValueFromUploadedFiles($value) and $value['error'] != \UPLOAD_ERR_NO_FILE;
}
if (\is_string($value)) {
return \mb_strlen(\trim($value), 'UTF-8') > 0;
}
if (\is_array($value)) {
return \count($value) > 0;
}
return !\is_null($value);
}
/**
* Set attribute is required if $this->attribute is set
*
* @return void
*/
protected function setAttributeAsRequired()
{
if ($this->attribute) {
$this->attribute->setRequired(\true);
}
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredIf extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign the $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['field'] = \array_shift($params);
$this->params['values'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['field', 'values']);
$anotherAttribute = $this->parameter('field');
$definedValues = $this->parameter('values');
$anotherValue = $this->getAttribute()->getValue($anotherAttribute);
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
if (\in_array($anotherValue, $definedValues)) {
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
return \true;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredUnless extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign the $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['field'] = \array_shift($params);
$this->params['values'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['field', 'values']);
$anotherAttribute = $this->parameter('field');
$definedValues = $this->parameter('values');
$anotherValue = $this->getAttribute()->getValue($anotherAttribute);
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
if (!\in_array($anotherValue, $definedValues)) {
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
return \true;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredWith extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['fields'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['fields']);
$fields = $this->parameter('fields');
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
foreach ($fields as $field) {
if ($this->validation->hasValue($field)) {
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
}
return \true;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredWithAll extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['fields'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['fields']);
$fields = $this->parameter('fields');
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
foreach ($fields as $field) {
if (!$this->validation->hasValue($field)) {
return \true;
}
}
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredWithout extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['fields'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['fields']);
$fields = $this->parameter('fields');
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
foreach ($fields as $field) {
if (!$this->validation->hasValue($field)) {
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
}
return \true;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class RequiredWithoutAll extends Required
{
/** @var bool */
protected $implicit = \true;
/** @var string */
protected $message = "The :attribute is required";
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->params['fields'] = $params;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters(['fields']);
$fields = $this->parameter('fields');
$validator = $this->validation->getValidator();
$requiredValidator = $validator('required');
foreach ($fields as $field) {
if ($this->validation->hasValue($field)) {
return \true;
}
}
$this->setAttributeAsRequired();
return $requiredValidator->check($value, []);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Same extends Rule
{
/** @var string */
protected $message = "The :attribute must be same with :field";
/** @var array */
protected $fillableParams = ['field'];
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$this->requireParameters($this->fillableParams);
$field = $this->parameter('field');
$anotherValue = $this->getAttribute()->getValue($field);
return $value == $anotherValue;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules\Traits;
use Exception;
trait DateUtilsTrait
{
/**
* Check the $date is valid
*
* @param string $date
* @return bool
*/
protected function isValidDate(string $date) : bool
{
return \strtotime($date) !== \false;
}
/**
* Throw exception
*
* @param string $value
* @return Exception
*/
protected function throwException(string $value)
{
// phpcs:ignore
return new Exception("Expected a valid date, got '{$value}' instead. 2016-12-08, 2016-12-02 14:58, tomorrow are considered valid dates");
}
/**
* Given $date and get the time stamp
*
* @param mixed $date
* @return int
*/
protected function getTimeStamp($date) : int
{
return \strtotime($date);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules\Traits;
use InvalidArgumentException;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
trait FileTrait
{
/**
* Check whether value is from $_FILES
*
* @param mixed $value
* @return bool
*/
public function isValueFromUploadedFiles($value) : bool
{
if (!\is_array($value)) {
return \false;
}
$keys = ['name', 'type', 'tmp_name', 'size', 'error'];
foreach ($keys as $key) {
if (!\array_key_exists($key, $value)) {
return \false;
}
}
return \true;
}
/**
* Check the $value is uploaded file
*
* @param mixed $value
* @return bool
*/
public function isUploadedFile($value) : bool
{
return $this->isValueFromUploadedFiles($value) && \is_uploaded_file($value['tmp_name']);
}
/**
* Resolve uploaded file value
*
* @param mixed $value
* @return array|null
*/
public function resolveUploadedFileValue($value)
{
if (!$this->isValueFromUploadedFiles($value)) {
return null;
}
// Here $value should be an array:
// [
// 'name' => string|array,
// 'type' => string|array,
// 'size' => int|array,
// 'tmp_name' => string|array,
// 'error' => string|array,
// ]
// Flatten $value to it's array dot format,
// so our array must be something like:
// ['name' => string, 'type' => string, 'size' => int, ...]
// or for multiple values:
// ['name.0' => string, 'name.1' => string, 'type.0' => string, 'type.1' => string, ...]
// or for nested array:
// ['name.foo.bar' => string, 'name.foo.baz' => string, 'type.foo.bar' => string, 'type.foo.baz' => string, ...]
$arrayDots = Helper::arrayDot($value);
$results = [];
foreach ($arrayDots as $key => $val) {
// Move first key to last key
// name.foo.bar -> foo.bar.name
$splits = \explode(".", $key);
$firstKey = \array_shift($splits);
$key = \count($splits) ? \implode(".", $splits) . ".{$firstKey}" : $firstKey;
Helper::arraySet($results, $key, $val);
}
return $results;
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules\Traits;
use InvalidArgumentException;
trait SizeTrait
{
/**
* Get size (int) value from given $value
*
* @param int|string $value
* @return float|false
*/
protected function getValueSize($value)
{
if ($this->getAttribute() && ($this->getAttribute()->hasRule('numeric') || $this->getAttribute()->hasRule('integer')) && \is_numeric($value)) {
$value = (float) $value;
}
if (\is_int($value) || \is_float($value)) {
return (float) $value;
} elseif (\is_string($value)) {
return (float) \mb_strlen($value, 'UTF-8');
} elseif ($this->isUploadedFileValue($value)) {
return (float) $value['size'];
} elseif (\is_array($value)) {
return (float) \count($value);
} else {
return \false;
}
}
/**
* Given $size and get the bytes
*
* @param string|int $size
* @return float
* @throws InvalidArgumentException
*/
protected function getBytesSize($size)
{
if (\is_numeric($size)) {
return (float) $size;
}
if (!\is_string($size)) {
throw new InvalidArgumentException("Size must be string or numeric Bytes", 1);
}
if (!\preg_match("/^(?<number>((\\d+)?\\.)?\\d+)(?<format>(B|K|M|G|T|P)B?)?\$/i", $size, $match)) {
throw new InvalidArgumentException("Size is not valid format", 1);
}
$number = (float) $match['number'];
$format = isset($match['format']) ? $match['format'] : '';
switch (\strtoupper($format)) {
case "KB":
case "K":
return $number * 1024;
case "MB":
case "M":
return $number * \pow(1024, 2);
case "GB":
case "G":
return $number * \pow(1024, 3);
case "TB":
case "T":
return $number * \pow(1024, 4);
case "PB":
case "P":
return $number * \pow(1024, 5);
default:
return $number;
}
}
/**
* Check whether value is from $_FILES
*
* @param mixed $value
* @return bool
*/
public function isUploadedFileValue($value) : bool
{
if (!\is_array($value)) {
return \false;
}
$keys = ['name', 'type', 'tmp_name', 'size', 'error'];
foreach ($keys as $key) {
if (!\array_key_exists($key, $value)) {
return \false;
}
}
return \true;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class TypeArray extends Rule
{
/** @var string */
protected $message = "The :attribute must be array";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \is_array($value);
}
}

View File

@ -0,0 +1,154 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Helper;
use WP_Ultimo\Dependencies\Rakit\Validation\MimeTypeGuesser;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
use WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces\BeforeValidate;
class UploadedFile extends Rule implements BeforeValidate
{
use Traits\FileTrait, Traits\SizeTrait;
/** @var string */
protected $message = "The :attribute is not valid uploaded file";
/** @var string|int */
protected $maxSize = null;
/** @var string|int */
protected $minSize = null;
/** @var array */
protected $allowedTypes = [];
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
$this->minSize(\array_shift($params));
$this->maxSize(\array_shift($params));
$this->fileTypes($params);
return $this;
}
/**
* Given $size and set the max size
*
* @param string|int $size
* @return self
*/
public function maxSize($size) : Rule
{
$this->params['max_size'] = $size;
return $this;
}
/**
* Given $size and set the min size
*
* @param string|int $size
* @return self
*/
public function minSize($size) : Rule
{
$this->params['min_size'] = $size;
return $this;
}
/**
* Given $min and $max then set the range size
*
* @param string|int $min
* @param string|int $max
* @return self
*/
public function sizeBetween($min, $max) : Rule
{
$this->minSize($min);
$this->maxSize($max);
return $this;
}
/**
* Given $types and assign $this->params
*
* @param mixed $types
* @return self
*/
public function fileTypes($types) : Rule
{
if (\is_string($types)) {
$types = \explode('|', $types);
}
$this->params['allowed_types'] = $types;
return $this;
}
/**
* {@inheritDoc}
*/
public function beforeValidate()
{
$attribute = $this->getAttribute();
// We only resolve uploaded file value
// from complex attribute such as 'files.photo', 'images.*', 'images.foo.bar', etc.
if (!$attribute->isUsingDotNotation()) {
return;
}
$keys = \explode(".", $attribute->getKey());
$firstKey = \array_shift($keys);
$firstKeyValue = $this->validation->getValue($firstKey);
$resolvedValue = $this->resolveUploadedFileValue($firstKeyValue);
// Return original value if $value can't be resolved as uploaded file value
if (!$resolvedValue) {
return;
}
$this->validation->setValue($firstKey, $resolvedValue);
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$minSize = $this->parameter('min_size');
$maxSize = $this->parameter('max_size');
$allowedTypes = $this->parameter('allowed_types');
if ($allowedTypes) {
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$this->setParameterText('allowed_types', Helper::join(Helper::wraps($allowedTypes, "'"), ', ', ", {$or} "));
}
// below is Required rule job
if (!$this->isValueFromUploadedFiles($value) or $value['error'] == \UPLOAD_ERR_NO_FILE) {
return \true;
}
if (!$this->isUploadedFile($value)) {
return \false;
}
// just make sure there is no error
if ($value['error']) {
return \false;
}
if ($minSize) {
$bytesMinSize = $this->getBytesSize($minSize);
if ($value['size'] < $bytesMinSize) {
$this->setMessage('The :attribute file is too small, minimum size is :min_size');
return \false;
}
}
if ($maxSize) {
$bytesMaxSize = $this->getBytesSize($maxSize);
if ($value['size'] > $bytesMaxSize) {
$this->setMessage('The :attribute file is too large, maximum size is :max_size');
return \false;
}
}
if (!empty($allowedTypes)) {
$guesser = new MimeTypeGuesser();
$ext = $guesser->getExtension($value['type']);
unset($guesser);
if (!\in_array($ext, $allowedTypes)) {
$this->setMessage('The :attribute file type must be :allowed_types');
return \false;
}
}
return \true;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Uppercase extends Rule
{
/** @var string */
protected $message = "The :attribute must be uppercase";
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
return \mb_strtoupper($value, \mb_detect_encoding($value)) === $value;
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Rules;
use WP_Ultimo\Dependencies\Rakit\Validation\Rule;
class Url extends Rule
{
/** @var string */
protected $message = "The :attribute is not valid url";
/**
* Given $params and assign $this->params
*
* @param array $params
* @return self
*/
public function fillParameters(array $params) : Rule
{
if (\count($params) == 1 and \is_array($params[0])) {
$params = $params[0];
}
return $this->forScheme($params);
}
/**
* Given $schemes and assign $this->params
*
* @param array $schemes
* @return self
*/
public function forScheme($schemes) : Rule
{
$this->params['schemes'] = (array) $schemes;
return $this;
}
/**
* Check the $value is valid
*
* @param mixed $value
* @return bool
*/
public function check($value) : bool
{
$schemes = $this->parameter('schemes');
if (!$schemes) {
return $this->validateCommonScheme($value);
} else {
foreach ($schemes as $scheme) {
$method = 'validate' . \ucfirst($scheme) . 'Scheme';
if (\method_exists($this, $method)) {
if ($this->{$method}($value)) {
return \true;
}
} elseif ($this->validateCommonScheme($value, $scheme)) {
return \true;
}
}
return \false;
}
}
/**
* Validate $value is valid URL format
*
* @param mixed $value
* @return bool
*/
public function validateBasic($value) : bool
{
return \filter_var($value, \FILTER_VALIDATE_URL) !== \false;
}
/**
* Validate $value is correct $scheme format
*
* @param mixed $value
* @param null $scheme
* @return bool
*/
public function validateCommonScheme($value, $scheme = null) : bool
{
if (!$scheme) {
return $this->validateBasic($value) && (bool) \preg_match("/^\\w+:\\/\\//i", $value);
} else {
return $this->validateBasic($value) && (bool) \preg_match("/^{$scheme}:\\/\\//", $value);
}
}
/**
* Validate the $value is mailto scheme format
*
* @param mixed $value
* @return bool
*/
public function validateMailtoScheme($value) : bool
{
return $this->validateBasic($value) && \preg_match("/^mailto:/", $value);
}
/**
* Validate the $value is jdbc scheme format
*
* @param mixed $value
* @return bool
*/
public function validateJdbcScheme($value) : bool
{
return (bool) \preg_match("/^jdbc:\\w+:\\/\\//", $value);
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Traits;
trait MessagesTrait
{
/** @var array */
protected $messages = [];
/**
* Given $key and $message to set message
*
* @param mixed $key
* @param mixed $message
* @return void
*/
public function setMessage(string $key, string $message)
{
$this->messages[$key] = $message;
}
/**
* Given $messages and set multiple messages
*
* @param array $messages
* @return void
*/
public function setMessages(array $messages)
{
$this->messages = \array_merge($this->messages, $messages);
}
/**
* Given message from given $key
*
* @param string $key
* @return string
*/
public function getMessage(string $key) : string
{
return \array_key_exists($key, $this->messages) ? $this->messages[$key] : $key;
}
/**
* Get all $messages
*
* @return array
*/
public function getMessages() : array
{
return $this->messages;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation\Traits;
trait TranslationsTrait
{
/** @var array */
protected $translations = [];
/**
* Given $key and $translation to set translation
*
* @param mixed $key
* @param mixed $translation
* @return void
*/
public function setTranslation(string $key, string $translation)
{
$this->translations[$key] = $translation;
}
/**
* Given $translations and set multiple translations
*
* @param array $translations
* @return void
*/
public function setTranslations(array $translations)
{
$this->translations = \array_merge($this->translations, $translations);
}
/**
* Given translation from given $key
*
* @param string $key
* @return string
*/
public function getTranslation(string $key) : string
{
return \array_key_exists($key, $this->translations) ? $this->translations[$key] : $key;
}
/**
* Get all $translations
*
* @return array
*/
public function getTranslations() : array
{
return $this->translations;
}
}

View File

@ -0,0 +1,608 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
use Closure;
use WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces\BeforeValidate;
use WP_Ultimo\Dependencies\Rakit\Validation\Rules\Interfaces\ModifyValue;
use WP_Ultimo\Dependencies\Rakit\Validation\Rules\Required;
class Validation
{
use Traits\TranslationsTrait, Traits\MessagesTrait;
/** @var mixed */
protected $validator;
/** @var array */
protected $inputs = [];
/** @var array */
protected $attributes = [];
/** @var array */
protected $aliases = [];
/** @var string */
protected $messageSeparator = ':';
/** @var array */
protected $validData = [];
/** @var array */
protected $invalidData = [];
/** @var ErrorBag */
public $errors;
/**
* Constructor
*
* @param \Rakit\Validation\Validator $validator
* @param array $inputs
* @param array $rules
* @param array $messages
* @return void
*/
public function __construct(Validator $validator, array $inputs, array $rules, array $messages = [])
{
$this->validator = $validator;
$this->inputs = $this->resolveInputAttributes($inputs);
$this->messages = $messages;
$this->errors = new ErrorBag();
foreach ($rules as $attributeKey => $rules) {
$this->addAttribute($attributeKey, $rules);
}
}
/**
* Add attribute rules
*
* @param string $attributeKey
* @param string|array $rules
* @return void
*/
public function addAttribute(string $attributeKey, $rules)
{
$resolvedRules = $this->resolveRules($rules);
$attribute = new Attribute($this, $attributeKey, $this->getAlias($attributeKey), $resolvedRules);
$this->attributes[$attributeKey] = $attribute;
}
/**
* Get attribute by key
*
* @param string $attributeKey
* @return null|\Rakit\Validation\Attribute
*/
public function getAttribute(string $attributeKey)
{
return isset($this->attributes[$attributeKey]) ? $this->attributes[$attributeKey] : null;
}
/**
* Run validation
*
* @param array $inputs
* @return void
*/
public function validate(array $inputs = [])
{
$this->errors = new ErrorBag();
// reset error bag
$this->inputs = \array_merge($this->inputs, $this->resolveInputAttributes($inputs));
// Before validation hooks
foreach ($this->attributes as $attributeKey => $attribute) {
foreach ($attribute->getRules() as $rule) {
if ($rule instanceof BeforeValidate) {
$rule->beforeValidate();
}
}
}
foreach ($this->attributes as $attributeKey => $attribute) {
$this->validateAttribute($attribute);
}
}
/**
* Get ErrorBag instance
*
* @return \Rakit\Validation\ErrorBag
*/
public function errors() : ErrorBag
{
return $this->errors;
}
/**
* Validate attribute
*
* @param \Rakit\Validation\Attribute $attribute
* @return void
*/
protected function validateAttribute(Attribute $attribute)
{
if ($this->isArrayAttribute($attribute)) {
$attributes = $this->parseArrayAttribute($attribute);
foreach ($attributes as $i => $attr) {
$this->validateAttribute($attr);
}
return;
}
$attributeKey = $attribute->getKey();
$rules = $attribute->getRules();
$value = $this->getValue($attributeKey);
$isEmptyValue = $this->isEmptyValue($value);
if ($attribute->hasRule('nullable') && $isEmptyValue) {
$rules = [];
}
$isValid = \true;
foreach ($rules as $ruleValidator) {
$ruleValidator->setAttribute($attribute);
if ($ruleValidator instanceof ModifyValue) {
$value = $ruleValidator->modifyValue($value);
$isEmptyValue = $this->isEmptyValue($value);
}
$valid = $ruleValidator->check($value);
if ($isEmptyValue and $this->ruleIsOptional($attribute, $ruleValidator)) {
continue;
}
if (!$valid) {
$isValid = \false;
$this->addError($attribute, $value, $ruleValidator);
if ($ruleValidator->isImplicit()) {
break;
}
}
}
if ($isValid) {
$this->setValidData($attribute, $value);
} else {
$this->setInvalidData($attribute, $value);
}
}
/**
* Check whether given $attribute is array attribute
*
* @param \Rakit\Validation\Attribute $attribute
* @return bool
*/
protected function isArrayAttribute(Attribute $attribute) : bool
{
$key = $attribute->getKey();
return \strpos($key, '*') !== \false;
}
/**
* Parse array attribute into it's child attributes
*
* @param \Rakit\Validation\Attribute $attribute
* @return array
*/
protected function parseArrayAttribute(Attribute $attribute) : array
{
$attributeKey = $attribute->getKey();
$data = Helper::arrayDot($this->initializeAttributeOnData($attributeKey));
$pattern = \str_replace('\\*', '([^\\.]+)', \preg_quote($attributeKey));
$data = \array_merge($data, $this->extractValuesForWildcards($data, $attributeKey));
$attributes = [];
foreach ($data as $key => $value) {
if ((bool) \preg_match('/^' . $pattern . '\\z/', $key, $match)) {
$attr = new Attribute($this, $key, null, $attribute->getRules());
$attr->setPrimaryAttribute($attribute);
$attr->setKeyIndexes(\array_slice($match, 1));
$attributes[] = $attr;
}
}
// set other attributes to each attributes
foreach ($attributes as $i => $attr) {
$otherAttributes = $attributes;
unset($otherAttributes[$i]);
$attr->setOtherAttributes($otherAttributes);
}
return $attributes;
}
/**
* Gather a copy of the attribute data filled with any missing attributes.
* Adapted from: https://github.com/illuminate/validation/blob/v5.3.23/Validator.php#L334
*
* @param string $attribute
* @return array
*/
protected function initializeAttributeOnData(string $attributeKey) : array
{
$explicitPath = $this->getLeadingExplicitAttributePath($attributeKey);
$data = $this->extractDataFromPath($explicitPath);
$asteriskPos = \strpos($attributeKey, '*');
if (\false === $asteriskPos || $asteriskPos === \mb_strlen($attributeKey, 'UTF-8') - 1) {
return $data;
}
return Helper::arraySet($data, $attributeKey, null, \true);
}
/**
* Get all of the exact attribute values for a given wildcard attribute.
* Adapted from: https://github.com/illuminate/validation/blob/v5.3.23/Validator.php#L354
*
* @param array $data
* @param string $attributeKey
* @return array
*/
public function extractValuesForWildcards(array $data, string $attributeKey) : array
{
$keys = [];
$pattern = \str_replace('\\*', '[^\\.]+', \preg_quote($attributeKey));
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] = Helper::arrayGet($this->inputs, $key);
}
return $data;
}
/**
* Get the explicit part of the attribute name.
* Adapted from: https://github.com/illuminate/validation/blob/v5.3.23/Validator.php#L2817
*
* E.g. 'foo.bar.*.baz' -> 'foo.bar'
*
* Allows us to not spin through all of the flattened data for some operations.
*
* @param string $attributeKey
* @return string|null null when root wildcard
*/
protected function getLeadingExplicitAttributePath(string $attributeKey)
{
return \rtrim(\explode('*', $attributeKey)[0], '.') ?: null;
}
/**
* Extract data based on the given dot-notated path.
* Adapted from: https://github.com/illuminate/validation/blob/v5.3.23/Validator.php#L2830
*
* Used to extract a sub-section of the data for faster iteration.
*
* @param string|null $attributeKey
* @return array
*/
protected function extractDataFromPath($attributeKey) : array
{
$results = [];
$value = Helper::arrayGet($this->inputs, $attributeKey, '__missing__');
if ($value != '__missing__') {
Helper::arraySet($results, $attributeKey, $value);
}
return $results;
}
/**
* Add error to the $this->errors
*
* @param \Rakit\Validation\Attribute $attribute
* @param mixed $value
* @param \Rakit\Validation\Rule $ruleValidator
* @return void
*/
protected function addError(Attribute $attribute, $value, Rule $ruleValidator)
{
$ruleName = $ruleValidator->getKey();
$message = $this->resolveMessage($attribute, $value, $ruleValidator);
$this->errors->add($attribute->getKey(), $ruleName, $message);
}
/**
* Check $value is empty value
*
* @param mixed $value
* @return boolean
*/
protected function isEmptyValue($value) : bool
{
$requiredValidator = new Required();
return \false === $requiredValidator->check($value, []);
}
/**
* Check the rule is optional
*
* @param \Rakit\Validation\Attribute $attribute
* @param \Rakit\Validation\Rule $rule
* @return bool
*/
protected function ruleIsOptional(Attribute $attribute, Rule $rule) : bool
{
return \false === $attribute->isRequired() and \false === $rule->isImplicit() and \false === $rule instanceof Required;
}
/**
* Resolve attribute name
*
* @param \Rakit\Validation\Attribute $attribute
* @return string
*/
protected function resolveAttributeName(Attribute $attribute) : string
{
$primaryAttribute = $attribute->getPrimaryAttribute();
if (isset($this->aliases[$attribute->getKey()])) {
return $this->aliases[$attribute->getKey()];
} elseif ($primaryAttribute and isset($this->aliases[$primaryAttribute->getKey()])) {
return $this->aliases[$primaryAttribute->getKey()];
} elseif ($this->validator->isUsingHumanizedKey()) {
return $attribute->getHumanizedKey();
} else {
return $attribute->getKey();
}
}
/**
* Resolve message
*
* @param \Rakit\Validation\Attribute $attribute
* @param mixed $value
* @param \Rakit\Validation\Rule $validator
* @return mixed
*/
protected function resolveMessage(Attribute $attribute, $value, Rule $validator) : string
{
$primaryAttribute = $attribute->getPrimaryAttribute();
$params = \array_merge($validator->getParameters(), $validator->getParametersTexts());
$attributeKey = $attribute->getKey();
$ruleKey = $validator->getKey();
$alias = $attribute->getAlias() ?: $this->resolveAttributeName($attribute);
$message = $validator->getMessage();
// default rule message
$messageKeys = [$attributeKey . $this->messageSeparator . $ruleKey, $attributeKey, $ruleKey];
if ($primaryAttribute) {
// insert primaryAttribute keys
// $messageKeys = [
// $attributeKey.$this->messageSeparator.$ruleKey,
// >> here [1] <<
// $attributeKey,
// >> and here [3] <<
// $ruleKey
// ];
$primaryAttributeKey = $primaryAttribute->getKey();
\array_splice($messageKeys, 1, 0, $primaryAttributeKey . $this->messageSeparator . $ruleKey);
\array_splice($messageKeys, 3, 0, $primaryAttributeKey);
}
foreach ($messageKeys as $key) {
if (isset($this->messages[$key])) {
$message = $this->messages[$key];
break;
}
}
// Replace message params
$vars = \array_merge($params, ['attribute' => $alias, 'value' => $value]);
foreach ($vars as $key => $value) {
$value = $this->stringify($value);
$message = \str_replace(':' . $key, $value, $message);
}
// Replace key indexes
$keyIndexes = $attribute->getKeyIndexes();
foreach ($keyIndexes as $pathIndex => $index) {
$replacers = ["[{$pathIndex}]" => $index];
if (\is_numeric($index)) {
$replacers["{{$pathIndex}}"] = $index + 1;
}
$message = \str_replace(\array_keys($replacers), \array_values($replacers), $message);
}
return $message;
}
/**
* Stringify $value
*
* @param mixed $value
* @return string
*/
protected function stringify($value) : string
{
if (\is_string($value) || \is_numeric($value)) {
return $value;
} elseif (\is_array($value) || \is_object($value)) {
return \json_encode($value);
} else {
return '';
}
}
/**
* Resolve $rules
*
* @param mixed $rules
* @return array
*/
protected function resolveRules($rules) : array
{
if (\is_string($rules)) {
$rules = \explode('|', $rules);
}
$resolvedRules = [];
$validatorFactory = $this->getValidator();
foreach ($rules as $i => $rule) {
if (empty($rule)) {
continue;
}
$params = [];
if (\is_string($rule)) {
list($rulename, $params) = $this->parseRule($rule);
$validator = \call_user_func_array($validatorFactory, \array_merge([$rulename], $params));
} elseif ($rule instanceof Rule) {
$validator = $rule;
} elseif ($rule instanceof Closure) {
$validator = \call_user_func_array($validatorFactory, ['callback', $rule]);
} else {
$ruleName = \is_object($rule) ? \get_class($rule) : \gettype($rule);
$message = "Rule must be a string, Closure or '" . Rule::class . "' instance. " . $ruleName . " given";
throw new \Exception();
}
$resolvedRules[] = $validator;
}
return $resolvedRules;
}
/**
* Parse $rule
*
* @param string $rule
* @return array
*/
protected function parseRule(string $rule) : array
{
$exp = \explode(':', $rule, 2);
$rulename = $exp[0];
if ($rulename !== 'regex') {
$params = isset($exp[1]) ? \explode(',', $exp[1]) : [];
} else {
$params = [$exp[1]];
}
return [$rulename, $params];
}
/**
* Given $attributeKey and $alias then assign alias
*
* @param mixed $attributeKey
* @param mixed $alias
* @return void
*/
public function setAlias(string $attributeKey, string $alias)
{
$this->aliases[$attributeKey] = $alias;
}
/**
* Get attribute alias from given key
*
* @param mixed $attributeKey
* @return string|null
*/
public function getAlias(string $attributeKey)
{
return isset($this->aliases[$attributeKey]) ? $this->aliases[$attributeKey] : null;
}
/**
* Set attributes aliases
*
* @param array $aliases
* @return void
*/
public function setAliases(array $aliases)
{
$this->aliases = \array_merge($this->aliases, $aliases);
}
/**
* Check validations are passed
*
* @return bool
*/
public function passes() : bool
{
return $this->errors->count() == 0;
}
/**
* Check validations are failed
*
* @return bool
*/
public function fails() : bool
{
return !$this->passes();
}
/**
* Given $key and get value
*
* @param string $key
* @return mixed
*/
public function getValue(string $key)
{
return Helper::arrayGet($this->inputs, $key);
}
/**
* Set input value
*
* @param string $key
* @param mixed $value
* @return void
*/
public function setValue(string $key, $value)
{
Helper::arraySet($this->inputs, $key, $value);
}
/**
* Given $key and check value is exsited
*
* @param string $key
* @return boolean
*/
public function hasValue(string $key) : bool
{
return Helper::arrayHas($this->inputs, $key);
}
/**
* Get Validator class instance
*
* @return \Rakit\Validation\Validator
*/
public function getValidator() : Validator
{
return $this->validator;
}
/**
* Given $inputs and resolve input attributes
*
* @param array $inputs
* @return array
*/
protected function resolveInputAttributes(array $inputs) : array
{
$resolvedInputs = [];
foreach ($inputs as $key => $rules) {
$exp = \explode(':', $key);
if (\count($exp) > 1) {
// set attribute alias
$this->aliases[$exp[0]] = $exp[1];
}
$resolvedInputs[$exp[0]] = $rules;
}
return $resolvedInputs;
}
/**
* Get validated data
*
* @return array
*/
public function getValidatedData() : array
{
return \array_merge($this->validData, $this->invalidData);
}
/**
* Set valid data
*
* @param \Rakit\Validation\Attribute $attribute
* @param mixed $value
* @return void
*/
protected function setValidData(Attribute $attribute, $value)
{
$key = $attribute->getKey();
if ($attribute->isArrayAttribute() || $attribute->isUsingDotNotation()) {
Helper::arraySet($this->validData, $key, $value);
Helper::arrayUnset($this->invalidData, $key);
} else {
$this->validData[$key] = $value;
}
}
/**
* Get valid data
*
* @return array
*/
public function getValidData() : array
{
return $this->validData;
}
/**
* Set invalid data
*
* @param \Rakit\Validation\Attribute $attribute
* @param mixed $value
* @return void
*/
protected function setInvalidData(Attribute $attribute, $value)
{
$key = $attribute->getKey();
if ($attribute->isArrayAttribute() || $attribute->isUsingDotNotation()) {
Helper::arraySet($this->invalidData, $key, $value);
Helper::arrayUnset($this->validData, $key);
} else {
$this->invalidData[$key] = $value;
}
}
/**
* Get invalid data
*
* @return void
*/
public function getInvalidData() : array
{
return $this->invalidData;
}
}

View File

@ -0,0 +1,200 @@
<?php
namespace WP_Ultimo\Dependencies\Rakit\Validation;
class Validator
{
use Traits\TranslationsTrait, Traits\MessagesTrait;
/** @var array */
protected $translations = [];
/** @var array */
protected $validators = [];
/** @var bool */
protected $allowRuleOverride = \false;
/** @var bool */
protected $useHumanizedKeys = \true;
/**
* Constructor
*
* @param array $messages
* @return void
*/
public function __construct(array $messages = [])
{
$this->messages = $messages;
$this->registerBaseValidators();
}
/**
* Register or override existing validator
*
* @param mixed $key
* @param \Rakit\Validation\Rule $rule
* @return void
*/
public function setValidator(string $key, Rule $rule)
{
$this->validators[$key] = $rule;
$rule->setKey($key);
}
/**
* Get validator object from given $key
*
* @param mixed $key
* @return mixed
*/
public function getValidator($key)
{
return isset($this->validators[$key]) ? $this->validators[$key] : null;
}
/**
* Validate $inputs
*
* @param array $inputs
* @param array $rules
* @param array $messages
* @return Validation
*/
public function validate(array $inputs, array $rules, array $messages = []) : Validation
{
$validation = $this->make($inputs, $rules, $messages);
$validation->validate();
return $validation;
}
/**
* Given $inputs, $rules and $messages to make the Validation class instance
*
* @param array $inputs
* @param array $rules
* @param array $messages
* @return Validation
*/
public function make(array $inputs, array $rules, array $messages = []) : Validation
{
$messages = \array_merge($this->messages, $messages);
$validation = new Validation($this, $inputs, $rules, $messages);
$validation->setTranslations($this->getTranslations());
return $validation;
}
/**
* Magic invoke method to make Rule instance
*
* @param string $rule
* @return Rule
* @throws RuleNotFoundException
*/
public function __invoke(string $rule) : Rule
{
$args = \func_get_args();
$rule = \array_shift($args);
$params = $args;
$validator = $this->getValidator($rule);
if (!$validator) {
throw new RuleNotFoundException("Validator '{$rule}' is not registered", 1);
}
$clonedValidator = clone $validator;
$clonedValidator->fillParameters($params);
return $clonedValidator;
}
/**
* Initialize base validators array
*
* @return void
*/
protected function registerBaseValidators()
{
$baseValidator = [
'required' => new Rules\Required(),
'required_if' => new Rules\RequiredIf(),
'required_unless' => new Rules\RequiredUnless(),
'required_with' => new Rules\RequiredWith(),
'required_without' => new Rules\RequiredWithout(),
'required_with_all' => new Rules\RequiredWithAll(),
'required_without_all' => new Rules\RequiredWithoutAll(),
'email' => new Rules\Email(),
'alpha' => new Rules\Alpha(),
'numeric' => new Rules\Numeric(),
'alpha_num' => new Rules\AlphaNum(),
'alpha_dash' => new Rules\AlphaDash(),
'alpha_spaces' => new Rules\AlphaSpaces(),
'in' => new Rules\In(),
'not_in' => new Rules\NotIn(),
'min' => new Rules\Min(),
'max' => new Rules\Max(),
'between' => new Rules\Between(),
'url' => new Rules\Url(),
'integer' => new Rules\Integer(),
'boolean' => new Rules\Boolean(),
'ip' => new Rules\Ip(),
'ipv4' => new Rules\Ipv4(),
'ipv6' => new Rules\Ipv6(),
'extension' => new Rules\Extension(),
'array' => new Rules\TypeArray(),
'same' => new Rules\Same(),
'regex' => new Rules\Regex(),
'date' => new Rules\Date(),
'accepted' => new Rules\Accepted(),
'present' => new Rules\Present(),
'different' => new Rules\Different(),
'uploaded_file' => new Rules\UploadedFile(),
'mimes' => new Rules\Mimes(),
'callback' => new Rules\Callback(),
'before' => new Rules\Before(),
'after' => new Rules\After(),
'lowercase' => new Rules\Lowercase(),
'uppercase' => new Rules\Uppercase(),
'json' => new Rules\Json(),
'digits' => new Rules\Digits(),
'digits_between' => new Rules\DigitsBetween(),
'defaults' => new Rules\Defaults(),
'default' => new Rules\Defaults(),
// alias of defaults
'nullable' => new Rules\Nullable(),
];
foreach ($baseValidator as $key => $validator) {
$this->setValidator($key, $validator);
}
}
/**
* Given $ruleName and $rule to add new validator
*
* @param string $ruleName
* @param \Rakit\Validation\Rule $rule
* @return void
*/
public function addValidator(string $ruleName, Rule $rule)
{
if (!$this->allowRuleOverride && \array_key_exists($ruleName, $this->validators)) {
throw new RuleQuashException("You cannot override a built in rule. You have to rename your rule");
}
$this->setValidator($ruleName, $rule);
}
/**
* Set rule can allow to be overrided
*
* @param boolean $status
* @return void
*/
public function allowRuleOverride(bool $status = \false)
{
$this->allowRuleOverride = $status;
}
/**
* Set this can use humanize keys
*
* @param boolean $useHumanizedKeys
* @return void
*/
public function setUseHumanizedKeys(bool $useHumanizedKeys = \true)
{
$this->useHumanizedKeys = $useHumanizedKeys;
}
/**
* Get $this->useHumanizedKeys value
*
* @return void
*/
public function isUsingHumanizedKey() : bool
{
return $this->useHumanizedKeys;
}
}