Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Mon, Jan 6, 4:33 AM

in-portal

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 = '-&infin;';
if ( !isset($max_val) ) $max_val = '&infin;';
$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