845 lines
34 KiB
PHP
845 lines
34 KiB
PHP
<?php
|
||
namespace DynCom\mysyde\common\classes;
|
||
use ReflectionClass;
|
||
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: Bauer
|
||
* Date: 6/12/2015
|
||
* Time: 3:42 AM
|
||
*/
|
||
class NewValidator
|
||
{
|
||
|
||
const ORDINAL_COMPARATOR_EQ = '=';
|
||
const ORDINAL_COMPARATOR_LT = '<';
|
||
const ORDINAL_COMPARATOR_LTE = '<=';
|
||
const ORDINAL_COMPARATOR_GT = '>';
|
||
const ORDINAL_COMPARATOR_GTE = '>=';
|
||
|
||
const DECIMAL_SEPARATOR_COMMA = ',';
|
||
const DECIMAL_SEPARATOR_POINT = '.';
|
||
|
||
const DATE_FORMAT_ISO_8601 = 'yyyy-mm-dd';
|
||
const DATE_FORMAT_DDMMYY_DASHES = 'dd-mm-yy';
|
||
const DATE_FORMAT_DDMMYYYY_DASHES = 'dd-mm-yyyy';
|
||
const DATE_FORMAT_DDMMYY_DOTS = 'dd.mm.yy';
|
||
const DATE_FORMAT_DDMMYYYY_DOTS = 'dd.mm.yyyy';
|
||
const DATE_FORMAT_DDMMYY_SLASHES = 'dd/mm/yy';
|
||
const DATE_FORMAT_DDMMYYYY_SLASHES = 'dd/mm/yyyy';
|
||
const DATE_FORMAT_MMDDYY_DASHES = 'mm-dd-yy';
|
||
const DATE_FORMAT_MMDDYYYY_DASHES = 'mm-dd-yyyy';
|
||
const DATE_FORMAT_MMDDYY_DOTS = 'mm.dd.yy';
|
||
const DATE_FORMAT_MMDDYYYY_DOTS = 'mm.dd.yyyy';
|
||
const DATE_FORMAT_MMDDYY_SLASHES = 'mm/dd/yy';
|
||
const DATE_FORMAT_MMDDYYYY_SLASHES = 'mm/dd/yyyy';
|
||
|
||
const DATETIME_FORMAT_ISO_8601 = 'yyyy-mm-ddThh:mm:ss';
|
||
const DATETIME_FORMAT_MYSQL = 'yyyy-mm-dd hh:mm:ss';
|
||
|
||
const TIME_FORMAT_COLON = 'hh:mm:ss';
|
||
|
||
const CONF_RULE_SEPARATOR = '|';
|
||
const CONF_RULE_VALUE_SEPARATOR = ':';
|
||
|
||
const ERROR_MSG_CONST_SUFFIX = '_ERROR_MSG_CODE';
|
||
|
||
const RULE_REQUIRED = 'required';
|
||
const RULE_REQUIRED_ERROR_MSG_CODE = 'validation_error_required_not_set';
|
||
|
||
const RULE_EMAIL = 'email';
|
||
const RULE_EMAIL_ERROR_MSG_CODE = 'validation_error_email_invalid';
|
||
|
||
const RULE_NAME = 'name';
|
||
const RULE_NAME_ERROR_MSG_CODE = 'validation_error_name_invalid';
|
||
|
||
const RULE_ADDR_STREET = 'addrstreet';
|
||
const RULE_ADDR_STREET_ERROR_MSG_CODE = 'validation_error_addr_street_invalid';
|
||
|
||
const RULE_ADDR_STREET_NO = 'addrstreetno';
|
||
const RULE_ADDR_STREET_NO_ERROR_MSG_CODE = 'validation_error_addr_street_no_invalid';
|
||
|
||
const RULE_ADDR_STREET_PLUS_NO = 'addrstreetplusno';
|
||
const RULE_ADDR_STREET_PLUS_NO_ERROR_MSG_CODE = 'validation_error_addr_street_plus_no_invalid';
|
||
|
||
const RULE_ADDR_CITY = 'addrcity';
|
||
const RULE_ADDR_CITY_ERROR_MSG_CODE = 'validation_error_addr_city_invalid';
|
||
|
||
const RULE_ADDR_ZIP = 'addrzip';
|
||
const RULE_ADDR_ZIP_ERROR_MSG_CODE = 'validation_error_addr_zip_invalid';
|
||
|
||
const RULE_STR_WS_DASH_DOT = 'strwsdashdot';
|
||
const RULE_STR_WS_DASH_DOT_ERROR_MSG_CODE = 'validation_error_str_ws_dash_dot_invalid';
|
||
|
||
const RULE_STR_WS_DASH_DOT_PAR = 'strwsdashdotparen';
|
||
const RULE_STR_WS_DASH_DOT_PAR_ERROR_MSG_CODE = 'validation_error_str_ws_dash_dot_par_invalid';
|
||
|
||
const RULE_URL = 'url';
|
||
const RULE_URL_ERROR_MSG_CODE = 'validation_error_url_invalid';
|
||
|
||
const RULE_ALPHA = 'Alpha';
|
||
const RULE_ALPHA_ERROR_MSG_CODE = 'validation_error_alpha_invalid';
|
||
|
||
const RULE_ALPHA_CAPS = 'ALPHA';
|
||
const RULE_ALPHA_CAPS_ERROR_MSG_CODE = 'validation_error_alpha_caps_invalid';
|
||
|
||
const RULE_ALPHA_SMALL = 'alpha';
|
||
const RULE_ALPHA_SMALL_ERROR_MSG_CODE = 'validation_error_alpha_small_invalid';
|
||
|
||
const RULE_DIGIT = 'digit';
|
||
const RULE_DIGIT_ERROR_MSG_CODE = 'validation_error_alpha_digit_invalid';
|
||
|
||
const RULE_DECIMAL = 'decimal';
|
||
const RULE_DECIMAL_ERROR_MSG_CODE = 'validation_error_decimal_invalid';
|
||
|
||
const RULE_ALNUM = 'alnum';
|
||
const RULE_ALNUM_ERROR_MSG_CODE = 'validation_error_alnum_invalid';
|
||
|
||
const RULE_GENERAL_TEXT = 'text';
|
||
const RULE_GENERAL_TEXT_ERROR_MSG_CODE = 'validation_error_text_general_invalid';
|
||
|
||
const RULE_DATE = 'date';
|
||
const RULE_DATE_ERROR_MSG_CODE = 'validation_error_date_invalid';
|
||
|
||
const RULE_DATETIME = 'dateTime';
|
||
const RULE_DATETIME_ERROR_MSG_CODE = 'validation_error_datetime_invalid';
|
||
|
||
const RULE_MIN_LENGTH = 'minlen';
|
||
const RULE_MIN_LENGTH_ERROR_MSG_CODE = 'validation_error_minlen_exceeded';
|
||
|
||
const RULE_MAX_LENGTH = 'maxlen';
|
||
const RULE_MAX_LENGTH_ERROR_MSG_CODE = 'validation_error_maxlen_exceeded';
|
||
|
||
const RULE_MIN_NUMERIC = 'minnum';
|
||
const RULE_MIN_NUM_ERROR_MSG_CODE = 'validation_error_minnum_exceeded';
|
||
|
||
const RULE_MAX_NUMERIC = 'maxnum';
|
||
const RULE_MAX_NUM_ERROR_MSG_CODE = 'validation_error_maxnum_exceeded';
|
||
|
||
const RULE_MIN_DATE = 'mindate';
|
||
const RULE_MIN_DATE_ERROR_MSG_CODE = 'validation_error_mindate_exceeded';
|
||
|
||
const RULE_MAX_DATE = 'maxdate';
|
||
const RULE_MAX_DATE_ERROR_MSG_CODE = 'validation_error_max_date_exceeded';
|
||
|
||
const RULE_CUST_REGEX = 'regex';
|
||
const RULE_CUST_REGEX_ERROR_MSG_CODE = 'validation_error_cust_regex_unmatched';
|
||
|
||
const RULE_REQUIRES = 'requires';
|
||
const RULE_REQUIRES_ERROR_MSG_CODE = 'validation_error_required_field_not_set';
|
||
|
||
const RULE_EXTENDS = 'extends';
|
||
const RULE_IN = 'in';
|
||
|
||
const RULE_INSTANCEOF = 'instanceof';
|
||
const RULE_FIELD = 'field';
|
||
const RULE_METHOD = 'method';
|
||
|
||
const RULE_EMPTY_ALLOWED = 'orempty';
|
||
|
||
protected $decimalSeparator = self::DECIMAL_SEPARATOR_POINT;
|
||
protected $dateFormat = self::DATE_FORMAT_DDMMYY_DOTS;
|
||
protected $timeFormat = self::TIME_FORMAT_COLON;
|
||
protected $dateTimeFormat = self::DATETIME_FORMAT_MYSQL;
|
||
protected $dateValidation = array();
|
||
|
||
protected $ruleConstants = array();
|
||
|
||
protected $data = array();
|
||
protected $rules = array();
|
||
|
||
protected $languageCode = 'de';
|
||
|
||
/**
|
||
* @param $regex
|
||
* @return bool
|
||
*/
|
||
protected function _isValidRegex($regex)
|
||
{
|
||
return (preg_match($regex, null) !== false);
|
||
}
|
||
|
||
/**
|
||
* @param $fieldName
|
||
* @param $regex
|
||
*/
|
||
public function setCustomRegexRule($fieldName, $regex)
|
||
{
|
||
if (!array_key_exists($fieldName, $this->data)) {
|
||
throw new \InvalidArgumentException(
|
||
sprintf(
|
||
'%s is not the name of a data-item.',
|
||
strip_tags($fieldName)
|
||
)
|
||
);
|
||
}
|
||
|
||
if (!$this->_isValidRegex($regex)) {
|
||
throw new \InvalidArgumentException(
|
||
sprintf(
|
||
'%s is not a valid regex.',
|
||
strip_tags($regex)
|
||
)
|
||
);
|
||
}
|
||
|
||
$callable = function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match($validationParam, $fieldValue) > 0);
|
||
};
|
||
|
||
$this->rules[$fieldName][self::RULE_CUST_REGEX] = array('callable' => &$callable, 'ruleValue' => $regex);
|
||
}
|
||
|
||
protected function _setDefaultDateFormatValidation()
|
||
{
|
||
$this->dateValidation = array(
|
||
self::DATE_FORMAT_ISO_8601 => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('Y-m-d', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYY_DASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d-m-y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYYYY_DASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d-m-Y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYY_DOTS => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d.m.y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYYYY_DOTS => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d.m.Y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYY_SLASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d/m/y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_DDMMYYYY_SLASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('d/m/Y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYY_DASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m-d-y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYYYY_DASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m-d-Y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYY_DOTS => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m.d.y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYYYY_DOTS => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m.d.Y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYY_SLASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m/d/y', $dataSourceString);
|
||
},
|
||
self::DATE_FORMAT_MMDDYYYY_SLASHES => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('m/d/Y', $dataSourceString);
|
||
},
|
||
self::DATETIME_FORMAT_ISO_8601 => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('Y-m-dTH:i:s', $dataSourceString);
|
||
},
|
||
self::DATETIME_FORMAT_MYSQL => function ($dataSourceString) {
|
||
return $this->_isValidByDateFormat('Y-m-d H:i:s', $dataSourceString);
|
||
}
|
||
);
|
||
}
|
||
|
||
protected $ruleValidation = array();
|
||
|
||
protected function _setDefaultRuleValidation()
|
||
{
|
||
$this->ruleValidation = array(
|
||
self::RULE_REQUIRED => function () {
|
||
$fieldName = func_get_arg(0);
|
||
return array_key_exists($fieldName, $this->data);
|
||
},
|
||
self::RULE_EMAIL => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return filter_var($fieldValue, FILTER_VALIDATE_EMAIL);
|
||
},
|
||
self::RULE_NAME => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ\s\-]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ\s\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET_NO => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match(
|
||
'/^[[:digit:]]+[[:alpha:]]{0,1}(?:\s*\-\s*[[:digit:]]{0,}[[:alpha:]]*){0,1}$/',
|
||
$fieldValue
|
||
) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET_PLUS_NO => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match(
|
||
'/^[[:alpha:]äöüßÄÖÜ\s\-\.]+\s+[[:digit:]]+[[:alpha:]]{0,1}(?:\s*\-\s*[[:digit:]]{0,}[[:alpha:]]*){0,1}$/',
|
||
$fieldValue
|
||
) > 0);
|
||
},
|
||
self::RULE_ADDR_CITY => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ\s\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_ZIP => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:digit:]]{5}$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_STR_WS_DASH_DOT => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_STR_WS_DASH_DOT_PAR => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ\-\.\(\)]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_URL => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return filter_var($fieldValue, FILTER_VALIDATE_URL);
|
||
},
|
||
self::RULE_ALPHA => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alpha:]äöüßÄÖÜ]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ALPHA_CAPS => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:upper:]ÄÖÜ]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ALPHA_SMALL => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:lower:]äöüß]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_DIGIT => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:digit:]]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_DECIMAL => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match(
|
||
'/^[[:digit:]]+(\\' . $this->decimalSeparator . '[[:digit:]]{1,})|[[:digit:]]$/',
|
||
$fieldValue
|
||
) > 0);
|
||
},
|
||
self::RULE_ALNUM => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (preg_match('/^[[:alnum:]äöüßÄÖÜ]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_GENERAL_TEXT => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return (strip_tags($fieldValue) === $fieldValue);
|
||
},
|
||
self::RULE_DATE => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return ($this->dateValidation[$this->dateFormat]($fieldValue));
|
||
},
|
||
self::RULE_DATETIME => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
return ($this->dateValidation[$this->dateTimeFormat]($fieldValue));
|
||
},
|
||
self::RULE_MIN_LENGTH => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return (mb_strlen($fieldValue, 'UTF-8') >= $validationParam);
|
||
},
|
||
self::RULE_MAX_LENGTH => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return (mb_strlen($fieldValue, 'UTF-8') <= $validationParam);
|
||
},
|
||
self::RULE_MIN_NUMERIC => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return ((float)$fieldValue >= (float)$validationParam);
|
||
},
|
||
self::RULE_MAX_NUMERIC => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return ((float)$fieldValue <= (float)$validationParam);
|
||
},
|
||
self::RULE_MIN_DATE => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return $this->_dateStrHasOrdinalRelToRefDateStr(
|
||
$fieldValue,
|
||
$validationParam,
|
||
self::ORDINAL_COMPARATOR_GTE
|
||
);
|
||
},
|
||
self::RULE_MAX_DATE => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
return $this->_dateStrHasOrdinalRelToRefDateStr(
|
||
$fieldValue,
|
||
$validationParam,
|
||
self::ORDINAL_COMPARATOR_LTE
|
||
);
|
||
},
|
||
self::RULE_REQUIRES => function () {
|
||
$validationParam = func_get_arg(2);
|
||
$dataExists = array_key_exists($validationParam, $this->data);
|
||
if (!$dataExists) { return false; }
|
||
$fieldData = $this->data[$validationParam];
|
||
$isValid = true;
|
||
$dummyFieldStatusArr = [];
|
||
//If rules exist for other field, they have to be valid;
|
||
$this->_validateField($validationParam, $fieldData, $dummyFieldStatusArr, $isValid);
|
||
return $isValid;
|
||
},
|
||
self::RULE_EXTENDS => function ($fieldName, $fieldValue, $validationParam, array &$fieldStatusArr) {
|
||
$isValid = true;
|
||
$extendedRulesExists = array_key_exists($validationParam, $this->rules);
|
||
if (!$extendedRulesExists) { return $isValid; }
|
||
//Validate the data of this field against the rules of the extended Field
|
||
$this->_validateField($validationParam, $fieldValue, $fieldStatusArr, $isValid);
|
||
return $isValid;
|
||
},
|
||
self::RULE_IN => function () {
|
||
$fieldValue = func_get_arg(1);
|
||
$validationParam = func_get_arg(2);
|
||
$validValues = json_decode($validationParam, false);
|
||
$isValid = (is_array($validValues) && in_array($fieldValue, $validValues, true));
|
||
return $isValid;
|
||
},
|
||
self::RULE_INSTANCEOF => function () {
|
||
$obj = func_get_arg(1);
|
||
$objName = func_get_arg(2);
|
||
return (is_object($obj) && ($obj instanceof $objName));
|
||
},
|
||
self::RULE_FIELD => function () {
|
||
$obj = func_get_arg(1);
|
||
$nameValueStringArr = explode('=', func_get_arg(2), 2);
|
||
$fieldName = $nameValueStringArr[0];
|
||
$fieldValue = (array_key_exists(1, $nameValueStringArr) && strlen($nameValueStringArr[1]) > 0) ?
|
||
$nameValueStringArr[1] : true;
|
||
$objValue = false;
|
||
if (is_object($obj)) {
|
||
@$objValue = $obj->$fieldName;
|
||
}
|
||
return ($objValue == $fieldValue);
|
||
},
|
||
self::RULE_METHOD => function () {
|
||
$obj = func_get_arg(1);
|
||
$nameValueStringArr = explode('=', func_get_arg(2), 2);
|
||
$methodName = $nameValueStringArr[0];
|
||
$fieldValue = (array_key_exists(1, $nameValueStringArr) && strlen($nameValueStringArr[1]) > 0) ?
|
||
$nameValueStringArr[1] : true;
|
||
$objValue = false;
|
||
if (is_object($obj)) {
|
||
@$objValue = $obj->$methodName();
|
||
}
|
||
return ($objValue == $fieldValue);
|
||
},
|
||
self::RULE_EMPTY_ALLOWED => function () {
|
||
return true;
|
||
}
|
||
);
|
||
}
|
||
|
||
protected $errorMessages = array();
|
||
|
||
protected function _setDefaultErrorMsgCallables()
|
||
{
|
||
$this->errorMessages = array(
|
||
self::RULE_REQUIRED => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (array_key_exists($fieldName, $this->data));
|
||
},
|
||
self::RULE_EMAIL => function ($fieldName, $fieldValue, $validationParam) {
|
||
return filter_var($fieldValue, FILTER_VALIDATE_EMAIL);
|
||
},
|
||
self::RULE_NAME => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\s\-]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\s\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET_NO => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:digit:]]+[[:alpha:]]{0,1}(?:\s*\-\s*[[:digit:]]{0,}[[:alpha:]]*){0,1}$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_STREET_PLUS_NO => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\s\-\.]+\s+[[:digit:]]+[[:alpha:]]{0,1}(?:\s*\-\s*[[:digit:]]{0,}[[:alpha:]]*){0,1}$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_CITY => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\s\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ADDR_ZIP => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[0-9]{5}$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_STR_WS_DASH_DOT => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\-\.]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_STR_WS_DASH_DOT_PAR => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\-\.\(\)]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_URL => function ($fieldName, $fieldValue, $validationParam) {
|
||
return filter_var($fieldValue, FILTER_VALIDATE_URL);
|
||
},
|
||
self::RULE_ALPHA => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alpha:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ALPHA_CAPS => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:upper:]<5D><><EFBFBD>]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ALPHA_SMALL => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:lower:]<5D><><EFBFBD><EFBFBD>]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_DIGIT => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:digit:]]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_DECIMAL => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:digit:]]+(\\' . $this->decimalSeparator . '[[:digit:]]{1,})|[[:digit:]]$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_ALNUM => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (preg_match('/^[[:alnum:]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>]+$/', $fieldValue) > 0);
|
||
},
|
||
self::RULE_GENERAL_TEXT => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (strip_tags($fieldValue) === $fieldValue);
|
||
},
|
||
self::RULE_DATE => function ($fieldName, $fieldValue, $validationParam) {
|
||
return ($this->dateValidation[$this->dateFormat]($fieldValue));
|
||
},
|
||
self::RULE_DATETIME => function ($fieldName, $fieldValue, $validationParam) {
|
||
return $this->dateValidation[$this->dateTimeFormat]($fieldValue);
|
||
},
|
||
self::RULE_MIN_LENGTH => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (mb_strlen($fieldValue, 'UTF-8') >= $validationParam);
|
||
},
|
||
self::RULE_MAX_LENGTH => function ($fieldName, $fieldValue, $validationParam) {
|
||
return (mb_strlen($fieldValue, 'UTF-8') <= $validationParam);
|
||
},
|
||
self::RULE_MIN_NUMERIC => function ($fieldName, $fieldValue, $validationParam) {
|
||
return ((float)$fieldValue >= (float)$validationParam);
|
||
},
|
||
self::RULE_MAX_NUMERIC => function ($fieldName, $fieldValue, $validationParam) {
|
||
return ((float)$fieldValue <= (float)$validationParam);
|
||
},
|
||
self::RULE_MIN_DATE => function ($fieldName, $fieldValue, $validationParam) {
|
||
return $this->_dateStrHasOrdinalRelToRefDateStr($fieldValue, $validationParam, self::ORDINAL_COMPARATOR_GTE);
|
||
},
|
||
self::RULE_MAX_DATE => function ($fieldName, $fieldValue, $validationParam) {
|
||
return $this->_dateStrHasOrdinalRelToRefDateStr($fieldValue, $validationParam, self::ORDINAL_COMPARATOR_LTE);
|
||
}
|
||
);
|
||
}
|
||
|
||
protected function _setRuleConstants()
|
||
{
|
||
$ref = new ReflectionClass($this);
|
||
$constants = $ref->getConstants();
|
||
foreach ($constants as $constName => $constVal) {
|
||
if (static::strStartsWith($constName, 'RULE_')) {
|
||
$this->ruleConstants[$constName] = $constVal;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param $ruleName
|
||
* @return bool
|
||
*/
|
||
public function isValidRuleName($ruleName)
|
||
{
|
||
if (!(count($this->ruleConstants) > 0)) {
|
||
$this->_setRuleConstants();
|
||
}
|
||
return in_array($ruleName, $this->ruleConstants, true);
|
||
}
|
||
|
||
/**
|
||
* @param $ruleName
|
||
* @return bool
|
||
*/
|
||
public static function isValidDefaultInlineRuleName($ruleName)
|
||
{
|
||
$arr = array(
|
||
self::RULE_REQUIRED,
|
||
self::RULE_EMAIL,
|
||
self::RULE_NAME,
|
||
self::RULE_ADDR_STREET,
|
||
self::RULE_ADDR_STREET_NO,
|
||
self::RULE_ADDR_STREET_PLUS_NO,
|
||
self::RULE_ADDR_CITY,
|
||
self::RULE_ADDR_ZIP,
|
||
self::RULE_STR_WS_DASH_DOT,
|
||
self::RULE_STR_WS_DASH_DOT_PAR,
|
||
self::RULE_URL,
|
||
self::RULE_ALPHA,
|
||
self::RULE_ALPHA_CAPS,
|
||
self::RULE_ALPHA_SMALL,
|
||
self::RULE_DIGIT,
|
||
self::RULE_DECIMAL,
|
||
self::RULE_ALNUM,
|
||
self::RULE_GENERAL_TEXT,
|
||
self::RULE_DATE,
|
||
self::RULE_DATETIME,
|
||
self::RULE_MIN_LENGTH,
|
||
self::RULE_MAX_LENGTH,
|
||
self::RULE_MIN_NUMERIC,
|
||
self::RULE_MAX_NUMERIC,
|
||
self::RULE_MIN_DATE,
|
||
self::RULE_MAX_DATE,
|
||
self::RULE_CUST_REGEX
|
||
);
|
||
return in_array($ruleName, $arr, 1);
|
||
}
|
||
|
||
/**
|
||
* @param $dateFormatString
|
||
* @param $dataSourceString
|
||
* @return bool
|
||
*/
|
||
protected function _isValidByDateFormat($dateFormatString, $dataSourceString)
|
||
{
|
||
$dateTime = \DateTime::createFromFormat($dateFormatString, $dataSourceString);
|
||
$dateTimeString = $dateTime->format($dateFormatString);
|
||
return ($dateTimeString === $dataSourceString);
|
||
}
|
||
|
||
|
||
/**
|
||
* NewValidator constructor.
|
||
* @param array $dataRules
|
||
* @param array|null $data
|
||
*/
|
||
public function __construct(array $dataRules, array $data = null)
|
||
{
|
||
$this->_setDefaultRuleValidation();
|
||
$this->_setDefaultDateFormatValidation();
|
||
if(null === $data) { $data = []; }
|
||
$this->setData($data);
|
||
if (is_array($dataRules)) {
|
||
foreach ($dataRules as $fieldName => $ruleStr) {
|
||
$this->_parseRuleString($fieldName, $ruleStr);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param array $data
|
||
*/
|
||
public function setData(array $data) {
|
||
foreach($data as $dataKey => $dataVal) {
|
||
$this->data[$dataKey] = $dataVal;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param $fieldName
|
||
* @param $ruleString
|
||
*/
|
||
protected function _parseRuleString($fieldName, $ruleString)
|
||
{
|
||
if (!array_key_exists($fieldName, $this->data)) {
|
||
throw new \InvalidArgumentException(
|
||
sprintf(
|
||
'%s is not the name of a data-item.',
|
||
strip_tags($fieldName)
|
||
)
|
||
);
|
||
}
|
||
|
||
$rules = explode(self::CONF_RULE_SEPARATOR, $ruleString);
|
||
if (!is_array($rules) || count($rules) < 1) {
|
||
throw new \InvalidArgumentException(
|
||
sprintf(
|
||
'%s is not a string of rules split by %s.',
|
||
strip_tags($rules),
|
||
self::CONF_RULE_SEPARATOR
|
||
)
|
||
);
|
||
}
|
||
|
||
foreach ($rules as $rule) {
|
||
$ruleParts = explode(self::CONF_RULE_VALUE_SEPARATOR, $rule, 2);
|
||
$ruleName = $ruleParts[0];
|
||
$ruleValue = (isset($ruleParts[1]) ? $ruleParts[1] : '');
|
||
if (self::RULE_CUST_REGEX !== $ruleName && !array_key_exists($ruleName, $this->ruleValidation)) {
|
||
throw new \InvalidArgumentException(
|
||
sprintf(
|
||
'%s is not a valid rule.',
|
||
strip_tags($ruleName)
|
||
)
|
||
);
|
||
}
|
||
if (self::RULE_CUST_REGEX === $ruleName) {
|
||
throw new \InvalidArgumentException('A custom regex-rule can only be set via method.');
|
||
}
|
||
$this->rules[$fieldName][$ruleName] = array('callable' => &$this->ruleValidation[$ruleName], 'ruleValue' => $ruleValue);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @param $dateStr
|
||
* @param $refDateStr
|
||
* @param $comparator
|
||
* @return bool
|
||
*/
|
||
protected function _dateStrHasOrdinalRelToRefDateStr($dateStr, $refDateStr, $comparator)
|
||
{
|
||
$dt = new \DateTime(strtotime($dateStr));
|
||
$dtRef = new \DateTime(strtotime($refDateStr));
|
||
switch ($comparator) {
|
||
case self::ORDINAL_COMPARATOR_EQ:
|
||
$isValid = ($dt->getTimestamp() === $dtRef->getTimestamp());
|
||
break;
|
||
case self::ORDINAL_COMPARATOR_LT:
|
||
$isValid = ($dt->getTimestamp() < $dtRef->getTimestamp());
|
||
break;
|
||
case self::ORDINAL_COMPARATOR_LTE:
|
||
$isValid = ($dt->getTimestamp() <= $dtRef->getTimestamp());
|
||
break;
|
||
case self::ORDINAL_COMPARATOR_GT:
|
||
$isValid = ($dt->getTimestamp() > $dtRef->getTimestamp());
|
||
break;
|
||
case self::ORDINAL_COMPARATOR_GTE:
|
||
$isValid = ($dt->getTimestamp() >= $dtRef->getTimestamp());
|
||
break;
|
||
default:
|
||
$isValid = ($dt->getTimestamp() === $dtRef->getTimestamp());
|
||
break;
|
||
}
|
||
return $isValid;
|
||
}
|
||
|
||
/**
|
||
* After validation, $fieldStatusArr will contain detailed information about the validation result, including rule-mismatch error-messages
|
||
* @param array|null $fieldStatusArr
|
||
* @return bool
|
||
* @throws \InvalidArgumentException
|
||
*/
|
||
public function isValid(array &$fieldStatusArr)
|
||
{
|
||
if (null === $this->data) {
|
||
throw new \InvalidArgumentException(
|
||
'Method \'Cannot check validity while data is not set\''
|
||
);
|
||
}
|
||
$isValid = true;
|
||
$statusArr = array();
|
||
|
||
foreach ($this->data as $fieldName => $fieldValue) {
|
||
$singleFieldStatusArr = [];
|
||
$this->_validateField($fieldName,$fieldValue,$singleFieldStatusArr,$isValid);
|
||
$statusArr[$fieldName] = $singleFieldStatusArr;
|
||
}
|
||
$fieldStatusArr = $statusArr;
|
||
return $isValid;
|
||
}
|
||
|
||
/**
|
||
* @param $fieldName
|
||
* @param $fieldValue
|
||
* @param $singleFieldStatusArr
|
||
* @param $isValidTotal
|
||
* @return bool
|
||
*/
|
||
protected function _validateField($fieldName, $fieldValue, &$singleFieldStatusArr, &$isValidTotal) {
|
||
$isValidField = true;
|
||
$unmatchedRules = [];
|
||
$appliedRulesString = '';
|
||
$i = 0;
|
||
if (isset($this->rules[$fieldName])) {
|
||
$emptyAllowed = (array_key_exists(self::RULE_EMPTY_ALLOWED,$this->rules[$fieldName]) || !array_key_exists(self::RULE_REQUIRED,$this->rules[$fieldName]));
|
||
if (!$emptyAllowed) {
|
||
foreach ($this->rules[$fieldName] as $ruleName => $ruleArr) {
|
||
//$fieldValue = $this->data[$fieldName];
|
||
$ruleCallable = $ruleArr['callable'];
|
||
$ruleValue = $ruleArr['ruleValue'];
|
||
if ($i > 0) {
|
||
$appliedRulesString .= self::CONF_RULE_SEPARATOR;
|
||
}
|
||
$appliedRulesString .= $ruleName;
|
||
$fieldStatusArrTMP = [];
|
||
if (!$ruleCallable($fieldName, $fieldValue, $ruleValue, $fieldStatusArrTMP)) {
|
||
$isValidField = false;
|
||
$unmatchedRules = (isset($fieldStatusArrTMP['unmatchedRules']) ? $fieldStatusArrTMP['unmatchedRules'] : []);
|
||
$unmatchedRules[] = array('ruleName' => $ruleName, 'ruleValue' => $ruleValue, 'ruleError' => $this->getRuleErrorMessage($ruleName));
|
||
$isValidTotal = false;
|
||
}
|
||
++$i;
|
||
}
|
||
}
|
||
$singleFieldStatusArr = array('value' => $fieldValue, 'valid' => $isValidField, 'appliedRules' => $appliedRulesString, 'unmatchedRules' => $unmatchedRules);
|
||
}
|
||
return $isValidField;
|
||
}
|
||
|
||
/**
|
||
* @return bool
|
||
*/
|
||
public function isInvalid()
|
||
{
|
||
$dummyArr = [];
|
||
return !($this->isValid($dummyArr));
|
||
}
|
||
|
||
/**
|
||
* @param array $rules
|
||
*/
|
||
public function setRules(array $rules)
|
||
{
|
||
if (null === $this->data) {
|
||
throw new \BadMethodCallException(
|
||
'Method \'setRules cannot be called while data is not set\''
|
||
);
|
||
}
|
||
foreach ($rules as $fieldName => $ruleStr) {
|
||
$this->_parseRuleString($fieldName, $ruleStr);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param $ruleName
|
||
* @return mixed|string
|
||
*/
|
||
public function getRuleErrorMessage($ruleName ) {
|
||
$errorMsgConstName = $ruleName . self::ERROR_MSG_CONST_SUFFIX;
|
||
$fqn = 'static::' . $errorMsgConstName;
|
||
if (defined($fqn)) {
|
||
return constant($fqn);
|
||
} else {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @param $haystack
|
||
* @param $needle
|
||
* @return bool
|
||
*/
|
||
public static function strStartsWith($haystack, $needle)
|
||
{
|
||
// search backwards starting from haystack length characters from the end
|
||
return $needle === '' || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
|
||
}
|
||
|
||
/**
|
||
* @param $haystack
|
||
* @param $needle
|
||
* @return bool
|
||
*/
|
||
public static function strEndsWith($haystack, $needle)
|
||
{
|
||
// search forward starting from end minus needle length characters
|
||
return $needle === '' || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== FALSE);
|
||
}
|
||
|
||
/**
|
||
* @param $dataItem
|
||
* @param $ruleString
|
||
* @return array
|
||
*/
|
||
public static function evaluateDataItemAgainstRuleString($dataItem,$ruleString) {
|
||
$dataArr = array(
|
||
'dataItem' => $dataItem
|
||
);
|
||
$ruleArr = array(
|
||
'dataItem' => $ruleString
|
||
);
|
||
$validator = new self($ruleArr, $dataArr);
|
||
$fieldStatusArr = array();
|
||
$validator->isValid($fieldStatusArr);
|
||
unset($validator);
|
||
return $fieldStatusArr;
|
||
}
|
||
} |