First Local Commit - After Clean up.
Signed-off-by: Rick Hays <rhays@haysgang.com>
This commit is contained in:
338
system/Validation/CreditCardRules.php
Normal file
338
system/Validation/CreditCardRules.php
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
/**
|
||||
* Class CreditCardRules
|
||||
*
|
||||
* Provides validation methods for common credit-card inputs.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Credit_card_number
|
||||
*
|
||||
* @package CodeIgniter\Validation
|
||||
*/
|
||||
class CreditCardRules
|
||||
{
|
||||
|
||||
/**
|
||||
* The cards that we support, with the defining details:
|
||||
*
|
||||
* name - The type of card as found in the form. Must match the user's value
|
||||
* length - List of possible lengths for the card number
|
||||
* prefixes - List of possible prefixes for the card
|
||||
* checkdigit - Boolean on whether we should do a modulus10 check on the numbers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $cards = [
|
||||
'American Express' => [
|
||||
'name' => 'amex',
|
||||
'length' => '15',
|
||||
'prefixes' => '34,37',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'China UnionPay' => [
|
||||
'name' => 'unionpay',
|
||||
'length' => '16,17,18,19',
|
||||
'prefixes' => '62',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Dankort' => [
|
||||
'name' => 'dankort',
|
||||
'length' => '16',
|
||||
'prefixes' => '5019,4175,4571,4',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'DinersClub' => [
|
||||
'name' => 'dinersclub',
|
||||
'length' => '14,16',
|
||||
'prefixes' => '300,301,302,303,304,305,309,36,38,39,54,55',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'DinersClub CarteBlanche' => [
|
||||
'name' => 'carteblanche',
|
||||
'length' => '14',
|
||||
'prefixes' => '300,301,302,303,304,305',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Discover Card' => [
|
||||
'name' => 'discover',
|
||||
'length' => '16,19',
|
||||
'prefixes' => '6011,622,644,645,656,647,648,649,65',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'InterPayment' => [
|
||||
'name' => 'interpayment',
|
||||
'length' => '16,17,18,19',
|
||||
'prefixes' => '4',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'JCB' => [
|
||||
'name' => 'jcb',
|
||||
'length' => '16,17,18,19',
|
||||
'prefixes' => '352,353,354,355,356,357,358',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Maestro' => [
|
||||
'name' => 'maestro',
|
||||
'length' => '12,13,14,15,16,18,19',
|
||||
'prefixes' => '50,56,57,58,59,60,61,62,63,64,65,66,67,68,69',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'MasterCard' => [
|
||||
'name' => 'mastercard',
|
||||
'length' => '16',
|
||||
'prefixes' => '51,52,53,54,55,22,23,24,25,26,27',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'NSPK MIR' => [
|
||||
'name' => 'mir',
|
||||
'length' => '16',
|
||||
'prefixes' => '2200,2201,2202,2203,2204',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Troy' => [
|
||||
'name' => 'troy',
|
||||
'length' => '16',
|
||||
'prefixes' => '979200,979289',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'UATP' => [
|
||||
'name' => 'uatp',
|
||||
'length' => '15',
|
||||
'prefixes' => '1',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Verve' => [
|
||||
'name' => 'verve',
|
||||
'length' => '16,19',
|
||||
'prefixes' => '506,650',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
'Visa' => [
|
||||
'name' => 'visa',
|
||||
'length' => '13,16,19',
|
||||
'prefixes' => '4',
|
||||
'checkdigit' => true,
|
||||
],
|
||||
// Canadian Cards
|
||||
'BMO ABM Card' => [
|
||||
'name' => 'bmoabm',
|
||||
'length' => '16',
|
||||
'prefixes' => '500',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
'CIBC Convenience Card' => [
|
||||
'name' => 'cibc',
|
||||
'length' => '16',
|
||||
'prefixes' => '4506',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
'HSBC Canada Card' => [
|
||||
'name' => 'hsbc',
|
||||
'length' => '16',
|
||||
'prefixes' => '56',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
'Royal Bank of Canada Client Card' => [
|
||||
'name' => 'rbc',
|
||||
'length' => '16',
|
||||
'prefixes' => '45',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
'Scotiabank Scotia Card' => [
|
||||
'name' => 'scotia',
|
||||
'length' => '16',
|
||||
'prefixes' => '4536',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
'TD Canada Trust Access Card' => [
|
||||
'name' => 'tdtrust',
|
||||
'length' => '16',
|
||||
'prefixes' => '589297',
|
||||
'checkdigit' => false,
|
||||
],
|
||||
];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Verifies that a credit card number is valid and matches the known
|
||||
* formats for a wide number of credit card types. This does not verify
|
||||
* that the card is a valid card, only that the number is formatted correctly.
|
||||
*
|
||||
* Example:
|
||||
* $rules = [
|
||||
* 'cc_num' => 'valid_cc_number[visa]'
|
||||
* ];
|
||||
*
|
||||
* @param string $ccNumber
|
||||
* @param string $type
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_cc_number(string $ccNumber = null, string $type, array $data): bool
|
||||
{
|
||||
$type = strtolower($type);
|
||||
$info = null;
|
||||
|
||||
// Get our card info based on provided name.
|
||||
foreach ($this->cards as $card)
|
||||
{
|
||||
if ($card['name'] === $type)
|
||||
{
|
||||
$info = $card;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If empty, it's not a card type we recognize, or invalid type.
|
||||
if (empty($info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we have a valid length
|
||||
if (strlen($ccNumber) === 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove any spaces and dashes
|
||||
$ccNumber = str_replace([' ', '-'], '', $ccNumber);
|
||||
|
||||
// Non-numeric values cannot be a number...duh
|
||||
if (! is_numeric($ccNumber))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure it's a valid length for this card
|
||||
$lengths = explode(',', $info['length']);
|
||||
|
||||
if (! in_array(strlen($ccNumber), $lengths))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure it has a valid prefix
|
||||
$prefixes = explode(',', $info['prefixes']);
|
||||
|
||||
$validPrefix = false;
|
||||
|
||||
foreach ($prefixes as $prefix)
|
||||
{
|
||||
if (strpos($ccNumber, $prefix) === 0)
|
||||
{
|
||||
$validPrefix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($validPrefix === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Still here? Then check the number against the Luhn algorithm, if required
|
||||
// @see https://en.wikipedia.org/wiki/Luhn_algorithm
|
||||
// @see https://gist.github.com/troelskn/1287893
|
||||
if ($info['checkdigit'] === true)
|
||||
{
|
||||
return $this->isValidLuhn($ccNumber);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks the given number to see if the number passing a Luhn check.
|
||||
*
|
||||
* @param string $number
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isValidLuhn(string $number = null): bool
|
||||
{
|
||||
settype($number, 'string');
|
||||
|
||||
$sumTable = [
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8,
|
||||
1,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
9,
|
||||
],
|
||||
];
|
||||
|
||||
$sum = 0;
|
||||
$flip = 0;
|
||||
|
||||
for ($i = strlen($number) - 1; $i >= 0; $i --)
|
||||
{
|
||||
$sum += $sumTable[$flip ++ & 0x1][$number[$i]];
|
||||
}
|
||||
|
||||
return $sum % 10 === 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
32
system/Validation/Exceptions/ValidationException.php
Normal file
32
system/Validation/Exceptions/ValidationException.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php namespace CodeIgniter\Validation\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use CodeIgniter\Exceptions\FrameworkException;
|
||||
|
||||
class ValidationException extends FrameworkException implements ExceptionInterface
|
||||
{
|
||||
public static function forRuleNotFound(string $rule = null)
|
||||
{
|
||||
return new static(lang('Validation.ruleNotFound', [$rule]));
|
||||
}
|
||||
|
||||
public static function forGroupNotFound(string $group = null)
|
||||
{
|
||||
return new static(lang('Validation.groupNotFound', [$group]));
|
||||
}
|
||||
|
||||
public static function forGroupNotArray(string $group = null)
|
||||
{
|
||||
return new static(lang('Validation.groupNotArray', [$group]));
|
||||
}
|
||||
|
||||
public static function forInvalidTemplate(string $template = null)
|
||||
{
|
||||
return new static(lang('Validation.invalidTemplate', [$template]));
|
||||
}
|
||||
|
||||
public static function forNoRuleSets()
|
||||
{
|
||||
return new static(lang('Validation.noRuleSets'));
|
||||
}
|
||||
}
|
||||
317
system/Validation/FileRules.php
Normal file
317
system/Validation/FileRules.php
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* File validation rules
|
||||
*/
|
||||
class FileRules
|
||||
{
|
||||
|
||||
/**
|
||||
* Request instance. So we can get access to the files.
|
||||
*
|
||||
* @var \CodeIgniter\HTTP\RequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
*/
|
||||
public function __construct(RequestInterface $request = null)
|
||||
{
|
||||
if (is_null($request))
|
||||
{
|
||||
$request = Services::request();
|
||||
}
|
||||
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Verifies that $name is the name of a valid uploaded file.
|
||||
*
|
||||
* @param string $blank
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function uploaded(string $blank = null, string $name, array $data): bool
|
||||
{
|
||||
$file = $this->request->getFile($name);
|
||||
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ENVIRONMENT === 'testing')
|
||||
{
|
||||
return $file->getError() === 0;
|
||||
}
|
||||
|
||||
// Note: cannot unit test this; no way to over-ride ENVIRONMENT?
|
||||
// @codeCoverageIgnoreStart
|
||||
return $file->isValid();
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Verifies if the file's size in Kilobytes is no larger than the parameter.
|
||||
*
|
||||
* @param string|null $blank
|
||||
* @param string $params
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function max_size(string $blank = null, string $params, array $data): bool
|
||||
{
|
||||
// Grab the file name off the top of the $params
|
||||
// after we split it.
|
||||
$params = explode(',', $params);
|
||||
$name = array_shift($params);
|
||||
|
||||
if (! ($files = $this->request->getFileMultiple($name)))
|
||||
{
|
||||
$files = [$this->request->getFile($name)];
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($file->getSize() / 1024 > $params[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Uses the mime config file to determine if a file is considered an "image",
|
||||
* which for our purposes basically means that it's a raster image or svg.
|
||||
*
|
||||
* @param string|null $blank
|
||||
* @param string $params
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_image(string $blank = null, string $params, array $data): bool
|
||||
{
|
||||
// Grab the file name off the top of the $params
|
||||
// after we split it.
|
||||
$params = explode(',', $params);
|
||||
$name = array_shift($params);
|
||||
|
||||
if (! ($files = $this->request->getFileMultiple($name)))
|
||||
{
|
||||
$files = [$this->request->getFile($name)];
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We know that our mimes list always has the first mime
|
||||
// start with `image` even when then are multiple accepted types.
|
||||
$type = \Config\Mimes::guessTypeFromExtension($file->getExtension());
|
||||
|
||||
if (mb_strpos($type, 'image') !== 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks to see if an uploaded file's mime type matches one in the parameter.
|
||||
*
|
||||
* @param string|null $blank
|
||||
* @param string $params
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function mime_in(string $blank = null, string $params, array $data): bool
|
||||
{
|
||||
// Grab the file name off the top of the $params
|
||||
// after we split it.
|
||||
$params = explode(',', $params);
|
||||
$name = array_shift($params);
|
||||
|
||||
if (! ($files = $this->request->getFileMultiple($name)))
|
||||
{
|
||||
$files = [$this->request->getFile($name)];
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! in_array($file->getMimeType(), $params))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks to see if an uploaded file's extension matches one in the parameter.
|
||||
*
|
||||
* @param string|null $blank
|
||||
* @param string $params
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function ext_in(string $blank = null, string $params, array $data): bool
|
||||
{
|
||||
// Grab the file name off the top of the $params
|
||||
// after we split it.
|
||||
$params = explode(',', $params);
|
||||
$name = array_shift($params);
|
||||
|
||||
if (! ($files = $this->request->getFileMultiple($name)))
|
||||
{
|
||||
$files = [$this->request->getFile($name)];
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! in_array($file->getExtension(), $params))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks an uploaded file to verify that the dimensions are within
|
||||
* a specified allowable dimension.
|
||||
*
|
||||
* @param string|null $blank
|
||||
* @param string $params
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function max_dims(string $blank = null, string $params, array $data): bool
|
||||
{
|
||||
// Grab the file name off the top of the $params
|
||||
// after we split it.
|
||||
$params = explode(',', $params);
|
||||
$name = array_shift($params);
|
||||
|
||||
if (! ($files = $this->request->getFileMultiple($name)))
|
||||
{
|
||||
$files = [$this->request->getFile($name)];
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (is_null($file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Parameter sizes
|
||||
$allowedWidth = $params[0] ?? 0;
|
||||
$allowedHeight = $params[1] ?? 0;
|
||||
|
||||
// Get uploaded image size
|
||||
$info = getimagesize($file->getTempName());
|
||||
$fileWidth = $info[0];
|
||||
$fileHeight = $info[1];
|
||||
|
||||
if ($fileWidth > $allowedWidth || $fileHeight > $allowedHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
409
system/Validation/FormatRules.php
Normal file
409
system/Validation/FormatRules.php
Normal file
@@ -0,0 +1,409 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
/**
|
||||
* Format validation Rules.
|
||||
*
|
||||
* @package CodeIgniter\Validation
|
||||
*/
|
||||
class FormatRules
|
||||
{
|
||||
|
||||
/**
|
||||
* Alpha
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function alpha(string $str = null): bool
|
||||
{
|
||||
return ctype_alpha($str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Alpha with spaces.
|
||||
*
|
||||
* @param string $value Value.
|
||||
*
|
||||
* @return boolean True if alpha with spaces, else false.
|
||||
*/
|
||||
public function alpha_space(string $value = null): bool
|
||||
{
|
||||
if ($value === null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return (bool) preg_match('/^[A-Z ]+$/i', $value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Alpha-numeric with underscores and dashes
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function alpha_dash(string $str = null): bool
|
||||
{
|
||||
return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Alpha-numeric
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function alpha_numeric(string $str = null): bool
|
||||
{
|
||||
return ctype_alnum($str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Alpha-numeric w/ spaces
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function alpha_numeric_space(string $str = null): bool
|
||||
{
|
||||
return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Any type of string
|
||||
*
|
||||
* Note: we specifically do NOT type hint $str here so that
|
||||
* it doesn't convert numbers into strings.
|
||||
*
|
||||
* @param string|null $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function string($str = null): bool
|
||||
{
|
||||
return is_string($str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Decimal number
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function decimal(string $str = null): bool
|
||||
{
|
||||
return (bool) preg_match('/^[\-+]?[0-9]+(|\.[0-9]+)$/', $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Integer
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function integer(string $str = null): bool
|
||||
{
|
||||
return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is a Natural number (0,1,2,3, etc.)
|
||||
*
|
||||
* @param string $str
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_natural(string $str = null): bool
|
||||
{
|
||||
return ctype_digit($str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is a Natural number, but not a zero (1,2,3, etc.)
|
||||
*
|
||||
* @param string $str
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_natural_no_zero(string $str = null): bool
|
||||
{
|
||||
return ($str !== '0' && ctype_digit($str));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Numeric
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function numeric(string $str = null): bool
|
||||
{
|
||||
return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Compares value against a regular expression pattern.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $pattern
|
||||
* @param array $data Other field/value pairs
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function regex_match(string $str = null, string $pattern, array $data): bool
|
||||
{
|
||||
if (strpos($pattern, '/') !== 0)
|
||||
{
|
||||
$pattern = "/{$pattern}/";
|
||||
}
|
||||
|
||||
return (bool) preg_match($pattern, $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validates that the string is a valid timezone as per the
|
||||
* timezone_identifiers_list function.
|
||||
*
|
||||
* @see http://php.net/manual/en/datetimezone.listidentifiers.php
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function timezone(string $str = null): bool
|
||||
{
|
||||
return in_array($str, timezone_identifiers_list());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Valid Base64
|
||||
*
|
||||
* Tests a string for characters outside of the Base64 alphabet
|
||||
* as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
|
||||
*
|
||||
* @param string $str
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_base64(string $str = null): bool
|
||||
{
|
||||
return (base64_encode(base64_decode($str)) === $str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Valid JSON
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_json(string $str = null): bool
|
||||
{
|
||||
json_decode($str);
|
||||
return json_last_error() === JSON_ERROR_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks for a correctly formatted email address
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_email(string $str = null): bool
|
||||
{
|
||||
if (function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches))
|
||||
{
|
||||
$str = $matches[1] . '@' . idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46);
|
||||
}
|
||||
|
||||
return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validate a comma-separated list of email addresses.
|
||||
*
|
||||
* Example:
|
||||
* valid_emails[one@example.com,two@example.com]
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_emails(string $str = null): bool
|
||||
{
|
||||
foreach (explode(',', $str) as $email)
|
||||
{
|
||||
$email = trim($email);
|
||||
if ($email === '')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->valid_email($email) === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validate an IP address
|
||||
*
|
||||
* @param string $ip IP Address
|
||||
* @param string $which IP protocol: 'ipv4' or 'ipv6'
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_ip(string $ip = null, string $which = null, array $data): bool
|
||||
{
|
||||
switch (strtolower($which))
|
||||
{
|
||||
case 'ipv4':
|
||||
$which = FILTER_FLAG_IPV4;
|
||||
break;
|
||||
case 'ipv6':
|
||||
$which = FILTER_FLAG_IPV6;
|
||||
break;
|
||||
default:
|
||||
$which = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks a URL to ensure it's formed correctly.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_url(string $str = null): bool
|
||||
{
|
||||
if (empty($str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
|
||||
{
|
||||
if (! in_array($matches[1], ['http', 'https'], true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$str = $matches[2];
|
||||
}
|
||||
|
||||
$str = 'http://' . $str;
|
||||
|
||||
return (filter_var($str, FILTER_VALIDATE_URL) !== false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks for a valid date and matches a given date format
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $format
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid_date(string $str = null, string $format = null): bool
|
||||
{
|
||||
if (empty($format))
|
||||
{
|
||||
return (bool) strtotime($str);
|
||||
}
|
||||
|
||||
$date = \DateTime::createFromFormat($format, $str);
|
||||
|
||||
return (bool) $date && \DateTime::getLastErrors()['warning_count'] === 0 && \DateTime::getLastErrors()['error_count'] === 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
408
system/Validation/Rules.php
Normal file
408
system/Validation/Rules.php
Normal file
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
use Config\Database;
|
||||
|
||||
/**
|
||||
* Validation Rules.
|
||||
*
|
||||
* @package CodeIgniter\Validation
|
||||
*/
|
||||
class Rules
|
||||
{
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The value does not match another field in $data.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $field
|
||||
* @param array $data Other field/value pairs
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function differs(string $str = null, string $field, array $data): bool
|
||||
{
|
||||
return array_key_exists($field, $data) ? ($str !== $data[$field]) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Equals the static value provided.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $val
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function equals(string $str = null, string $val): bool
|
||||
{
|
||||
return $str === $val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if $str is $val characters long.
|
||||
* $val = "5" (one) | "5,8,12" (multiple values)
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $val
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function exact_length(string $str = null, string $val, array $data): bool
|
||||
{
|
||||
$val = explode(',', $val);
|
||||
foreach ($val as $tmp)
|
||||
{
|
||||
if (is_numeric($tmp) && (int)$tmp === mb_strlen($str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Greater than
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $min
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function greater_than(string $str = null, string $min, array $data): bool
|
||||
{
|
||||
return is_numeric($str) ? ($str > $min) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Equal to or Greater than
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $min
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function greater_than_equal_to(string $str = null, string $min, array $data): bool
|
||||
{
|
||||
return is_numeric($str) ? ($str >= $min) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Value should be within an array of values
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $list
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
*/
|
||||
public function in_list(string $value = null, string $list, array $data): bool
|
||||
{
|
||||
$list = explode(',', $list);
|
||||
$list = array_map(function ($value) {
|
||||
return trim($value);
|
||||
}, $list);
|
||||
return in_array($value, $list, true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks the database to see if the given value is unique. Can
|
||||
* ignore a single record by field/value to make it useful during
|
||||
* record updates.
|
||||
*
|
||||
* Example:
|
||||
* is_unique[table.field,ignore_field,ignore_value]
|
||||
* is_unique[users.email,id,5]
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $field
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_unique(string $str = null, string $field, array $data): bool
|
||||
{
|
||||
// Grab any data for exclusion of a single row.
|
||||
list($field, $ignoreField, $ignoreValue) = array_pad(explode(',', $field), 3, null);
|
||||
|
||||
// Break the table and field apart
|
||||
sscanf($field, '%[^.].%[^.]', $table, $field);
|
||||
|
||||
$db = Database::connect($data['DBGroup'] ?? null);
|
||||
|
||||
$row = $db->table($table)
|
||||
->select('1')
|
||||
->where($field, $str)
|
||||
->limit(1);
|
||||
|
||||
if (! empty($ignoreField) && ! empty($ignoreValue))
|
||||
{
|
||||
$row = $row->where("{$ignoreField} !=", $ignoreValue);
|
||||
}
|
||||
|
||||
return (bool) ($row->get()
|
||||
->getRow() === null);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Less than
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $max
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function less_than(string $str = null, string $max): bool
|
||||
{
|
||||
return is_numeric($str) ? ($str < $max) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Equal to or Less than
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $max
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function less_than_equal_to(string $str = null, string $max): bool
|
||||
{
|
||||
return is_numeric($str) ? ($str <= $max) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Matches the value of another field in $data.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $field
|
||||
* @param array $data Other field/value pairs
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function matches(string $str = null, string $field, array $data): bool
|
||||
{
|
||||
return array_key_exists($field, $data) ? ($str === $data[$field]) : false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if $str is $val or fewer characters in length.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $val
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function max_length(string $str = null, string $val, array $data): bool
|
||||
{
|
||||
return ($val >= mb_strlen($str));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if $str is at least $val length.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $val
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function min_length(string $str = null, string $val, array $data): bool
|
||||
{
|
||||
return ($val <= mb_strlen($str));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Does not equal the static value provided.
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $val
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function not_equals(string $str = null, string $val): bool
|
||||
{
|
||||
return $str !== $val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Required
|
||||
*
|
||||
* @param mixed $str Value
|
||||
*
|
||||
* @return boolean True if valid, false if not
|
||||
*/
|
||||
public function required($str = null): bool
|
||||
{
|
||||
if (is_object($str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_array($str) ? ! empty($str) : (trim($str) !== '');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The field is required when any of the other required fields are present
|
||||
* in the data.
|
||||
*
|
||||
* Example (field is required when the password field is present):
|
||||
*
|
||||
* required_with[password]
|
||||
*
|
||||
* @param $str
|
||||
* @param string $fields List of fields that we should check if present
|
||||
* @param array $data Complete list of fields from the form
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function required_with($str = null, string $fields, array $data): bool
|
||||
{
|
||||
$fields = explode(',', $fields);
|
||||
|
||||
// If the field is present we can safely assume that
|
||||
// the field is here, no matter whether the corresponding
|
||||
// search field is present or not.
|
||||
$present = $this->required($str ?? '');
|
||||
|
||||
if ($present)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Still here? Then we fail this test if
|
||||
// any of the fields are present in $data
|
||||
// as $fields is the lis
|
||||
$requiredFields = [];
|
||||
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (array_key_exists($field, $data))
|
||||
{
|
||||
$requiredFields[] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any keys with empty values since, that means they
|
||||
// weren't truly there, as far as this is concerned.
|
||||
$requiredFields = array_filter($requiredFields, function ($item) use ($data) {
|
||||
return ! empty($data[$item]);
|
||||
});
|
||||
|
||||
return empty($requiredFields);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The field is required when all of the other fields are present
|
||||
* in the data but not required.
|
||||
*
|
||||
* Example (field is required when the id or email field is missing):
|
||||
*
|
||||
* required_without[id,email]
|
||||
*
|
||||
* @param $str
|
||||
* @param string $fields
|
||||
* @param array $data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function required_without($str = null, string $fields, array $data): bool
|
||||
{
|
||||
$fields = explode(',', $fields);
|
||||
|
||||
// If the field is present we can safely assume that
|
||||
// the field is here, no matter whether the corresponding
|
||||
// search field is present or not.
|
||||
$present = $this->required($str ?? '');
|
||||
|
||||
if ($present)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Still here? Then we fail this test if
|
||||
// any of the fields are not present in $data
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (! array_key_exists($field, $data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
756
system/Validation/Validation.php
Normal file
756
system/Validation/Validation.php
Normal file
@@ -0,0 +1,756 @@
|
||||
<?php
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\Validation\Exceptions\ValidationException;
|
||||
use CodeIgniter\View\RendererInterface;
|
||||
|
||||
/**
|
||||
* Validator
|
||||
*/
|
||||
class Validation implements ValidationInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Files to load with validation functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $ruleSetFiles;
|
||||
|
||||
/**
|
||||
* The loaded instances of our validation files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $ruleSetInstances = [];
|
||||
|
||||
/**
|
||||
* Stores the actual rules that should
|
||||
* be ran against $data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $rules = [];
|
||||
|
||||
/**
|
||||
* The data that should be validated,
|
||||
* where 'key' is the alias, with value.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Any generated errors during validation.
|
||||
* 'key' is the alias, 'value' is the message.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errors = [];
|
||||
|
||||
/**
|
||||
* Stores custom error message to use
|
||||
* during validation. Where 'key' is the alias.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $customErrors = [];
|
||||
|
||||
/**
|
||||
* Our configuration.
|
||||
*
|
||||
* @var \Config\Validation
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The view renderer used to render validation messages.
|
||||
*
|
||||
* @var RendererInterface
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validation constructor.
|
||||
*
|
||||
* @param \Config\Validation $config
|
||||
* @param RendererInterface $view
|
||||
*/
|
||||
public function __construct($config, RendererInterface $view)
|
||||
{
|
||||
$this->ruleSetFiles = $config->ruleSets;
|
||||
|
||||
$this->config = $config;
|
||||
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Runs the validation process, returning true/false determining whether
|
||||
* validation was successful or not.
|
||||
*
|
||||
* @param array $data The array of data to validate.
|
||||
* @param string $group The pre-defined group of rules to apply.
|
||||
* @param string $db_group The database group to use.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function run(array $data = null, string $group = null, string $db_group = null): bool
|
||||
{
|
||||
$data = $data ?? $this->data;
|
||||
|
||||
// i.e. is_unique
|
||||
$data['DBGroup'] = $db_group;
|
||||
|
||||
$this->loadRuleSets();
|
||||
|
||||
$this->loadRuleGroup($group);
|
||||
|
||||
// If no rules exist, we return false to ensure
|
||||
// the developer didn't forget to set the rules.
|
||||
if (empty($this->rules))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Need this for searching arrays in validation.
|
||||
helper('array');
|
||||
|
||||
// Run through each rule. If we have any field set for
|
||||
// this rule, then we need to run them through!
|
||||
foreach ($this->rules as $rField => $rSetup)
|
||||
{
|
||||
// Blast $rSetup apart, unless it's already an array.
|
||||
$rules = $rSetup['rules'] ?? $rSetup;
|
||||
|
||||
if (is_string($rules))
|
||||
{
|
||||
$rules = $this->splitRules($rules);
|
||||
}
|
||||
|
||||
$value = dot_array_search($rField, $data);
|
||||
|
||||
$this->processRules($rField, $rSetup['label'] ?? $rField, $value ?? null, $rules, $data);
|
||||
}
|
||||
|
||||
return ! empty($this->getErrors()) ? false : true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check; runs the validation process, returning true or false
|
||||
* determining whether validation was successful or not.
|
||||
*
|
||||
* @param mixed $value Value to validation.
|
||||
* @param string $rule Rule.
|
||||
* @param string[] $errors Errors.
|
||||
*
|
||||
* @return boolean True if valid, else false.
|
||||
*/
|
||||
public function check($value, string $rule, array $errors = []): bool
|
||||
{
|
||||
$this->reset();
|
||||
$this->setRule('check', null, $rule, $errors);
|
||||
|
||||
return $this->run([
|
||||
'check' => $value,
|
||||
]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Runs all of $rules against $field, until one fails, or
|
||||
* all of them have been processed. If one fails, it adds
|
||||
* the error to $this->errors and moves on to the next,
|
||||
* so that we can collect all of the first errors.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string|null $label
|
||||
* @param string $value
|
||||
* @param array|null $rules
|
||||
* @param array $data // All of the fields to check.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function processRules(string $field, string $label = null, $value, $rules = null, array $data): bool
|
||||
{
|
||||
// If the if_exist rule is defined...
|
||||
if (in_array('if_exist', $rules))
|
||||
{
|
||||
// and the current field does not exists in the input data
|
||||
// we can return true. Ignoring all other rules to this field.
|
||||
if (! array_key_exists($field, $data))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Otherwise remove the if_exist rule and continue the process
|
||||
$rules = array_diff($rules, ['if_exist']);
|
||||
}
|
||||
|
||||
if (in_array('permit_empty', $rules))
|
||||
{
|
||||
if (! in_array('required', $rules) && (is_array($value) ? empty($value) : (trim($value) === '')))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$rules = array_diff($rules, ['permit_empty']);
|
||||
}
|
||||
|
||||
foreach ($rules as $rule)
|
||||
{
|
||||
$callable = is_callable($rule);
|
||||
$passed = false;
|
||||
|
||||
// Rules can contain parameters: max_length[5]
|
||||
$param = false;
|
||||
if (! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
|
||||
{
|
||||
$rule = $match[1];
|
||||
$param = $match[2];
|
||||
}
|
||||
|
||||
// Placeholder for custom errors from the rules.
|
||||
$error = null;
|
||||
|
||||
// If it's a callable, call and and get out of here.
|
||||
if ($callable)
|
||||
{
|
||||
$passed = $param === false ? $rule($value) : $rule($value, $param, $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
$found = false;
|
||||
|
||||
// Check in our rulesets
|
||||
foreach ($this->ruleSetInstances as $set)
|
||||
{
|
||||
if (! method_exists($set, $rule))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$found = true;
|
||||
|
||||
$passed = $param === false ? $set->$rule($value, $error) : $set->$rule($value, $param, $data, $error);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the rule wasn't found anywhere, we
|
||||
// should throw an exception so the developer can find it.
|
||||
if (! $found)
|
||||
{
|
||||
throw ValidationException::forRuleNotFound($rule);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the error message if we didn't survive.
|
||||
if ($passed === false)
|
||||
{
|
||||
$this->errors[$field] = is_null($error) ? $this->getErrorMessage($rule, $field, $label, $param) : $error;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Takes a Request object and grabs the input data to use from its
|
||||
* array values.
|
||||
*
|
||||
* @param \CodeIgniter\HTTP\RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function withRequest(RequestInterface $request): ValidationInterface
|
||||
{
|
||||
if (in_array($request->getMethod(), ['put', 'patch', 'delete']))
|
||||
{
|
||||
$this->data = $request->getRawInput();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->data = $request->getVar() ?? [];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------
|
||||
// Rules
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets an individual rule and custom error messages for a single field.
|
||||
*
|
||||
* The custom error message should be just the messages that apply to
|
||||
* this field, like so:
|
||||
*
|
||||
* [
|
||||
* 'rule' => 'message',
|
||||
* 'rule' => 'message'
|
||||
* ]
|
||||
*
|
||||
* @param string $field
|
||||
* @param string|null $label
|
||||
* @param string $rules
|
||||
* @param array $errors
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRule(string $field, string $label = null, string $rules, array $errors = [])
|
||||
{
|
||||
$this->rules[$field] = [
|
||||
'label' => $label,
|
||||
'rules' => $rules,
|
||||
];
|
||||
$this->customErrors = array_merge($this->customErrors, [
|
||||
$field => $errors,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stores the rules that should be used to validate the items.
|
||||
* Rules should be an array formatted like:
|
||||
*
|
||||
* [
|
||||
* 'field' => 'rule1|rule2'
|
||||
* ]
|
||||
*
|
||||
* The $errors array should be formatted like:
|
||||
* [
|
||||
* 'field' => [
|
||||
* 'rule' => 'message',
|
||||
* 'rule' => 'message
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* @param array $rules
|
||||
* @param array $errors // An array of custom error messages
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function setRules(array $rules, array $errors = []): ValidationInterface
|
||||
{
|
||||
$this->customErrors = $errors;
|
||||
|
||||
foreach ($rules as $field => &$rule)
|
||||
{
|
||||
if (is_array($rule))
|
||||
{
|
||||
if (array_key_exists('errors', $rule))
|
||||
{
|
||||
$this->customErrors[$field] = $rule['errors'];
|
||||
unset($rule['errors']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->rules = $rules;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns all of the rules currently defined.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRules(): array
|
||||
{
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks to see if the rule for key $field has been set or not.
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasRule(string $field): bool
|
||||
{
|
||||
return array_key_exists($field, $this->rules);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get rule group.
|
||||
*
|
||||
* @param string $group Group.
|
||||
*
|
||||
* @return string[] Rule group.
|
||||
*
|
||||
* @throws \InvalidArgumentException If group not found.
|
||||
*/
|
||||
public function getRuleGroup(string $group): array
|
||||
{
|
||||
if (! isset($this->config->$group))
|
||||
{
|
||||
throw ValidationException::forGroupNotFound($group);
|
||||
}
|
||||
|
||||
if (! is_array($this->config->$group))
|
||||
{
|
||||
throw ValidationException::forGroupNotArray($group);
|
||||
}
|
||||
|
||||
return $this->config->$group;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set rule group.
|
||||
*
|
||||
* @param string $group Group.
|
||||
*
|
||||
* @throws \InvalidArgumentException If group not found.
|
||||
*/
|
||||
public function setRuleGroup(string $group)
|
||||
{
|
||||
$rules = $this->getRuleGroup($group);
|
||||
$this->rules = $rules;
|
||||
|
||||
$errorName = $group . '_errors';
|
||||
if (isset($this->config->$errorName))
|
||||
{
|
||||
$this->customErrors = $this->config->$errorName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rendered HTML of the errors as defined in $template.
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function listErrors(string $template = 'list'): string
|
||||
{
|
||||
if (! array_key_exists($template, $this->config->templates))
|
||||
{
|
||||
throw ValidationException::forInvalidTemplate($template);
|
||||
}
|
||||
|
||||
return $this->view->setVar('errors', $this->getErrors())
|
||||
->render($this->config->templates[$template]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Displays a single error in formatted HTML as defined in the $template view.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function showError(string $field, string $template = 'single'): string
|
||||
{
|
||||
if (! array_key_exists($field, $this->getErrors()))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if (! array_key_exists($template, $this->config->templates))
|
||||
{
|
||||
throw ValidationException::forInvalidTemplate($template);
|
||||
}
|
||||
|
||||
return $this->view->setVar('error', $this->getError($field))
|
||||
->render($this->config->templates[$template]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Loads all of the rulesets classes that have been defined in the
|
||||
* Config\Validation and stores them locally so we can use them.
|
||||
*/
|
||||
protected function loadRuleSets()
|
||||
{
|
||||
if (empty($this->ruleSetFiles))
|
||||
{
|
||||
throw ValidationException::forNoRuleSets();
|
||||
}
|
||||
|
||||
foreach ($this->ruleSetFiles as $file)
|
||||
{
|
||||
$this->ruleSetInstances[] = new $file();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Loads custom rule groups (if set) into the current rules.
|
||||
*
|
||||
* Rules can be pre-defined in Config\Validation and can
|
||||
* be any name, but must all still be an array of the
|
||||
* same format used with setRules(). Additionally, check
|
||||
* for {group}_errors for an array of custom error messages.
|
||||
*
|
||||
* @param string|null $group
|
||||
*
|
||||
* @return array|ValidationException|null
|
||||
*/
|
||||
public function loadRuleGroup(string $group = null)
|
||||
{
|
||||
if (empty($group))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! isset($this->config->$group))
|
||||
{
|
||||
throw ValidationException::forGroupNotFound($group);
|
||||
}
|
||||
|
||||
if (! is_array($this->config->$group))
|
||||
{
|
||||
throw ValidationException::forGroupNotArray($group);
|
||||
}
|
||||
|
||||
$this->rules = $this->config->$group;
|
||||
|
||||
// If {group}_errors exists in the config file,
|
||||
// then override our custom errors with them.
|
||||
$errorName = $group . '_errors';
|
||||
|
||||
if (isset($this->config->$errorName))
|
||||
{
|
||||
$this->customErrors = $this->config->$errorName;
|
||||
}
|
||||
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------
|
||||
// Errors
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks to see if an error exists for the given field.
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasError(string $field): bool
|
||||
{
|
||||
return array_key_exists($field, $this->getErrors());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the error(s) for a specified $field (or empty string if not
|
||||
* set).
|
||||
*
|
||||
* @param string $field Field.
|
||||
*
|
||||
* @return string Error(s).
|
||||
*/
|
||||
public function getError(string $field = null): string
|
||||
{
|
||||
if ($field === null && count($this->rules) === 1)
|
||||
{
|
||||
reset($this->rules);
|
||||
$field = key($this->rules);
|
||||
}
|
||||
|
||||
return array_key_exists($field, $this->getErrors()) ? $this->errors[$field] : '';
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the array of errors that were encountered during
|
||||
* a run() call. The array should be in the following format:
|
||||
*
|
||||
* [
|
||||
* 'field1' => 'error message',
|
||||
* 'field2' => 'error message',
|
||||
* ]
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* Excluded from code coverage because that it always run as cli
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
// If we already have errors, we'll use those.
|
||||
// If we don't, check the session to see if any were
|
||||
// passed along from a redirect_with_input request.
|
||||
if (empty($this->errors) && ! is_cli())
|
||||
{
|
||||
if (isset($_SESSION, $_SESSION['_ci_validation_errors']))
|
||||
{
|
||||
$this->errors = unserialize($_SESSION['_ci_validation_errors']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->errors ?? [];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the error for a specific field. Used by custom validation methods.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $error
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function setError(string $field, string $error): ValidationInterface
|
||||
{
|
||||
$this->errors[$field] = $error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Attempts to find the appropriate error message
|
||||
*
|
||||
* @param string $rule
|
||||
* @param string $field
|
||||
* @param string|null $label
|
||||
* @param string $param
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getErrorMessage(string $rule, string $field, string $label = null, string $param = null): string
|
||||
{
|
||||
// Check if custom message has been defined by user
|
||||
if (isset($this->customErrors[$field][$rule]))
|
||||
{
|
||||
$message = $this->customErrors[$field][$rule];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to grab a localized version of the message...
|
||||
// lang() will return the rule name back if not found,
|
||||
// so there will always be a string being returned.
|
||||
$message = lang('Validation.' . $rule);
|
||||
}
|
||||
|
||||
$message = str_replace('{field}', $label ?? $field, $message);
|
||||
$message = str_replace('{param}', $this->rules[$param]['label'] ?? $param, $message);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split rules string by pipe operator.
|
||||
*
|
||||
* @param string $rules
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function splitRules(string $rules): array
|
||||
{
|
||||
$non_escape_bracket = '((?<!\\\\)(?:\\\\\\\\)*[\[\]])';
|
||||
$pipe_not_in_bracket = sprintf(
|
||||
'/\|(?=(?:[^\[\]]*%s[^\[\]]*%s)*(?![^\[\]]*%s))/',
|
||||
$non_escape_bracket,
|
||||
$non_escape_bracket,
|
||||
$non_escape_bracket
|
||||
);
|
||||
|
||||
$_rules = preg_split(
|
||||
$pipe_not_in_bracket,
|
||||
$rules
|
||||
);
|
||||
|
||||
return array_unique($_rules);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------
|
||||
// Misc
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resets the class to a blank slate. Should be called whenever
|
||||
* you need to process more than one array.
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function reset(): ValidationInterface
|
||||
{
|
||||
$this->data = [];
|
||||
$this->rules = [];
|
||||
$this->errors = [];
|
||||
$this->customErrors = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
166
system/Validation/ValidationInterface.php
Normal file
166
system/Validation/ValidationInterface.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Validation;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
|
||||
/**
|
||||
* Expected behavior of a validator
|
||||
*/
|
||||
interface ValidationInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Runs the validation process, returning true/false determining whether
|
||||
* or not validation was successful.
|
||||
*
|
||||
* @param array $data The array of data to validate.
|
||||
* @param string $group The pre-defined group of rules to apply.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function run(array $data = null, string $group = null): bool;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check; runs the validation process, returning true or false
|
||||
* determining whether or not validation was successful.
|
||||
*
|
||||
* @param mixed $value Value to validation.
|
||||
* @param string $rule Rule.
|
||||
* @param string[] $errors Errors.
|
||||
*
|
||||
* @return boolean True if valid, else false.
|
||||
*/
|
||||
public function check($value, string $rule, array $errors = []): bool;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Takes a Request object and grabs the input data to use from its
|
||||
* array values.
|
||||
*
|
||||
* @param \CodeIgniter\HTTP\RequestInterface $request
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function withRequest(RequestInterface $request): ValidationInterface;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Rules
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stores the rules that should be used to validate the items.
|
||||
*
|
||||
* @param array $rules
|
||||
* @param array $messages
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function setRules(array $rules, array $messages = []): ValidationInterface;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks to see if the rule for key $field has been set or not.
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasRule(string $field): bool;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------
|
||||
// Errors
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the error for a specified $field (or empty string if not set).
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getError(string $field): string;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the array of errors that were encountered during
|
||||
* a run() call. The array should be in the following format:
|
||||
*
|
||||
* [
|
||||
* 'field1' => 'error message',
|
||||
* 'field2' => 'error message',
|
||||
* ]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(): array;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the error for a specific field. Used by custom validation methods.
|
||||
*
|
||||
* @param string $alias
|
||||
* @param string $error
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function setError(string $alias, string $error): ValidationInterface;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Misc
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resets the class to a blank slate. Should be called whenever
|
||||
* you need to process more than one array.
|
||||
*
|
||||
* @return \CodeIgniter\Validation\ValidationInterface
|
||||
*/
|
||||
public function reset(): ValidationInterface;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
9
system/Validation/Views/list.php
Normal file
9
system/Validation/Views/list.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php if (! empty($errors)) : ?>
|
||||
<div class="errors" role="alert">
|
||||
<ul>
|
||||
<?php foreach ($errors as $error) : ?>
|
||||
<li><?= esc($error) ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
1
system/Validation/Views/single.php
Normal file
1
system/Validation/Views/single.php
Normal file
@@ -0,0 +1 @@
|
||||
<span class="help-block"><?= esc($error) ?></span>
|
||||
Reference in New Issue
Block a user