Index: trunk/core/kernel/db/dbitem.php
===================================================================
diff -u -r3543 -r3868
--- trunk/core/kernel/db/dbitem.php (.../dbitem.php) (revision 3543)
+++ trunk/core/kernel/db/dbitem.php (.../dbitem.php) (revision 3868)
@@ -7,66 +7,67 @@
* @package kernel4
*/
class kDBItem extends kDBBase {
-
+
/**
* Description
*
* @var array Associative array of current item' field values
* @access public
*/
var $FieldValues;
-
+
/**
* Unformatted field values, before parse
*
* @var Array
* @access private
*/
var $DirtyFieldValues = Array();
-
+
var $FieldErrors;
-
+
var $ErrorMsgs = Array();
-
+
/**
* If set to true, Update will skip Validation before running
*
* @var array Associative array of current item' field values
* @access public
*/
var $IgnoreValidation = false;
-
+
var $Loaded = false;
-
+
/**
* Holds item' primary key value
*
* @var int Value of primary key field for current item
* @access public
*/
var $ID;
-
+
function kDBItem()
{
parent::kDBBase();
- $this->ErrorMsgs['required'] = 'Field is required';
- $this->ErrorMsgs['unique'] = 'Field value must be unique';
- $this->ErrorMsgs['value_out_of_range'] = 'Field is out of range, possible values from %s to %s';
- $this->ErrorMsgs['length_out_of_range'] = 'Field is out of range';
- $this->ErrorMsgs['bad_type'] = 'Incorrect data format, please use %s';
- $this->ErrorMsgs['bad_date_format'] = 'Incorrect date format, please use (%s) ex. (%s)';
+ $this->ErrorMsgs['required'] = $this->Application->Phrase('la_err_required'); //'Field is required';
+ $this->ErrorMsgs['unique'] = $this->Application->Phrase('la_err_unique'); //'Field value must be unique';
+ $this->ErrorMsgs['value_out_of_range'] = $this->Application->Phrase('la_err_value_out_of_range'); //'Field is out of range, possible values from %s to %s';
+ $this->ErrorMsgs['length_out_of_range'] = $this->Application->Phrase('la_err_length_out_of_range'); //'Field is out of range';
+ $this->ErrorMsgs['bad_type'] = $this->Application->Phrase('la_err_bad_type'); //'Incorrect data format, please use %s';
+ $this->ErrorMsgs['bad_date_format'] = $this->Application->Phrase('la_err_bad_date_format'); //'Incorrect date format, please use (%s) ex. (%s)';
+ $this->ErrorMsgs['primary_lang_required'] = $this->Application->Phrase('la_err_primary_lang_required');
}
-
+
function SetDirtyField($field_name, $field_value)
{
$this->DirtyFieldValues[$field_name] = $field_value;
}
-
+
function GetDirtyField($field_name)
{
return $this->DirtyFieldValues[$field_name];
}
-
+
/**
* Set's default values for all fields
*
@@ -106,7 +107,7 @@
}
$this->SetDBField($name,$parsed);
}
-
+
/**
* Sets current item field value
* (doesn't apply formatting)
@@ -124,7 +125,7 @@
$formatter->UpdateSubFields($name, $value, $this->Fields[$name], $this);
}*/
}
-
+
/**
* Set's field error, if pseudo passed not found then create it with message text supplied.
* Don't owerrite existing pseudo translation.
@@ -137,14 +138,14 @@
{
$error_field = isset($this->Fields[$field]['error_field']) ? $this->Fields[$field]['error_field'] : $field;
$this->FieldErrors[$error_field]['pseudo'] = $pseudo;
-
+
$error_msg = $error_label ? $this->Application->Phrase($error_label) : '';
if ($error_label && !getArrayValue($this->ErrorMsgs, $pseudo))
{
$this->ErrorMsgs[$pseudo] = $error_msg;
}
}
-
+
/**
* Return current item' field value by field name
* (doesn't apply formatter)
@@ -157,19 +158,19 @@
{
return $this->FieldValues[$name];
}
-
+
function HasField($name)
{
- return isset($this->FieldValues[$name]);
+ return isset($this->FieldValues[$name]);
}
-
+
function GetFieldValues()
{
return $this->FieldValues;
}
-
+
/**
- * Sets item' fields corresponding to elements in passed $hash values.
+ * Sets item' fields corresponding to elements in passed $hash values.
*
* The function sets current item fields to values passed in $hash, by matching $hash keys with field names
* of current item. If current item' fields are unknown {@link kDBItem::PrepareFields()} is called before acutally setting the fields
@@ -188,27 +189,27 @@
if ( is_array($set_fields) && !in_array($field_name, $set_fields) ) continue;
$this->SetDirtyField($field_name, $field_value);
}
-
- // formats all fields using associated formatters
+
+ // formats all fields using associated formatters
foreach ($hash as $field_name => $field_value)
{
if( eregi("^[0-9]+$", $field_name) || !array_key_exists($field_name,$this->Fields) ) continue;
if ( is_array($set_fields) && !in_array($field_name, $set_fields) ) continue;
$this->SetField($field_name,$field_value);
}
}
-
+
function SetDBFieldsFromHash($hash, $set_fields=null)
{
foreach ($hash as $field_name => $field_value)
{
if( eregi("^[0-9]+$", $field_name) || !array_key_exists($field_name,$this->Fields) ) continue;
if ( is_array($set_fields) && !in_array($field_name, $set_fields) ) continue;
-
+
$this->SetDBField($field_name, $field_value);
}
}
-
+
/**
* Returns part of SQL WHERE clause identifing the record, ex. id = 25
*
@@ -223,16 +224,16 @@
function GetKeyClause($method=null, $keys_hash = null)
{
if( !isset($keys_hash) ) $keys_hash = Array($this->IDField => $this->ID);
-
+
$ret = '';
foreach($keys_hash as $field => $value)
{
- $ret .= '(`'.$this->TableName.'`.'.$field.' = '.$this->Conn->qstr($value).') AND ';
+ $ret .= '(`'.$this->TableName.'`.'.$field.' = '.$this->Conn->qstr($value).') AND ';
}
-
+
return preg_replace('/(.*) AND $/', '\\1', $ret);
}
-
+
/**
* Loads item from the database by given id
*
@@ -255,14 +256,14 @@
$keys_sql = $this->GetKeyClause('load');
}
if ( isset($id_field_name) ) $this->setIDField( $this->Application->getUnitOption($this->Prefix, 'IDField') );
-
-
+
+
if( ($id === false) || !$keys_sql ) return $this->Clear();
-
+
if( !$this->raiseEvent('OnBeforeItemLoad', $id) ) return false;
-
+
$q = $this->GetSelectSQL().' WHERE '.$keys_sql;
-
+
$field_values = $this->Conn->GetRow($q);
if($field_values)
{
@@ -272,11 +273,11 @@
{
return $this->Clear();
}
-
+
if( is_array($id) || isset($id_field_name) ) $this->setID( $this->FieldValues[$this->IDField] );
$this->UpdateFormattersSubFields(); // used for updating separate virtual date/time fields from DB timestamp (for example)
-
+
$this->raiseEvent('OnAfterItemLoad', $this->GetID() );
$this->Loaded = true;
return true;
@@ -293,7 +294,7 @@
$sql = $this->addCalculatedFields($this->SelectClause);
return parent::GetSelectSQL($sql);
}
-
+
function UpdateFormattersMasterFields()
{
foreach ($this->Fields as $field => $options) {
@@ -303,7 +304,7 @@
}
}
}
-
+
function SkipField($field_name, $force_id=false)
{
$skip = false;
@@ -318,7 +319,7 @@
return $skip;
}
-
+
/**
* Updates previously loaded record with current item' values
*
@@ -329,25 +330,25 @@
function Update($id=null, $system_update=false)
{
if( isset($id) ) $this->setID($id);
-
+
if( !$this->raiseEvent('OnBeforeItemUpdate') ) return false;
-
+
if( !isset($this->ID) ) return false;
-
+
// Validate before updating
if( !$this->IgnoreValidation && !$this->Validate() ) return false;
if( !$this->raiseEvent('OnAfterItemValidate') ) return false;
-
+
//Nothing to update
if(!$this->FieldValues) return true;
-
+
$sql = sprintf('UPDATE %s SET ',$this->TableName);
foreach ($this->FieldValues as $field_name => $field_value)
{
if ($this->SkipField($field_name)) continue;
-
+
$real_field_name = eregi_replace("^.*\.", '',$field_name); //removing table names from field names
-
+
//Adding part of SET clause for current field, escaping data with ADODB' qstr
if (is_null( $this->FieldValues[$field_name] )) {
if (isset($this->Fields[$field_name]['not_null']) && $this->Fields[$field_name]['not_null']) {
@@ -362,20 +363,20 @@
}
}
$sql = ereg_replace(", $", '', $sql); //Removing last comma and space
-
+
$sql.= sprintf(' WHERE %s', $this->GetKeyClause('update')); //Adding WHERE clause with Primary Key
-
+
if( $this->Conn->ChangeQuery($sql) === false ) return false;
-
+
$affected = $this->Conn->getAffectedRows();
if (!$system_update && $affected == 1){
$this->setModifiedFlag();
}
-
+
$this->raiseEvent('OnAfterItemUpdate');
return true;
- }
-
+ }
+
/**
* Validate all item fields based on
* constraints set in each field options
@@ -395,16 +396,16 @@
$res = $res && $this->ValidateUnique($field, $params);
$res = $res && $this->ValidateRequired($field, $params);
$res = $res && $this->CustomValidation($field, $params);
-
- // If Formatter has set some error messages during values parsing
+
+ // If Formatter has set some error messages during values parsing
$error_field = isset($params['error_field']) ? $params['error_field'] : $field;
if (isset($this->FieldErrors[$error_field]['pseudo']) && $this->FieldErrors[$error_field] != '') {
$global_res = false;
}
-
+
$global_res = $global_res && $res;
}
-
+
if (!$global_res && $this->Application->isDebugMode() )
{
global $debugger;
@@ -413,10 +414,10 @@
trigger_error( $error_msg, E_USER_NOTICE);
$debugger->dumpVars($this->FieldErrors);
}
-
+
return $global_res;
- }
-
+ }
+
/**
* Check field value by user-defined alghoritm
*
@@ -428,7 +429,7 @@
{
return true;
}
-
+
/**
* Check if item has errors
*
@@ -438,17 +439,17 @@
function HasErrors($skip_fields)
{
$global_res = false;
-
+
foreach ($this->Fields as $field => $field_params) {
- // If Formatter has set some error messages during values parsing
+ // If Formatter has set some error messages during values parsing
if ( !( in_array($field, $skip_fields) ) &&
isset($this->FieldErrors[$field]['pseudo']) && $this->FieldErrors[$field] != '') {
$global_res = true;
}
}
return $global_res;
}
-
+
/**
* Check if value in field matches field type specified in config
*
@@ -462,10 +463,10 @@
$val = $this->FieldValues[$field];
$error_field = isset($params['error_field']) ? $params['error_field'] : $field;
if ( $val != '' &&
- isset($params['type']) &&
+ isset($params['type']) &&
preg_match("#int|integer|double|float|real|numeric|string#", $params['type'])
) {
- $res = is_numeric($val);
+ $res = is_numeric($val);
if($params['type']=='string' || $res)
{
$f = 'is_'.$params['type'];
@@ -480,7 +481,7 @@
}
return $res;
}
-
+
/**
* Check if value is set for required field
*
@@ -501,7 +502,7 @@
if (!$res && getArrayValue($options, 'formatter') != 'kUploadFormatter') $this->FieldErrors[$error_field]['pseudo'] = 'required';
return $res;
}
-
+
/**
* Validates that current record has unique field combination among other table records
*
@@ -523,21 +524,21 @@
{
$where[] = '`'.$unique_field.'` = '.$this->Conn->qstr( $this->GetDBField($unique_field) );
}
-
+
$sql = 'SELECT COUNT(*) FROM %s WHERE ('.implode(') AND (',$where).') AND ('.$this->IDField.' <> '.(int)$this->ID.')';
-
+
$res_temp = $this->Conn->GetOne( str_replace('%s', $this->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', kTempTablesHandler::GetLiveName($this->TableName), $sql) );
-
+
$res = ($res_temp == 0) && ($res_live == 0);
-
+
if(!$res) $this->FieldErrors[$error_field]['pseudo'] = 'unique';
}
return $res;
}
-
+
/**
* Check if field value is in range specified in config
*
@@ -551,7 +552,7 @@
$res = true;
$val = $this->FieldValues[$field];
$error_field = isset($params['error_field']) ? $params['error_field'] : $field;
-
+
if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) {
if ( isset($params['max_value_inc'])) {
$res = $res && $val <= $params['max_value_inc'];
@@ -572,10 +573,10 @@
}
if (!$res) {
$this->FieldErrors[$error_field]['pseudo'] = 'value_out_of_range';
-
+
if ( !isset($min_val) ) $min_val = '-∞';
if ( !isset($max_val) ) $max_val = '∞';
-
+
$this->FieldErrors[$error_field]['params'] = Array( $min_val, $max_val );
return $res;
}
@@ -592,7 +593,7 @@
}
return $res;
}
-
+
/**
* Return error message for field
*
@@ -603,26 +604,31 @@
function GetErrorMsg($field, $force_escape = null)
{
if( !isset($this->FieldErrors[$field]) ) return '';
-
+
$err = getArrayValue($this->FieldErrors[$field], 'pseudo');
+ if (!$err) return '';
+ // if special error msg defined in config
if( isset($this->Fields[$field]['error_msgs'][$err]) )
{
$msg = $this->Fields[$field]['error_msgs'][$err];
$msg = $this->Application->ReplaceLanguageTags($msg, $force_escape);
}
- else
+ else //fall back to defaults
{
- if( !isset($this->ErrorMsgs[$err]) ) return $err;
+ if( !isset($this->ErrorMsgs[$err]) ) {
+ trigger_error('No user message is defined for pseudo error '.$err.'
', E_USER_WARNING);
+ return $err; //return the pseudo itself
+ }
$msg = $this->ErrorMsgs[$err];
}
-
+
if ( isset($this->FieldErrors[$field]['params']) )
{
- return vsprintf($msg, $this->FieldErrors[$field]['params']);
+ return vsprintf($msg, $this->FieldErrors[$field]['params']);
}
return $msg;
}
-
+
/**
* Creates a record in the database table with current item' values
*
@@ -637,15 +643,15 @@
// Validating fields before attempting to create record
if( !$this->IgnoreValidation && !$this->Validate() ) return false;
if( !$this->raiseEvent('OnAfterItemValidate') ) return false;
-
+
if (is_int($force_id)) {
$this->FieldValues[$this->IDField] = $force_id;
}
elseif (!$force_id || !is_bool($force_id)) {
$this->FieldValues[$this->IDField] = $this->generateID();
}
-
-
+
+
$fields_sql = '';
$values_sql = '';
foreach ($this->FieldValues as $field_name => $field_value)
@@ -677,19 +683,19 @@
//Executing the query and checking the result
if($this->Conn->ChangeQuery($sql) === false) return false;
-
+
$insert_id = $this->Conn->getInsertID();
if($insert_id == 0) $insert_id = $this->FieldValues[$this->IDField];
$this->setID($insert_id);
-
+
if (!$system_create){
$this->setModifiedFlag();
}
-
+
$this->raiseEvent('OnAfterItemCreate');
return true;
}
-
+
/**
* Deletes the record from databse
*
@@ -699,20 +705,20 @@
function Delete($id = null)
{
if( isset($id) ) $this->setID($id);
-
+
if( !$this->raiseEvent('OnBeforeItemDelete') ) return false;
-
+
$q = 'DELETE FROM '.$this->TableName.' WHERE '.$this->GetKeyClause('Delete');
-
+
$ret = $this->Conn->ChangeQuery($q);
-
+
$this->setModifiedFlag();
-
+
$this->raiseEvent('OnAfterItemDelete');
-
+
return $ret;
}
-
+
/**
* Sets new name for item in case if it is beeing copied
* in same table
@@ -725,7 +731,7 @@
{
$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
if (!$title_field || isset($this->CalculatedFields[$title_field]) ) return;
-
+
$new_name = $this->GetDBField($title_field);
$original_checked = false;
do {
@@ -735,34 +741,34 @@
elseif ($original_checked) {
$new_name = 'Copy of '.$new_name;
}
-
- // if we are cloning in temp table this will look for names in temp table,
+
+ // if we are cloning in temp table this will look for names in temp table,
// since object' TableName contains correct TableName (for temp also!)
// if we are cloning live - look in live
$query = 'SELECT '.$title_field.' FROM '.$this->TableName.'
WHERE '.$title_field.' = '.$this->Conn->qstr($new_name);
-
+
$foreign_key_field = getArrayValue($master, 'ForeignKey');
$foreign_key_field = is_array($foreign_key_field) ? $foreign_key_field[ $master['ParentPrefix'] ] : $foreign_key_field;
-
+
if ($foreign_key_field && isset($foreign_key)) {
$query .= ' AND '.$foreign_key_field.' = '.$foreign_key;
}
-
+
$res = $this->Conn->GetOne($query);
-
+
/*// if not found in live table, check in temp table if applicable
if ($res === false && $object->Special == 'temp') {
$query = 'SELECT '.$name_field.' FROM '.$this->GetTempName($master['TableName']).'
WHERE '.$name_field.' = '.$this->Conn->qstr($new_name);
$res = $this->Conn->GetOne($query);
}*/
-
+
$original_checked = true;
} while ($res !== false);
$this->SetDBField($title_field, $new_name);
}
-
+
function raiseEvent($name, $id=null)
{
if( !isset($id) ) $id = $this->GetID();
@@ -771,7 +777,7 @@
$this->Application->HandleEvent($event);
return $event->status == erSUCCESS ? true : false;
}
-
+
/**
* Set's new ID for item
*
@@ -783,7 +789,7 @@
$this->ID = $new_id;
$this->SetDBField($this->IDField, $new_id);
}
-
+
/**
* Generate and set new temporary id
*
@@ -794,11 +800,11 @@
$new_id = (int)$this->Conn->GetOne('SELECT MIN('.$this->IDField.') FROM '.$this->TableName);
if($new_id > 0) $new_id = 0;
--$new_id;
-
+
$this->Conn->Query('UPDATE '.$this->TableName.' SET `'.$this->IDField.'` = '.$new_id.' WHERE `'.$this->IDField.'` = '.$this->GetID());
$this->SetID($new_id);
}
-
+
/**
* Set's modification flag for main prefix of current prefix to true
*
@@ -810,7 +816,7 @@
$main_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
$this->Application->StoreVar($main_prefix.'_modified', '1');
}
-
+
/**
* Returns ID of currently processed record
*
@@ -821,7 +827,7 @@
{
return $this->ID;
}
-
+
/**
* Generates ID for new items before inserting into database
*
@@ -832,7 +838,7 @@
{
return 0;
}
-
+
/**
* Returns true if item was loaded successfully by Load method
*
@@ -842,7 +848,7 @@
{
return $this->Loaded;
}
-
+
/**
* Checks if field is required
*
@@ -853,7 +859,7 @@
{
return getArrayValue( $this->Fields[$field], 'required' );
}
-
+
/**
* Sets new required flag to field
*
@@ -864,7 +870,7 @@
{
$this->Fields[$field]['required'] = $is_required;
}
-
+
function Clear()
{
$this->setID(null);
@@ -874,7 +880,7 @@
$this->FieldErrors = Array();
return $this->Loaded;
}
-
+
function Query($force = false)
{
if( $this->Application->isDebugMode() )