First Commit
This commit is contained in:
+309
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
}
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
}
|
||||
+804
@@ -0,0 +1,804 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
class MimeTypeGuesser
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $mimeTypes = [
|
||||
'application/andrew-inset' => 'ez',
|
||||
'application/applixware' => 'aw',
|
||||
'application/atom+xml' => 'atom',
|
||||
'application/atomcat+xml' => 'atomcat',
|
||||
'application/atomsvc+xml' => 'atomsvc',
|
||||
'application/ccxml+xml' => 'ccxml',
|
||||
'application/cdmi-capability' => 'cdmia',
|
||||
'application/cdmi-container' => 'cdmic',
|
||||
'application/cdmi-domain' => 'cdmid',
|
||||
'application/cdmi-object' => 'cdmio',
|
||||
'application/cdmi-queue' => 'cdmiq',
|
||||
'application/cu-seeme' => 'cu',
|
||||
'application/davmount+xml' => 'davmount',
|
||||
'application/docbook+xml' => 'dbk',
|
||||
'application/dssc+der' => 'dssc',
|
||||
'application/dssc+xml' => 'xdssc',
|
||||
'application/ecmascript' => 'ecma',
|
||||
'application/emma+xml' => 'emma',
|
||||
'application/epub+zip' => 'epub',
|
||||
'application/exi' => 'exi',
|
||||
'application/font-tdpfr' => 'pfr',
|
||||
'application/gml+xml' => 'gml',
|
||||
'application/gpx+xml' => 'gpx',
|
||||
'application/gxf' => 'gxf',
|
||||
'application/hyperstudio' => 'stk',
|
||||
'application/inkml+xml' => 'ink',
|
||||
'application/ipfix' => 'ipfix',
|
||||
'application/java-archive' => 'jar',
|
||||
'application/java-serialized-object' => 'ser',
|
||||
'application/java-vm' => 'class',
|
||||
'application/javascript' => 'js',
|
||||
'application/json' => 'json',
|
||||
'application/jsonml+json' => 'jsonml',
|
||||
'application/lost+xml' => 'lostxml',
|
||||
'application/mac-binhex40' => 'hqx',
|
||||
'application/mac-compactpro' => 'cpt',
|
||||
'application/mads+xml' => 'mads',
|
||||
'application/marc' => 'mrc',
|
||||
'application/marcxml+xml' => 'mrcx',
|
||||
'application/mathematica' => 'ma',
|
||||
'application/mathml+xml' => 'mathml',
|
||||
'application/mbox' => 'mbox',
|
||||
'application/mediaservercontrol+xml' => 'mscml',
|
||||
'application/metalink+xml' => 'metalink',
|
||||
'application/metalink4+xml' => 'meta4',
|
||||
'application/mets+xml' => 'mets',
|
||||
'application/mods+xml' => 'mods',
|
||||
'application/mp21' => 'm21',
|
||||
'application/mp4' => 'mp4s',
|
||||
'application/msword' => 'doc',
|
||||
'application/mxf' => 'mxf',
|
||||
'application/octet-stream' => 'bin',
|
||||
'application/oda' => 'oda',
|
||||
'application/oebps-package+xml' => 'opf',
|
||||
'application/ogg' => 'ogx',
|
||||
'application/omdoc+xml' => 'omdoc',
|
||||
'application/onenote' => 'onetoc',
|
||||
'application/oxps' => 'oxps',
|
||||
'application/patch-ops-error+xml' => 'xer',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/pgp-encrypted' => 'pgp',
|
||||
'application/pgp-signature' => 'asc',
|
||||
'application/pics-rules' => 'prf',
|
||||
'application/pkcs10' => 'p10',
|
||||
'application/pkcs7-mime' => 'p7m',
|
||||
'application/pkcs7-signature' => 'p7s',
|
||||
'application/pkcs8' => 'p8',
|
||||
'application/pkix-attr-cert' => 'ac',
|
||||
'application/pkix-cert' => 'cer',
|
||||
'application/pkix-crl' => 'crl',
|
||||
'application/pkix-pkipath' => 'pkipath',
|
||||
'application/pkixcmp' => 'pki',
|
||||
'application/pls+xml' => 'pls',
|
||||
'application/postscript' => 'ai',
|
||||
'application/prs.cww' => 'cww',
|
||||
'application/pskc+xml' => 'pskcxml',
|
||||
'application/rdf+xml' => 'rdf',
|
||||
'application/reginfo+xml' => 'rif',
|
||||
'application/relax-ng-compact-syntax' => 'rnc',
|
||||
'application/resource-lists+xml' => 'rl',
|
||||
'application/resource-lists-diff+xml' => 'rld',
|
||||
'application/rls-services+xml' => 'rs',
|
||||
'application/rpki-ghostbusters' => 'gbr',
|
||||
'application/rpki-manifest' => 'mft',
|
||||
'application/rpki-roa' => 'roa',
|
||||
'application/rsd+xml' => 'rsd',
|
||||
'application/rss+xml' => 'rss',
|
||||
'application/rtf' => 'rtf',
|
||||
'application/sbml+xml' => 'sbml',
|
||||
'application/scvp-cv-request' => 'scq',
|
||||
'application/scvp-cv-response' => 'scs',
|
||||
'application/scvp-vp-request' => 'spq',
|
||||
'application/scvp-vp-response' => 'spp',
|
||||
'application/sdp' => 'sdp',
|
||||
'application/set-payment-initiation' => 'setpay',
|
||||
'application/set-registration-initiation' => 'setreg',
|
||||
'application/shf+xml' => 'shf',
|
||||
'application/smil+xml' => 'smi',
|
||||
'application/sparql-query' => 'rq',
|
||||
'application/sparql-results+xml' => 'srx',
|
||||
'application/srgs' => 'gram',
|
||||
'application/srgs+xml' => 'grxml',
|
||||
'application/sru+xml' => 'sru',
|
||||
'application/ssdl+xml' => 'ssdl',
|
||||
'application/ssml+xml' => 'ssml',
|
||||
'application/tei+xml' => 'tei',
|
||||
'application/thraud+xml' => 'tfi',
|
||||
'application/timestamped-data' => 'tsd',
|
||||
'application/vnd.3gpp.pic-bw-large' => 'plb',
|
||||
'application/vnd.3gpp.pic-bw-small' => 'psb',
|
||||
'application/vnd.3gpp.pic-bw-var' => 'pvb',
|
||||
'application/vnd.3gpp2.tcap' => 'tcap',
|
||||
'application/vnd.3m.post-it-notes' => 'pwn',
|
||||
'application/vnd.accpac.simply.aso' => 'aso',
|
||||
'application/vnd.accpac.simply.imp' => 'imp',
|
||||
'application/vnd.acucobol' => 'acu',
|
||||
'application/vnd.acucorp' => 'atc',
|
||||
'application/vnd.adobe.air-application-installer-package+zip' => 'air',
|
||||
'application/vnd.adobe.formscentral.fcdt' => 'fcdt',
|
||||
'application/vnd.adobe.fxp' => 'fxp',
|
||||
'application/vnd.adobe.xdp+xml' => 'xdp',
|
||||
'application/vnd.adobe.xfdf' => 'xfdf',
|
||||
'application/vnd.ahead.space' => 'ahead',
|
||||
'application/vnd.airzip.filesecure.azf' => 'azf',
|
||||
'application/vnd.airzip.filesecure.azs' => 'azs',
|
||||
'application/vnd.amazon.ebook' => 'azw',
|
||||
'application/vnd.americandynamics.acc' => 'acc',
|
||||
'application/vnd.amiga.ami' => 'ami',
|
||||
'application/vnd.android.package-archive' => 'apk',
|
||||
'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
|
||||
'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
|
||||
'application/vnd.antix.game-component' => 'atx',
|
||||
'application/vnd.apple.installer+xml' => 'mpkg',
|
||||
'application/vnd.apple.mpegurl' => 'm3u8',
|
||||
'application/vnd.aristanetworks.swi' => 'swi',
|
||||
'application/vnd.astraea-software.iota' => 'iota',
|
||||
'application/vnd.audiograph' => 'aep',
|
||||
'application/vnd.blueice.multipass' => 'mpm',
|
||||
'application/vnd.bmi' => 'bmi',
|
||||
'application/vnd.businessobjects' => 'rep',
|
||||
'application/vnd.chemdraw+xml' => 'cdxml',
|
||||
'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
|
||||
'application/vnd.cinderella' => 'cdy',
|
||||
'application/vnd.claymore' => 'cla',
|
||||
'application/vnd.cloanto.rp9' => 'rp9',
|
||||
'application/vnd.clonk.c4group' => 'c4g',
|
||||
'application/vnd.cluetrust.cartomobile-config' => 'c11amc',
|
||||
'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz',
|
||||
'application/vnd.commonspace' => 'csp',
|
||||
'application/vnd.contact.cmsg' => 'cdbcmsg',
|
||||
'application/vnd.cosmocaller' => 'cmc',
|
||||
'application/vnd.crick.clicker' => 'clkx',
|
||||
'application/vnd.crick.clicker.keyboard' => 'clkk',
|
||||
'application/vnd.crick.clicker.palette' => 'clkp',
|
||||
'application/vnd.crick.clicker.template' => 'clkt',
|
||||
'application/vnd.crick.clicker.wordbank' => 'clkw',
|
||||
'application/vnd.criticaltools.wbs+xml' => 'wbs',
|
||||
'application/vnd.ctc-posml' => 'pml',
|
||||
'application/vnd.cups-ppd' => 'ppd',
|
||||
'application/vnd.curl.car' => 'car',
|
||||
'application/vnd.curl.pcurl' => 'pcurl',
|
||||
'application/vnd.dart' => 'dart',
|
||||
'application/vnd.data-vision.rdz' => 'rdz',
|
||||
'application/vnd.dece.data' => 'uvf',
|
||||
'application/vnd.dece.ttml+xml' => 'uvt',
|
||||
'application/vnd.dece.unspecified' => 'uvx',
|
||||
'application/vnd.dece.zip' => 'uvz',
|
||||
'application/vnd.denovo.fcselayout-link' => 'fe_launch',
|
||||
'application/vnd.dna' => 'dna',
|
||||
'application/vnd.dolby.mlp' => 'mlp',
|
||||
'application/vnd.dpgraph' => 'dpg',
|
||||
'application/vnd.dreamfactory' => 'dfac',
|
||||
'application/vnd.ds-keypoint' => 'kpxx',
|
||||
'application/vnd.dvb.ait' => 'ait',
|
||||
'application/vnd.dvb.service' => 'svc',
|
||||
'application/vnd.dynageo' => 'geo',
|
||||
'application/vnd.ecowin.chart' => 'mag',
|
||||
'application/vnd.enliven' => 'nml',
|
||||
'application/vnd.epson.esf' => 'esf',
|
||||
'application/vnd.epson.msf' => 'msf',
|
||||
'application/vnd.epson.quickanime' => 'qam',
|
||||
'application/vnd.epson.salt' => 'slt',
|
||||
'application/vnd.epson.ssf' => 'ssf',
|
||||
'application/vnd.eszigno3+xml' => 'es3',
|
||||
'application/vnd.ezpix-album' => 'ez2',
|
||||
'application/vnd.ezpix-package' => 'ez3',
|
||||
'application/vnd.fdf' => 'fdf',
|
||||
'application/vnd.fdsn.mseed' => 'mseed',
|
||||
'application/vnd.fdsn.seed' => 'seed',
|
||||
'application/vnd.flographit' => 'gph',
|
||||
'application/vnd.fluxtime.clip' => 'ftc',
|
||||
'application/vnd.framemaker' => 'fm',
|
||||
'application/vnd.frogans.fnc' => 'fnc',
|
||||
'application/vnd.frogans.ltf' => 'ltf',
|
||||
'application/vnd.fsc.weblaunch' => 'fsc',
|
||||
'application/vnd.fujitsu.oasys' => 'oas',
|
||||
'application/vnd.fujitsu.oasys2' => 'oa2',
|
||||
'application/vnd.fujitsu.oasys3' => 'oa3',
|
||||
'application/vnd.fujitsu.oasysgp' => 'fg5',
|
||||
'application/vnd.fujitsu.oasysprs' => 'bh2',
|
||||
'application/vnd.fujixerox.ddd' => 'ddd',
|
||||
'application/vnd.fujixerox.docuworks' => 'xdw',
|
||||
'application/vnd.fujixerox.docuworks.binder' => 'xbd',
|
||||
'application/vnd.fuzzysheet' => 'fzs',
|
||||
'application/vnd.genomatix.tuxedo' => 'txd',
|
||||
'application/vnd.geogebra.file' => 'ggb',
|
||||
'application/vnd.geogebra.tool' => 'ggt',
|
||||
'application/vnd.geometry-explorer' => 'gex',
|
||||
'application/vnd.geonext' => 'gxt',
|
||||
'application/vnd.geoplan' => 'g2w',
|
||||
'application/vnd.geospace' => 'g3w',
|
||||
'application/vnd.gmx' => 'gmx',
|
||||
'application/vnd.google-earth.kml+xml' => 'kml',
|
||||
'application/vnd.google-earth.kmz' => 'kmz',
|
||||
'application/vnd.grafeq' => 'gqf',
|
||||
'application/vnd.groove-account' => 'gac',
|
||||
'application/vnd.groove-help' => 'ghf',
|
||||
'application/vnd.groove-identity-message' => 'gim',
|
||||
'application/vnd.groove-injector' => 'grv',
|
||||
'application/vnd.groove-tool-message' => 'gtm',
|
||||
'application/vnd.groove-tool-template' => 'tpl',
|
||||
'application/vnd.groove-vcard' => 'vcg',
|
||||
'application/vnd.hal+xml' => 'hal',
|
||||
'application/vnd.handheld-entertainment+xml' => 'zmm',
|
||||
'application/vnd.hbci' => 'hbci',
|
||||
'application/vnd.hhe.lesson-player' => 'les',
|
||||
'application/vnd.hp-hpgl' => 'hpgl',
|
||||
'application/vnd.hp-hpid' => 'hpid',
|
||||
'application/vnd.hp-hps' => 'hps',
|
||||
'application/vnd.hp-jlyt' => 'jlt',
|
||||
'application/vnd.hp-pcl' => 'pcl',
|
||||
'application/vnd.hp-pclxl' => 'pclxl',
|
||||
'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
|
||||
'application/vnd.ibm.minipay' => 'mpy',
|
||||
'application/vnd.ibm.modcap' => 'afp',
|
||||
'application/vnd.ibm.rights-management' => 'irm',
|
||||
'application/vnd.ibm.secure-container' => 'sc',
|
||||
'application/vnd.iccprofile' => 'icc',
|
||||
'application/vnd.igloader' => 'igl',
|
||||
'application/vnd.immervision-ivp' => 'ivp',
|
||||
'application/vnd.immervision-ivu' => 'ivu',
|
||||
'application/vnd.insors.igm' => 'igm',
|
||||
'application/vnd.intercon.formnet' => 'xpw',
|
||||
'application/vnd.intergeo' => 'i2g',
|
||||
'application/vnd.intu.qbo' => 'qbo',
|
||||
'application/vnd.intu.qfx' => 'qfx',
|
||||
'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
|
||||
'application/vnd.irepository.package+xml' => 'irp',
|
||||
'application/vnd.is-xpr' => 'xpr',
|
||||
'application/vnd.isac.fcs' => 'fcs',
|
||||
'application/vnd.jam' => 'jam',
|
||||
'application/vnd.jcp.javame.midlet-rms' => 'rms',
|
||||
'application/vnd.jisp' => 'jisp',
|
||||
'application/vnd.joost.joda-archive' => 'joda',
|
||||
'application/vnd.kahootz' => 'ktz',
|
||||
'application/vnd.kde.karbon' => 'karbon',
|
||||
'application/vnd.kde.kchart' => 'chrt',
|
||||
'application/vnd.kde.kformula' => 'kfo',
|
||||
'application/vnd.kde.kivio' => 'flw',
|
||||
'application/vnd.kde.kontour' => 'kon',
|
||||
'application/vnd.kde.kpresenter' => 'kpr',
|
||||
'application/vnd.kde.kspread' => 'ksp',
|
||||
'application/vnd.kde.kword' => 'kwd',
|
||||
'application/vnd.kenameaapp' => 'htke',
|
||||
'application/vnd.kidspiration' => 'kia',
|
||||
'application/vnd.kinar' => 'kne',
|
||||
'application/vnd.koan' => 'skp',
|
||||
'application/vnd.kodak-descriptor' => 'sse',
|
||||
'application/vnd.las.las+xml' => 'lasxml',
|
||||
'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
|
||||
'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
|
||||
'application/vnd.lotus-1-2-3' => '123',
|
||||
'application/vnd.lotus-approach' => 'apr',
|
||||
'application/vnd.lotus-freelance' => 'pre',
|
||||
'application/vnd.lotus-notes' => 'nsf',
|
||||
'application/vnd.lotus-organizer' => 'org',
|
||||
'application/vnd.lotus-screencam' => 'scm',
|
||||
'application/vnd.lotus-wordpro' => 'lwp',
|
||||
'application/vnd.macports.portpkg' => 'portpkg',
|
||||
'application/vnd.mcd' => 'mcd',
|
||||
'application/vnd.medcalcdata' => 'mc1',
|
||||
'application/vnd.mediastation.cdkey' => 'cdkey',
|
||||
'application/vnd.mfer' => 'mwf',
|
||||
'application/vnd.mfmp' => 'mfm',
|
||||
'application/vnd.micrografx.flo' => 'flo',
|
||||
'application/vnd.micrografx.igx' => 'igx',
|
||||
'application/vnd.mif' => 'mif',
|
||||
'application/vnd.mobius.daf' => 'daf',
|
||||
'application/vnd.mobius.dis' => 'dis',
|
||||
'application/vnd.mobius.mbk' => 'mbk',
|
||||
'application/vnd.mobius.mqy' => 'mqy',
|
||||
'application/vnd.mobius.msl' => 'msl',
|
||||
'application/vnd.mobius.plc' => 'plc',
|
||||
'application/vnd.mobius.txf' => 'txf',
|
||||
'application/vnd.mophun.application' => 'mpn',
|
||||
'application/vnd.mophun.certificate' => 'mpc',
|
||||
'application/vnd.mozilla.xul+xml' => 'xul',
|
||||
'application/vnd.ms-artgalry' => 'cil',
|
||||
'application/vnd.ms-cab-compressed' => 'cab',
|
||||
'application/vnd.ms-excel' => 'xls',
|
||||
'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
|
||||
'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
|
||||
'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
|
||||
'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
|
||||
'application/vnd.ms-fontobject' => 'eot',
|
||||
'application/vnd.ms-htmlhelp' => 'chm',
|
||||
'application/vnd.ms-ims' => 'ims',
|
||||
'application/vnd.ms-lrm' => 'lrm',
|
||||
'application/vnd.ms-officetheme' => 'thmx',
|
||||
'application/vnd.ms-pki.seccat' => 'cat',
|
||||
'application/vnd.ms-pki.stl' => 'stl',
|
||||
'application/vnd.ms-powerpoint' => 'ppt',
|
||||
'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
|
||||
'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
|
||||
'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
|
||||
'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
|
||||
'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
|
||||
'application/vnd.ms-project' => 'mpp',
|
||||
'application/vnd.ms-word.document.macroenabled.12' => 'docm',
|
||||
'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
|
||||
'application/vnd.ms-works' => 'wps',
|
||||
'application/vnd.ms-wpl' => 'wpl',
|
||||
'application/vnd.ms-xpsdocument' => 'xps',
|
||||
'application/vnd.mseq' => 'mseq',
|
||||
'application/vnd.musician' => 'mus',
|
||||
'application/vnd.muvee.style' => 'msty',
|
||||
'application/vnd.mynfc' => 'taglet',
|
||||
'application/vnd.neurolanguage.nlu' => 'nlu',
|
||||
'application/vnd.nitf' => 'ntf',
|
||||
'application/vnd.noblenet-directory' => 'nnd',
|
||||
'application/vnd.noblenet-sealer' => 'nns',
|
||||
'application/vnd.noblenet-web' => 'nnw',
|
||||
'application/vnd.nokia.n-gage.data' => 'ngdat',
|
||||
'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
|
||||
'application/vnd.nokia.radio-preset' => 'rpst',
|
||||
'application/vnd.nokia.radio-presets' => 'rpss',
|
||||
'application/vnd.novadigm.edm' => 'edm',
|
||||
'application/vnd.novadigm.edx' => 'edx',
|
||||
'application/vnd.novadigm.ext' => 'ext',
|
||||
'application/vnd.oasis.opendocument.chart' => 'odc',
|
||||
'application/vnd.oasis.opendocument.chart-template' => 'otc',
|
||||
'application/vnd.oasis.opendocument.database' => 'odb',
|
||||
'application/vnd.oasis.opendocument.formula' => 'odf',
|
||||
'application/vnd.oasis.opendocument.formula-template' => 'odft',
|
||||
'application/vnd.oasis.opendocument.graphics' => 'odg',
|
||||
'application/vnd.oasis.opendocument.graphics-template' => 'otg',
|
||||
'application/vnd.oasis.opendocument.image' => 'odi',
|
||||
'application/vnd.oasis.opendocument.image-template' => 'oti',
|
||||
'application/vnd.oasis.opendocument.presentation' => 'odp',
|
||||
'application/vnd.oasis.opendocument.presentation-template' => 'otp',
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
|
||||
'application/vnd.oasis.opendocument.text' => 'odt',
|
||||
'application/vnd.oasis.opendocument.text-master' => 'odm',
|
||||
'application/vnd.oasis.opendocument.text-template' => 'ott',
|
||||
'application/vnd.oasis.opendocument.text-web' => 'oth',
|
||||
'application/vnd.olpc-sugar' => 'xo',
|
||||
'application/vnd.oma.dd2+xml' => 'dd2',
|
||||
'application/vnd.openofficeorg.extension' => 'oxt',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
|
||||
'application/vnd.osgeo.mapguide.package' => 'mgp',
|
||||
'application/vnd.osgi.dp' => 'dp',
|
||||
'application/vnd.osgi.subsystem' => 'esa',
|
||||
'application/vnd.palm' => 'pdb',
|
||||
'application/vnd.pawaafile' => 'paw',
|
||||
'application/vnd.pg.format' => 'str',
|
||||
'application/vnd.pg.osasli' => 'ei6',
|
||||
'application/vnd.picsel' => 'efif',
|
||||
'application/vnd.pmi.widget' => 'wg',
|
||||
'application/vnd.pocketlearn' => 'plf',
|
||||
'application/vnd.powerbuilder6' => 'pbd',
|
||||
'application/vnd.previewsystems.box' => 'box',
|
||||
'application/vnd.proteus.magazine' => 'mgz',
|
||||
'application/vnd.publishare-delta-tree' => 'qps',
|
||||
'application/vnd.pvi.ptid1' => 'ptid',
|
||||
'application/vnd.quark.quarkxpress' => 'qxd',
|
||||
'application/vnd.realvnc.bed' => 'bed',
|
||||
'application/vnd.recordare.musicxml' => 'mxl',
|
||||
'application/vnd.recordare.musicxml+xml' => 'musicxml',
|
||||
'application/vnd.rig.cryptonote' => 'cryptonote',
|
||||
'application/vnd.rim.cod' => 'cod',
|
||||
'application/vnd.rn-realmedia' => 'rm',
|
||||
'application/vnd.rn-realmedia-vbr' => 'rmvb',
|
||||
'application/vnd.route66.link66+xml' => 'link66',
|
||||
'application/vnd.sailingtracker.track' => 'st',
|
||||
'application/vnd.seemail' => 'see',
|
||||
'application/vnd.sema' => 'sema',
|
||||
'application/vnd.semd' => 'semd',
|
||||
'application/vnd.semf' => 'semf',
|
||||
'application/vnd.shana.informed.formdata' => 'ifm',
|
||||
'application/vnd.shana.informed.formtemplate' => 'itp',
|
||||
'application/vnd.shana.informed.interchange' => 'iif',
|
||||
'application/vnd.shana.informed.package' => 'ipk',
|
||||
'application/vnd.simtech-mindmapper' => 'twd',
|
||||
'application/vnd.smaf' => 'mmf',
|
||||
'application/vnd.smart.teacher' => 'teacher',
|
||||
'application/vnd.solent.sdkm+xml' => 'sdkm',
|
||||
'application/vnd.spotfire.dxp' => 'dxp',
|
||||
'application/vnd.spotfire.sfs' => 'sfs',
|
||||
'application/vnd.stardivision.calc' => 'sdc',
|
||||
'application/vnd.stardivision.draw' => 'sda',
|
||||
'application/vnd.stardivision.impress' => 'sdd',
|
||||
'application/vnd.stardivision.math' => 'smf',
|
||||
'application/vnd.stardivision.writer' => 'sdw',
|
||||
'application/vnd.stardivision.writer-global' => 'sgl',
|
||||
'application/vnd.stepmania.package' => 'smzip',
|
||||
'application/vnd.stepmania.stepchart' => 'sm',
|
||||
'application/vnd.sun.xml.calc' => 'sxc',
|
||||
'application/vnd.sun.xml.calc.template' => 'stc',
|
||||
'application/vnd.sun.xml.draw' => 'sxd',
|
||||
'application/vnd.sun.xml.draw.template' => 'std',
|
||||
'application/vnd.sun.xml.impress' => 'sxi',
|
||||
'application/vnd.sun.xml.impress.template' => 'sti',
|
||||
'application/vnd.sun.xml.math' => 'sxm',
|
||||
'application/vnd.sun.xml.writer' => 'sxw',
|
||||
'application/vnd.sun.xml.writer.global' => 'sxg',
|
||||
'application/vnd.sun.xml.writer.template' => 'stw',
|
||||
'application/vnd.sus-calendar' => 'sus',
|
||||
'application/vnd.svd' => 'svd',
|
||||
'application/vnd.symbian.install' => 'sis',
|
||||
'application/vnd.syncml+xml' => 'xsm',
|
||||
'application/vnd.syncml.dm+wbxml' => 'bdm',
|
||||
'application/vnd.syncml.dm+xml' => 'xdm',
|
||||
'application/vnd.tao.intent-module-archive' => 'tao',
|
||||
'application/vnd.tcpdump.pcap' => 'pcap',
|
||||
'application/vnd.tmobile-livetv' => 'tmo',
|
||||
'application/vnd.trid.tpt' => 'tpt',
|
||||
'application/vnd.triscape.mxs' => 'mxs',
|
||||
'application/vnd.trueapp' => 'tra',
|
||||
'application/vnd.ufdl' => 'ufd',
|
||||
'application/vnd.uiq.theme' => 'utz',
|
||||
'application/vnd.umajin' => 'umj',
|
||||
'application/vnd.unity' => 'unityweb',
|
||||
'application/vnd.uoml+xml' => 'uoml',
|
||||
'application/vnd.vcx' => 'vcx',
|
||||
'application/vnd.visio' => 'vsd',
|
||||
'application/vnd.visionary' => 'vis',
|
||||
'application/vnd.vsf' => 'vsf',
|
||||
'application/vnd.wap.wbxml' => 'wbxml',
|
||||
'application/vnd.wap.wmlc' => 'wmlc',
|
||||
'application/vnd.wap.wmlscriptc' => 'wmlsc',
|
||||
'application/vnd.webturbo' => 'wtb',
|
||||
'application/vnd.wolfram.player' => 'nbp',
|
||||
'application/vnd.wordperfect' => 'wpd',
|
||||
'application/vnd.wqd' => 'wqd',
|
||||
'application/vnd.wt.stf' => 'stf',
|
||||
'application/vnd.xara' => 'xar',
|
||||
'application/vnd.xfdl' => 'xfdl',
|
||||
'application/vnd.yamaha.hv-dic' => 'hvd',
|
||||
'application/vnd.yamaha.hv-script' => 'hvs',
|
||||
'application/vnd.yamaha.hv-voice' => 'hvp',
|
||||
'application/vnd.yamaha.openscoreformat' => 'osf',
|
||||
'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
|
||||
'application/vnd.yamaha.smaf-audio' => 'saf',
|
||||
'application/vnd.yamaha.smaf-phrase' => 'spf',
|
||||
'application/vnd.yellowriver-custom-menu' => 'cmp',
|
||||
'application/vnd.zul' => 'zir',
|
||||
'application/vnd.zzazz.deck+xml' => 'zaz',
|
||||
'application/voicexml+xml' => 'vxml',
|
||||
'application/widget' => 'wgt',
|
||||
'application/winhlp' => 'hlp',
|
||||
'application/wsdl+xml' => 'wsdl',
|
||||
'application/wspolicy+xml' => 'wspolicy',
|
||||
'application/x-7z-compressed' => '7z',
|
||||
'application/x-abiword' => 'abw',
|
||||
'application/x-ace-compressed' => 'ace',
|
||||
'application/x-apple-diskimage' => 'dmg',
|
||||
'application/x-authorware-bin' => 'aab',
|
||||
'application/x-authorware-map' => 'aam',
|
||||
'application/x-authorware-seg' => 'aas',
|
||||
'application/x-bcpio' => 'bcpio',
|
||||
'application/x-bittorrent' => 'torrent',
|
||||
'application/x-blorb' => 'blb',
|
||||
'application/x-bzip' => 'bz',
|
||||
'application/x-bzip2' => 'bz2',
|
||||
'application/x-cbr' => 'cbr',
|
||||
'application/x-cdlink' => 'vcd',
|
||||
'application/x-cfs-compressed' => 'cfs',
|
||||
'application/x-chat' => 'chat',
|
||||
'application/x-chess-pgn' => 'pgn',
|
||||
'application/x-conference' => 'nsc',
|
||||
'application/x-cpio' => 'cpio',
|
||||
'application/x-csh' => 'csh',
|
||||
'application/x-debian-package' => 'deb',
|
||||
'application/x-dgc-compressed' => 'dgc',
|
||||
'application/x-director' => 'dir',
|
||||
'application/x-doom' => 'wad',
|
||||
'application/x-dtbncx+xml' => 'ncx',
|
||||
'application/x-dtbook+xml' => 'dtb',
|
||||
'application/x-dtbresource+xml' => 'res',
|
||||
'application/x-dvi' => 'dvi',
|
||||
'application/x-envoy' => 'evy',
|
||||
'application/x-eva' => 'eva',
|
||||
'application/x-font-bdf' => 'bdf',
|
||||
'application/x-font-ghostscript' => 'gsf',
|
||||
'application/x-font-linux-psf' => 'psf',
|
||||
'application/x-font-otf' => 'otf',
|
||||
'application/x-font-pcf' => 'pcf',
|
||||
'application/x-font-snf' => 'snf',
|
||||
'application/x-font-ttf' => 'ttf',
|
||||
'application/x-font-type1' => 'pfa',
|
||||
'application/x-font-woff' => 'woff',
|
||||
'application/x-freearc' => 'arc',
|
||||
'application/x-futuresplash' => 'spl',
|
||||
'application/x-gca-compressed' => 'gca',
|
||||
'application/x-glulx' => 'ulx',
|
||||
'application/x-gnumeric' => 'gnumeric',
|
||||
'application/x-gramps-xml' => 'gramps',
|
||||
'application/x-gtar' => 'gtar',
|
||||
'application/x-hdf' => 'hdf',
|
||||
'application/x-install-instructions' => 'install',
|
||||
'application/x-iso9660-image' => 'iso',
|
||||
'application/x-java-jnlp-file' => 'jnlp',
|
||||
'application/x-latex' => 'latex',
|
||||
'application/x-lzh-compressed' => 'lzh',
|
||||
'application/x-mie' => 'mie',
|
||||
'application/x-mobipocket-ebook' => 'prc',
|
||||
'application/x-ms-application' => 'application',
|
||||
'application/x-ms-shortcut' => 'lnk',
|
||||
'application/x-ms-wmd' => 'wmd',
|
||||
'application/x-ms-wmz' => 'wmz',
|
||||
'application/x-ms-xbap' => 'xbap',
|
||||
'application/x-msaccess' => 'mdb',
|
||||
'application/x-msbinder' => 'obd',
|
||||
'application/x-mscardfile' => 'crd',
|
||||
'application/x-msclip' => 'clp',
|
||||
'application/x-msdownload' => 'exe',
|
||||
'application/x-msmediaview' => 'mvb',
|
||||
'application/x-msmetafile' => 'wmf',
|
||||
'application/x-msmoney' => 'mny',
|
||||
'application/x-mspublisher' => 'pub',
|
||||
'application/x-msschedule' => 'scd',
|
||||
'application/x-msterminal' => 'trm',
|
||||
'application/x-mswrite' => 'wri',
|
||||
'application/x-netcdf' => 'nc',
|
||||
'application/x-nzb' => 'nzb',
|
||||
'application/x-pkcs12' => 'p12',
|
||||
'application/x-pkcs7-certificates' => 'p7b',
|
||||
'application/x-pkcs7-certreqresp' => 'p7r',
|
||||
'application/x-rar-compressed' => 'rar',
|
||||
'application/x-rar' => 'rar',
|
||||
'application/x-research-info-systems' => 'ris',
|
||||
'application/x-sh' => 'sh',
|
||||
'application/x-shar' => 'shar',
|
||||
'application/x-shockwave-flash' => 'swf',
|
||||
'application/x-silverlight-app' => 'xap',
|
||||
'application/x-sql' => 'sql',
|
||||
'application/x-stuffit' => 'sit',
|
||||
'application/x-stuffitx' => 'sitx',
|
||||
'application/x-subrip' => 'srt',
|
||||
'application/x-sv4cpio' => 'sv4cpio',
|
||||
'application/x-sv4crc' => 'sv4crc',
|
||||
'application/x-t3vm-image' => 't3',
|
||||
'application/x-tads' => 'gam',
|
||||
'application/x-tar' => 'tar',
|
||||
'application/x-tcl' => 'tcl',
|
||||
'application/x-tex' => 'tex',
|
||||
'application/x-tex-tfm' => 'tfm',
|
||||
'application/x-texinfo' => 'texinfo',
|
||||
'application/x-tgif' => 'obj',
|
||||
'application/x-ustar' => 'ustar',
|
||||
'application/x-wais-source' => 'src',
|
||||
'application/x-x509-ca-cert' => 'der',
|
||||
'application/x-xfig' => 'fig',
|
||||
'application/x-xliff+xml' => 'xlf',
|
||||
'application/x-xpinstall' => 'xpi',
|
||||
'application/x-xz' => 'xz',
|
||||
'application/x-zmachine' => 'z1',
|
||||
'application/xaml+xml' => 'xaml',
|
||||
'application/xcap-diff+xml' => 'xdf',
|
||||
'application/xenc+xml' => 'xenc',
|
||||
'application/xhtml+xml' => 'xhtml',
|
||||
'application/xml' => 'xml',
|
||||
'application/xml-dtd' => 'dtd',
|
||||
'application/xop+xml' => 'xop',
|
||||
'application/xproc+xml' => 'xpl',
|
||||
'application/xslt+xml' => 'xslt',
|
||||
'application/xspf+xml' => 'xspf',
|
||||
'application/xv+xml' => 'mxml',
|
||||
'application/yang' => 'yang',
|
||||
'application/yin+xml' => 'yin',
|
||||
'application/zip' => 'zip',
|
||||
'audio/adpcm' => 'adp',
|
||||
'audio/basic' => 'au',
|
||||
'audio/midi' => 'mid',
|
||||
'audio/mp3' => 'mp3',
|
||||
'audio/mp4' => 'mp4a',
|
||||
'audio/mpeg' => 'mpga',
|
||||
'audio/ogg' => 'oga',
|
||||
'audio/s3m' => 's3m',
|
||||
'audio/silk' => 'sil',
|
||||
'audio/vnd.dece.audio' => 'uva',
|
||||
'audio/vnd.digital-winds' => 'eol',
|
||||
'audio/vnd.dra' => 'dra',
|
||||
'audio/vnd.dts' => 'dts',
|
||||
'audio/vnd.dts.hd' => 'dtshd',
|
||||
'audio/vnd.lucent.voice' => 'lvp',
|
||||
'audio/vnd.ms-playready.media.pya' => 'pya',
|
||||
'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
|
||||
'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
|
||||
'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
|
||||
'audio/vnd.rip' => 'rip',
|
||||
'audio/webm' => 'weba',
|
||||
'audio/x-aac' => 'aac',
|
||||
'audio/x-aiff' => 'aif',
|
||||
'audio/x-caf' => 'caf',
|
||||
'audio/x-flac' => 'flac',
|
||||
'audio/x-matroska' => 'mka',
|
||||
'audio/x-mpegurl' => 'm3u',
|
||||
'audio/x-ms-wax' => 'wax',
|
||||
'audio/x-ms-wma' => 'wma',
|
||||
'audio/x-pn-realaudio' => 'ram',
|
||||
'audio/x-pn-realaudio-plugin' => 'rmp',
|
||||
'audio/x-wav' => 'wav',
|
||||
'audio/xm' => 'xm',
|
||||
'chemical/x-cdx' => 'cdx',
|
||||
'chemical/x-cif' => 'cif',
|
||||
'chemical/x-cmdf' => 'cmdf',
|
||||
'chemical/x-cml' => 'cml',
|
||||
'chemical/x-csml' => 'csml',
|
||||
'chemical/x-xyz' => 'xyz',
|
||||
'image/bmp' => 'bmp',
|
||||
'image/x-ms-bmp' => 'bmp',
|
||||
'image/cgm' => 'cgm',
|
||||
'image/g3fax' => 'g3',
|
||||
'image/gif' => 'gif',
|
||||
'image/ief' => 'ief',
|
||||
'image/jpeg' => 'jpeg',
|
||||
'image/pjpeg' => 'jpeg',
|
||||
'image/ktx' => 'ktx',
|
||||
'image/png' => 'png',
|
||||
'image/prs.btif' => 'btif',
|
||||
'image/sgi' => 'sgi',
|
||||
'image/svg+xml' => 'svg',
|
||||
'image/tiff' => 'tiff',
|
||||
'image/vnd.adobe.photoshop' => 'psd',
|
||||
'image/vnd.dece.graphic' => 'uvi',
|
||||
'image/vnd.dvb.subtitle' => 'sub',
|
||||
'image/vnd.djvu' => 'djvu',
|
||||
'image/vnd.dwg' => 'dwg',
|
||||
'image/vnd.dxf' => 'dxf',
|
||||
'image/vnd.fastbidsheet' => 'fbs',
|
||||
'image/vnd.fpx' => 'fpx',
|
||||
'image/vnd.fst' => 'fst',
|
||||
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
|
||||
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
|
||||
'image/vnd.ms-modi' => 'mdi',
|
||||
'image/vnd.ms-photo' => 'wdp',
|
||||
'image/vnd.net-fpx' => 'npx',
|
||||
'image/vnd.wap.wbmp' => 'wbmp',
|
||||
'image/vnd.xiff' => 'xif',
|
||||
'image/webp' => 'webp',
|
||||
'image/x-3ds' => '3ds',
|
||||
'image/x-cmu-raster' => 'ras',
|
||||
'image/x-cmx' => 'cmx',
|
||||
'image/x-freehand' => 'fh',
|
||||
'image/x-icon' => 'ico',
|
||||
'image/x-mrsid-image' => 'sid',
|
||||
'image/x-pcx' => 'pcx',
|
||||
'image/x-pict' => 'pic',
|
||||
'image/x-portable-anymap' => 'pnm',
|
||||
'image/x-portable-bitmap' => 'pbm',
|
||||
'image/x-portable-graymap' => 'pgm',
|
||||
'image/x-portable-pixmap' => 'ppm',
|
||||
'image/x-rgb' => 'rgb',
|
||||
'image/x-tga' => 'tga',
|
||||
'image/x-xbitmap' => 'xbm',
|
||||
'image/x-xpixmap' => 'xpm',
|
||||
'image/x-xwindowdump' => 'xwd',
|
||||
'message/rfc822' => 'eml',
|
||||
'model/iges' => 'igs',
|
||||
'model/mesh' => 'msh',
|
||||
'model/vnd.collada+xml' => 'dae',
|
||||
'model/vnd.dwf' => 'dwf',
|
||||
'model/vnd.gdl' => 'gdl',
|
||||
'model/vnd.gtw' => 'gtw',
|
||||
'model/vnd.mts' => 'mts',
|
||||
'model/vnd.vtu' => 'vtu',
|
||||
'model/vrml' => 'wrl',
|
||||
'model/x3d+binary' => 'x3db',
|
||||
'model/x3d+vrml' => 'x3dv',
|
||||
'model/x3d+xml' => 'x3d',
|
||||
'text/cache-manifest' => 'appcache',
|
||||
'text/calendar' => 'ics',
|
||||
'text/css' => 'css',
|
||||
'text/csv' => 'csv',
|
||||
'text/html' => 'html',
|
||||
'text/n3' => 'n3',
|
||||
'text/plain' => 'txt',
|
||||
'text/prs.lines.tag' => 'dsc',
|
||||
'text/richtext' => 'rtx',
|
||||
'text/rtf' => 'rtf',
|
||||
'text/sgml' => 'sgml',
|
||||
'text/tab-separated-values' => 'tsv',
|
||||
'text/troff' => 't',
|
||||
'text/turtle' => 'ttl',
|
||||
'text/uri-list' => 'uri',
|
||||
'text/vcard' => 'vcard',
|
||||
'text/vnd.curl' => 'curl',
|
||||
'text/vnd.curl.dcurl' => 'dcurl',
|
||||
'text/vnd.curl.scurl' => 'scurl',
|
||||
'text/vnd.curl.mcurl' => 'mcurl',
|
||||
'text/vnd.dvb.subtitle' => 'sub',
|
||||
'text/vnd.fly' => 'fly',
|
||||
'text/vnd.fmi.flexstor' => 'flx',
|
||||
'text/vnd.graphviz' => 'gv',
|
||||
'text/vnd.in3d.3dml' => '3dml',
|
||||
'text/vnd.in3d.spot' => 'spot',
|
||||
'text/vnd.sun.j2me.app-descriptor' => 'jad',
|
||||
'text/vnd.wap.wml' => 'wml',
|
||||
'text/vnd.wap.wmlscript' => 'wmls',
|
||||
'text/x-asm' => 's',
|
||||
'text/x-c' => 'c',
|
||||
'text/x-fortran' => 'f',
|
||||
'text/x-pascal' => 'p',
|
||||
'text/x-java-source' => 'java',
|
||||
'text/x-opml' => 'opml',
|
||||
'text/x-nfo' => 'nfo',
|
||||
'text/x-setext' => 'etx',
|
||||
'text/x-sfv' => 'sfv',
|
||||
'text/x-uuencode' => 'uu',
|
||||
'text/x-vcalendar' => 'vcs',
|
||||
'text/x-vcard' => 'vcf',
|
||||
'video/3gpp' => '3gp',
|
||||
'video/3gpp2' => '3g2',
|
||||
'video/h261' => 'h261',
|
||||
'video/h263' => 'h263',
|
||||
'video/h264' => 'h264',
|
||||
'video/jpeg' => 'jpgv',
|
||||
'video/jpm' => 'jpm',
|
||||
'video/mj2' => 'mj2',
|
||||
'video/mp4' => 'mp4',
|
||||
'video/mpeg' => 'mpeg',
|
||||
'video/ogg' => 'ogv',
|
||||
'video/quicktime' => 'qt',
|
||||
'video/vnd.dece.hd' => 'uvh',
|
||||
'video/vnd.dece.mobile' => 'uvm',
|
||||
'video/vnd.dece.pd' => 'uvp',
|
||||
'video/vnd.dece.sd' => 'uvs',
|
||||
'video/vnd.dece.video' => 'uvv',
|
||||
'video/vnd.dvb.file' => 'dvb',
|
||||
'video/vnd.fvt' => 'fvt',
|
||||
'video/vnd.mpegurl' => 'mxu',
|
||||
'video/vnd.ms-playready.media.pyv' => 'pyv',
|
||||
'video/vnd.uvvu.mp4' => 'uvu',
|
||||
'video/vnd.vivo' => 'viv',
|
||||
'video/webm' => 'webm',
|
||||
'video/x-f4v' => 'f4v',
|
||||
'video/x-fli' => 'fli',
|
||||
'video/x-flv' => 'flv',
|
||||
'video/x-m4v' => 'm4v',
|
||||
'video/x-matroska' => 'mkv',
|
||||
'video/x-mng' => 'mng',
|
||||
'video/x-ms-asf' => 'asf',
|
||||
'video/x-ms-vob' => 'vob',
|
||||
'video/x-ms-wm' => 'wm',
|
||||
'video/x-ms-wmv' => 'wmv',
|
||||
'video/x-ms-wmx' => 'wmx',
|
||||
'video/x-ms-wvx' => 'wvx',
|
||||
'video/x-msvideo' => 'avi',
|
||||
'video/x-sgi-movie' => 'movie',
|
||||
'video/x-smv' => 'smv',
|
||||
'x-conference/x-cooltalk' => 'ice'
|
||||
];
|
||||
|
||||
/**
|
||||
* Get extension by mime type
|
||||
*
|
||||
* @param string $mimeType
|
||||
* @return string|null
|
||||
*/
|
||||
public function getExtension(string $mimeType)
|
||||
{
|
||||
return isset($this->mimeTypes[$mimeType])? $this->mimeTypes[$mimeType] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mime type by extension
|
||||
*
|
||||
* @param string $extension
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMimeType(string $extension)
|
||||
{
|
||||
$key = array_search($extension, $this->mimeTypes);
|
||||
return $key ?: null;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
class MissingRequiredParameterException extends \Exception
|
||||
{
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
use 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";
|
||||
|
||||
abstract public 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}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
use Exception;
|
||||
|
||||
class RuleNotFoundException extends Exception
|
||||
{
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
class RuleQuashException extends \Exception
|
||||
{
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Rule;
|
||||
use 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, []);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Helper;
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Helper;
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules\Interfaces;
|
||||
|
||||
interface BeforeValidate
|
||||
{
|
||||
/**
|
||||
* Before validate hook
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beforeValidate();
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Helper;
|
||||
use Rakit\Validation\MimeTypeGuesser;
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Helper;
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Rule;
|
||||
|
||||
class Nullable extends Rule
|
||||
{
|
||||
/**
|
||||
* Check the $value is valid
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function check($value): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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, []);
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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, []);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules\Traits;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use Rakit\Validation\Helper;
|
||||
use Rakit\Validation\MimeTypeGuesser;
|
||||
use Rakit\Validation\Rule;
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation\Rules;
|
||||
|
||||
use 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);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
||||
+716
@@ -0,0 +1,716 @@
|
||||
<?php
|
||||
|
||||
namespace Rakit\Validation;
|
||||
|
||||
use Closure;
|
||||
use Rakit\Validation\Rules\Interfaces\BeforeValidate;
|
||||
use Rakit\Validation\Rules\Interfaces\ModifyValue;
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user