'; 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:]�������\s\-]+$/', $fieldValue) > 0); }, self::RULE_ADDR_STREET => function ($fieldName, $fieldValue, $validationParam) { return (preg_match('/^[[:alpha:]�������\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:]�������\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:]�������\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:]�������\-\.]+$/', $fieldValue) > 0); }, self::RULE_STR_WS_DASH_DOT_PAR => function ($fieldName, $fieldValue, $validationParam) { return (preg_match('/^[[:alpha:]�������\-\.\(\)]+$/', $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:]�������]+$/', $fieldValue) > 0); }, self::RULE_ALPHA_CAPS => function ($fieldName, $fieldValue, $validationParam) { return (preg_match('/^[[:upper:]���]+$/', $fieldValue) > 0); }, self::RULE_ALPHA_SMALL => function ($fieldName, $fieldValue, $validationParam) { return (preg_match('/^[[:lower:]����]+$/', $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:]�������]+$/', $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; } }