Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F726976
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Jan 6, 4:33 AM
Size
14 KB
Mime Type
text/x-diff
Expires
Wed, Jan 8, 4:33 AM (1 d, 18 h ago)
Engine
blob
Format
Raw Data
Handle
537049
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.2.x/core/kernel/utility/validator.php
===================================================================
--- branches/5.2.x/core/kernel/utility/validator.php (revision 16234)
+++ branches/5.2.x/core/kernel/utility/validator.php (revision 16235)
@@ -1,525 +1,527 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kValidator extends kBase {
/**
* Form name, used for validation
*
* @var string
*/
protected $lastFormName = false;
/**
* Prefix & special of last data source
*
* @var string
*/
protected $lastPrefixSpecial = '';
/**
* Object, that holds a data to be validated
*
* @var kDBItem
*/
protected $dataSource = null;
/**
* Holds field errors
*
* @var Array
* @access protected
*/
protected $FieldErrors = Array ();
/**
* Phrases for each error pseudo
*
* @var Array
* @access protected
*/
protected $ErrorMsgs = Array (
'required' => '!la_err_required!', // Field is required
'unique' => '!la_err_unique!', // Field value must be unique
'value_out_of_range' => '!la_err_value_out_of_range!', // Field is out of range, possible values from %s to %s
'length_out_of_range' => '!la_err_length_out_of_range!', // Field is out of range
'bad_type' => '!la_err_bad_type!', // Incorrect data format, please use %s
'invalid_format' => '!la_err_invalid_format!', // Incorrect data format, please use %s
'bad_date_format' => '!la_err_bad_date_format!', // Incorrect date format, please use (%s) ex. (%s)
'primary_lang_required' => '!la_err_primary_lang_required!', // Primary Lang. value Required
);
/**
* Sets data source for validation
*
* @param kDBItem $object
*/
public function setDataSource(&$object)
{
if ( $object->getFormName() === $this->lastFormName && $object->getPrefixSpecial() === $this->lastPrefixSpecial ) {
return ;
}
$this->reset();
$this->dataSource =& $object;
$this->lastFormName = $object->getFormName();
$this->lastPrefixSpecial = $object->getPrefixSpecial();
}
/**
* Validate all item fields based on
* constraints set in each field options
* in config
*
* @return bool
* @access private
*/
public function Validate()
{
// order is critical - should be called BEFORE checking errors
$this->dataSource->UpdateFormattersMasterFields();
$global_res = true;
$fields = array_keys( $this->dataSource->getFields() );
foreach ($fields as $field) {
// call separately, otherwise 2+ validation errors will be ignored
$res = $this->ValidateField($field);
$global_res = $global_res && $res;
}
if ( !$global_res && $this->Application->isDebugMode() ) {
$title_info = $this->dataSource->GetTitleField();
$item_info = Array (
$this->dataSource->IDField . ': <strong>' . $this->dataSource->GetID() . '</strong>',
);
if ( $title_info && reset($title_info) ) {
$item_info[] = key($title_info) . ': <strong>' . current($title_info) . '</strong>';
}
$error_msg = ' Validation failed in prefix - <strong>' . $this->dataSource->Prefix . '</strong> (' . implode('; ', $item_info) . '),
FieldErrors follow (look at items with <strong>"pseudo"</strong> key set)<br />
You may ignore this notice if submitted data really has a validation error';
trigger_error(trim($error_msg), E_USER_NOTICE);
$this->Application->Debugger->dumpVars($this->FieldErrors);
}
return $global_res;
}
/**
* Validates given field
*
* @param string $field
* @return bool
* @access public
*/
public function ValidateField($field)
{
$options = $this->dataSource->GetFieldOptions($field);
$error_field = isset($options['error_field']) ? $options['error_field'] : $field;
$res = $this->GetErrorPseudo($error_field) == '';
$res = $res && $this->ValidateRequired($field, $options);
$res = $res && $this->ValidateType($field, $options);
$res = $res && $this->ValidateRange($field, $options);
$res = $res && $this->ValidateUnique($field, $options);
$res = $res && $this->CustomValidation($field, $options);
return $res;
}
/**
* Check if value is set for required field
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access public
*/
public function ValidateRequired($field, $params)
{
if ( !isset($params['required']) || !$params['required'] ) {
return true;
}
$value = $this->dataSource->GetDBField($field);
if ( $this->Application->ConfigValue('TrimRequiredFields') ) {
$value = trim($value);
}
if ( (string)$value == '' ) {
$this->SetError($field, 'required');
return false;
}
return true;
}
/**
* Check if value in field matches field type specified in config
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
*/
protected function ValidateType($field, $params)
{
$val = $this->dataSource->GetDBField($field);
$type_regex = "#int|integer|double|float|real|numeric|string#";
if ( $val == '' || !isset($params['type']) || !preg_match($type_regex, $params['type']) ) {
return true;
}
if ( $params['type'] == 'numeric' ) {
trigger_error('Invalid field type <strong>' . $params['type'] . '</strong> (in ValidateType method), please use <strong>float</strong> instead', E_USER_NOTICE);
$params['type'] = 'float';
}
$res = is_numeric($val);
if ( $params['type'] == 'string' || $res ) {
$f = 'is_' . $params['type'];
settype($val, $params['type']);
$res = $f($val) && ($val == $this->dataSource->GetDBField($field));
}
if ( !$res ) {
$this->SetError($field, 'bad_type', null, array('type' => $params['type']));
return false;
}
return true;
}
/**
* Check if field value is in range specified in config
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access private
*/
protected function ValidateRange($field, $params)
{
$res = true;
$val = $this->dataSource->GetDBField($field);
if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) {
// validate number
if ( isset($params['max_value_inc'])) {
$res = $res && $val <= $params['max_value_inc'];
$max_val = $params['max_value_inc'].' (inclusive)';
}
if ( isset($params['min_value_inc'])) {
$res = $res && $val >= $params['min_value_inc'];
$min_val = $params['min_value_inc'].' (inclusive)';
}
if ( isset($params['max_value_exc'])) {
$res = $res && $val < $params['max_value_exc'];
$max_val = $params['max_value_exc'].' (exclusive)';
}
if ( isset($params['min_value_exc'])) {
$res = $res && $val > $params['min_value_exc'];
$min_val = $params['min_value_exc'].' (exclusive)';
}
}
if ( !$res ) {
if ( !isset($min_val) ) $min_val = '-∞';
if ( !isset($max_val) ) $max_val = '∞';
$this->SetError($field, 'value_out_of_range', null, array(
'min_value' => $min_val,
'max_value' => $max_val
));
return false;
}
- // validate string
- if ( isset($params['max_len']) ) {
- $res = $res && mb_strlen($val) <= $params['max_len'];
- }
+ if ( strlen($val) > 0 ) {
+ // Validate string.
+ if ( isset($params['max_len']) ) {
+ $res = $res && mb_strlen($val) <= $params['max_len'];
+ }
- if ( isset($params['min_len']) ) {
- $res = $res && mb_strlen($val) >= $params['min_len'];
+ if ( isset($params['min_len']) ) {
+ $res = $res && mb_strlen($val) >= $params['min_len'];
+ }
}
if ( !$res ) {
$error_params = array(
'min_length' => (int)getArrayValue($params, 'min_len'),
'max_length' => (int)getArrayValue($params, 'max_len'),
'value' => mb_strlen($val)
);
$this->SetError($field, 'length_out_of_range', null, $error_params);
return false;
}
return true;
}
/**
* Validates that current record has unique field combination among other table records
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access private
*/
protected function ValidateUnique($field, $params)
{
$unique_fields = getArrayValue($params, 'unique');
if ( $unique_fields === false ) {
return true;
}
$where = Array ();
array_push($unique_fields, $field);
foreach ($unique_fields as $unique_field) {
// if field is not empty or if it is required - we add where condition
$field_value = $this->dataSource->GetDBField($unique_field);
if ( (string)$field_value != '' || $this->dataSource->isRequired($unique_field) ) {
$where[] = '`' . $unique_field . '` = ' . $this->Conn->qstr($field_value);
}
else {
// not good if we check by less fields than indicated
return true;
}
}
// This can ONLY happen if all unique fields are empty and not required.
// In such case we return true, because if unique field is not required there may be numerous empty values
// if (!$where) return true;
$sql = 'SELECT COUNT(*)
FROM %s
WHERE (' . implode(') AND (', $where) . ') AND (' . $this->dataSource->IDField . ' <> ' . (int)$this->dataSource->GetID() . ')';
$res_temp = $this->Conn->GetOne( str_replace('%s', $this->dataSource->TableName, $sql) );
$current_table_only = getArrayValue($params, 'current_table_only'); // check unique record only in current table
$res_live = $current_table_only ? 0 : $this->Conn->GetOne( str_replace('%s', $this->Application->GetLiveName($this->dataSource->TableName), $sql) );
$res = ($res_temp == 0) && ($res_live == 0);
if ( !$res ) {
$this->SetError($field, 'unique');
return false;
}
return true;
}
/**
* Check field value by user-defined alghoritm
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
*/
protected function CustomValidation($field, $params)
{
return true;
}
/**
* Set's field error, if pseudo passed not found then create it with message text supplied.
* Don't overwrite existing pseudo translation.
*
* @param string $field
* @param string $pseudo
* @param string $error_label
* @param Array $error_params
*
* @return bool
* @access public
*/
public function SetError($field, $pseudo, $error_label = null, $error_params = null)
{
$error_field = $this->dataSource->GetFieldOption($field, 'error_field', false, $field);
if ( $this->GetErrorPseudo($error_field) ) {
// don't set more then one error on field
return false;
}
$this->FieldErrors[$error_field]['pseudo'] = $pseudo;
if ( isset($error_params) ) {
if ( array_key_exists('value', $error_params) ) {
$this->FieldErrors[$error_field]['value'] = $error_params['value'];
unset($error_params['value']);
}
// additional params, that helps to determine error sources
$this->FieldErrors[$error_field]['params'] = $error_params;
}
if ( isset($error_label) && !isset($this->ErrorMsgs[$pseudo]) ) {
// label for error (only when not already set)
$this->ErrorMsgs[$pseudo] = (substr($error_label, 0, 1) == '+') ? substr($error_label, 1) : '!'.$error_label.'!';
}
return true;
}
/**
* Return error message for field
*
* @param string $field
* @param bool $force_escape
* @return string
* @access public
*/
public function GetErrorMsg($field, $force_escape = null)
{
$error_pseudo = $this->GetErrorPseudo($field);
if ( !$error_pseudo ) {
return '';
}
// if special error msg defined in config
$error_msgs = $this->dataSource->GetFieldOption($field, 'error_msgs', false, Array ());
if ( isset($error_msgs[$error_pseudo]) ) {
$msg = $error_msgs[$error_pseudo];
}
else {
// fallback to defaults
if ( !isset($this->ErrorMsgs[$error_pseudo]) ) {
trigger_error('No user message is defined for pseudo error <strong>' . $error_pseudo . '</strong>', E_USER_WARNING);
return $error_pseudo; //return the pseudo itself
}
$msg = $this->ErrorMsgs[$error_pseudo];
}
$msg = $this->Application->ReplaceLanguageTags($msg, $force_escape);
if ( isset($this->FieldErrors[$field]['params']) ) {
$params = $this->FieldErrors[$field]['params'];
}
else {
$params = array();
}
$field_phrase = $this->Application->isAdmin ? 'la_fld_' . $field : 'lu_fld_' . $field;
$params['field'] = $this->Application->Phrase($field_phrase);
foreach ( $params as $param_name => $param_value ) {
$msg = str_replace('{' . $param_name . '}', $param_value, $msg, $replacement_count);
}
if ( strpos($msg, '%s') !== false ) {
trigger_error('Unexpected "%s" in field "<b>' . $field . '</b>" validation error message (pseudo: "<b>' . $error_pseudo . '</b>") in "<b>' . $this->dataSource->Prefix . '</b>" unit', E_USER_WARNING);
}
return $msg;
}
/**
* Returns error pseudo
*
* @param string $field
* @return string
* @access public
*
*/
public function GetErrorPseudo($field)
{
if ( !isset($this->FieldErrors[$field]) ) {
return '';
}
return isset($this->FieldErrors[$field]['pseudo']) ? $this->FieldErrors[$field]['pseudo'] : '';
}
/**
* Removes error on field
*
* @param string $field
* @access public
*/
public function RemoveError($field)
{
unset( $this->FieldErrors[$field] );
}
/**
* Returns field errors
*
* @return Array
* @access public
*/
public function GetFieldErrors()
{
return $this->FieldErrors;
}
/**
* Check if item has errors
*
* @param Array $skip_fields fields to skip during error checking
* @return bool
* @access public
*/
public function HasErrors( $skip_fields = Array () )
{
$fields = array_keys( $this->dataSource->getFields() );
$fields = array_diff($fields, $skip_fields);
foreach ($fields as $field) {
// if Formatter has set some error messages during values parsing
if ( $this->GetErrorPseudo($field) ) {
return true;
}
}
return false;
}
/**
* Clears all validation errors
*
* @access public
*/
public function reset()
{
$this->FieldErrors = Array();
}
}
Event Timeline
Log In to Comment