First Commit
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2016-2019 Muhammad Syifa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+1168
File diff suppressed because it is too large
Load Diff
+36
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "rakit/validation",
|
||||
"description": "PHP Laravel like standalone validation library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"email": "emsifa@gmail.com",
|
||||
"name": "Muhammad Syifa"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Rakit\\Validation\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Rakit\\Validation\\Tests\\": ["tests", "tests/Fixtures"]
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.5",
|
||||
"squizlabs/php_codesniffer": "^3",
|
||||
"php-coveralls/php-coveralls": "^2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"phpunit",
|
||||
"phpcs"
|
||||
]
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Rakit validation coding standard">
|
||||
<description>Rakit validation coding standard</description>
|
||||
|
||||
<!-- display progress -->
|
||||
<arg value="p"/>
|
||||
<!-- use colors in output -->
|
||||
<arg name="colors"/>
|
||||
|
||||
<!-- inherit rules from: -->
|
||||
<rule ref="PSR2"/>
|
||||
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||
|
||||
<!-- Paths to check -->
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
</ruleset>
|
||||
+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