Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Feb 6, 1:26 PM

in-portal

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: branches/5.2.x/core/kernel/db/cat_dbitem.php
===================================================================
--- branches/5.2.x/core/kernel/db/cat_dbitem.php (revision 14595)
+++ branches/5.2.x/core/kernel/db/cat_dbitem.php (revision 14596)
@@ -1,603 +1,636 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 kCatDBItem extends kDBItem {
/**
* Category path, needed for import
*
* @var Array
*/
var $CategoryPath = Array();
/**
* Use automatic filename generation
*
* @var bool
*/
var $useFilenames = true;
/**
* Use pending editing abilities during item (delegated by permissions)
*
* @var bool
*/
var $usePendingEditing = false;
function Clear($new_id = null)
{
parent::Clear($new_id);
$this->CategoryPath = Array();
}
/**
* Set's prefix and special
*
* @param string $prefix
* @param string $special
* @access public
*/
function Init($prefix, $special)
{
parent::Init($prefix, $special);
$this->usePendingEditing = $this->Application->getUnitOption($this->Prefix, 'UsePendingEditing');
}
- function Create($force_id = false, $system_create = false)
+ /**
+ * Creates a record in the database table with current item' values
+ *
+ * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
+ * @param bool $system_create
+ * @return bool
+ * @access public
+ */
+ public function Create($force_id = false, $system_create = false)
{
$ret = parent::Create($force_id, $system_create);
if ($ret) {
// TODO: move to OnAfterItemCreate method
$this->assignPrimaryCategory();
}
return $ret;
}
/**
* Assigns primary category for the item
*
* @access public
*/
function assignPrimaryCategory()
{
if ( $this->GetDBField('CategoryId') <= 0 ) {
// set primary category in item object
$this->SetDBField('CategoryId', $this->Application->GetVar('m_cat_id'));
}
$this->assignToCategory($this->GetDBField('CategoryId'), true);
}
- function Update($id=null, $system_update=false)
+ /**
+ * Updates previously loaded record with current item' values
+ *
+ * @access public
+ * @param int $id Primary Key Id to update
+ * @param bool $system_update
+ * @return bool
+ * @access public
+ */
+ public function Update($id = null, $system_update = false)
{
- $this->VirtualFields['ResourceId'] = Array();
+ $this->VirtualFields['ResourceId'] = Array ();
- if ($this->GetChangedFields()) {
+ if ( $this->GetChangedFields() ) {
$now = adodb_mktime();
$this->SetDBField('Modified_date', $now);
$this->SetDBField('Modified_time', $now);
$this->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
}
- if ($this->useFilenames) {
+ if ( $this->useFilenames ) {
$this->checkFilename();
$this->generateFilename();
}
$ret = parent::Update($id, $system_update);
- if ($ret) {
+ if ( $ret ) {
$filename = $this->useFilenames ? (string)$this->GetDBField('Filename') : '';
- $sql = 'UPDATE '.$this->CategoryItemsTable().'
- SET Filename = '.$this->Conn->qstr($filename).'
- WHERE ItemResourceId = '.$this->GetDBField('ResourceId');
+ $sql = 'UPDATE ' . $this->CategoryItemsTable() . '
+ SET Filename = ' . $this->Conn->qstr($filename) . '
+ WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
$this->Conn->Query($sql);
}
unset($this->VirtualFields['ResourceId']);
+
return $ret;
}
/**
* Returns CategoryItems table based on current item mode (temp/live)
*
* @return string
*/
function CategoryItemsTable()
{
$table = TABLE_PREFIX.'CategoryItems';
if ($this->Application->IsTempTable($this->TableName)) {
$table = $this->Application->GetTempName($table, 'prefix:'.$this->Prefix);
}
return $table;
}
function checkFilename()
{
if( !$this->GetDBField('AutomaticFilename') )
{
$filename = $this->GetDBField('Filename');
$this->SetDBField('Filename', $this->stripDisallowed($filename) );
}
}
function Copy($cat_id=null)
{
if (!isset($cat_id)) $cat_id = $this->Application->GetVar('m_cat_id');
$this->NameCopy($cat_id);
return $this->Create($cat_id);
}
public function NameCopy($master=null, $foreign_key=null, $title_field=null, $format='Copy %1$s of %2$s')
{
$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
if (!$title_field) return;
$new_name = $this->GetDBField($title_field);
$cat_id = (int)$this->Application->GetVar('m_cat_id');
$original_checked = false;
do {
if ( preg_match('/Copy ([0-9]*) *of (.*)/', $new_name, $regs) ) {
$new_name = 'Copy '.( (int)$regs[1] + 1 ).' of '.$regs[2];
}
elseif ($original_checked) {
$new_name = 'Copy of '.$new_name;
}
$query = 'SELECT '.$title_field.' FROM '.$this->TableName.'
LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON
('.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$this->TableName.'.ResourceId)
WHERE ('.TABLE_PREFIX.'CategoryItems.CategoryId = '.$cat_id.') AND '.
$title_field.' = '.$this->Conn->qstr($new_name);
$res = $this->Conn->GetOne($query);
$original_checked = true;
} while ($res !== false);
$this->SetDBField($title_field, $new_name);
// this is needed, because Create will create items in its own CategoryId (if it's set),
// but we need to create it in target Paste category @see{kCatDBItem::Create} and its primary_category detection
$this->SetDBField('CategoryId', $cat_id);
}
/**
* Changes item primary category to given/current category
*
* @param int $category_id
*/
function MoveToCat($category_id = null)
{
// $this->NameCopy();
if (!isset($category_id)) {
$category_id = $this->Application->GetVar('m_cat_id');
}
$table_name = TABLE_PREFIX . 'CategoryItems';
if ($this->IsTempTable()) {
$table_name = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix);
}
// check if the item already exists in destination category
$sql = 'SELECT PrimaryCat
FROM ' . $table_name . '
WHERE (CategoryId = ' . (int)$category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
$is_primary = $this->Conn->GetOne($sql);
// if it's not found is_primary will be FALSE, if it's found but not primary it will be int 0
$exists = $is_primary !== false;
if ($exists) {
// if the item already exists in destination category
if ($is_primary) {
// do nothing when we paste to primary
return ;
}
// if it's not primary - delete it from destination category, as we will move it from current primary below
$sql = 'DELETE FROM ' . $table_name . '
WHERE (CategoryId = ' . (int)$category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
$this->Conn->Query($sql);
}
// change category id in existing primary category record
$sql = 'UPDATE ' . $table_name . '
SET CategoryId = ' . (int)$category_id . '
WHERE (ItemResourceId = ' . $this->GetDBField('ResourceId') . ') AND (PrimaryCat = 1)';
$this->Conn->Query($sql);
$this->Update();
}
/**
* When item is deleted, then also delete it from all categories
*
* @param int $id
* @return bool
+ * @access public
*/
- function Delete($id = null)
+ public function Delete($id = null)
{
- if( isset($id) ) {
+ if ( isset($id) ) {
$this->setID($id);
}
$this->Load($this->GetID());
$ret = parent::Delete();
- if ($ret) {
+ if ( $ret ) {
// TODO: move to OnAfterItemDelete method
$query = ' DELETE FROM ' . $this->CategoryItemsTable() . '
WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
$this->Conn->Query($query);
}
return $ret;
}
/**
* Deletes item from categories
*
* @param Array $delete_category_ids
* @author Alex
*/
function DeleteFromCategories($delete_category_ids)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); // because item was loaded before by ResourceId
- $ci_table = $this->Application->getUnitOption($this->Prefix.'-ci', 'TableName');
+ $ci_table = $this->Application->getUnitOption($this->Prefix . '-ci', 'TableName');
$resource_id = $this->GetDBField('ResourceId');
- $item_cats_sql = 'SELECT CategoryId FROM %s WHERE ItemResourceId = %s';
- $delete_category_items_sql = 'DELETE FROM %s WHERE ItemResourceId = %s AND CategoryId IN (%s)';
+ $item_cats_sql = ' SELECT CategoryId
+ FROM %s
+ WHERE ItemResourceId = %s';
+
+ $delete_category_items_sql = ' DELETE FROM %s
+ WHERE ItemResourceId = %s AND CategoryId IN (%s)';
$category_ids = $this->Conn->GetCol( sprintf($item_cats_sql, $ci_table, $resource_id) );
$cats_left = array_diff($category_ids, $delete_category_ids);
- if(!$cats_left)
- {
- $sql = 'SELECT %s FROM %s WHERE ResourceId = %s';
- $ids = $this->Conn->GetCol( sprintf($sql, $id_field, $this->TableName, $resource_id) );
- $temp =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp->DeleteItems($this->Prefix, $this->Special, $ids);
+ if ( !$cats_left ) {
+ $sql = 'SELECT %s
+ FROM %s
+ WHERE ResourceId = %s';
+ $ids = $this->Conn->GetCol(sprintf($sql, $id_field, $this->TableName, $resource_id));
+
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, $ids);
}
- else
- {
- $this->Conn->Query( sprintf($delete_category_items_sql, $ci_table, $resource_id, implode(',', $delete_category_ids) ) );
+ else {
+ $this->Conn->Query( sprintf($delete_category_items_sql, $ci_table, $resource_id, implode(',', $delete_category_ids)) );
- $sql = 'SELECT CategoryId FROM %s WHERE PrimaryCat = 1 AND ItemResourceId = %s';
- $primary_cat_id = $this->Conn->GetCol( sprintf($sql, $ci_table, $resource_id) );
- if( count($primary_cat_id) == 0 )
- {
- $sql = 'UPDATE %s SET PrimaryCat = 1 WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
- $this->Conn->Query( sprintf($sql, $ci_table, reset($cats_left), $resource_id ) );
+ $sql = 'SELECT CategoryId
+ FROM %s
+ WHERE PrimaryCat = 1 AND ItemResourceId = %s';
+ $primary_cat_id = $this->Conn->GetCol(sprintf($sql, $ci_table, $resource_id));
+
+ if ( count($primary_cat_id) == 0 ) {
+ $sql = 'UPDATE %s
+ SET PrimaryCat = 1
+ WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
+ $this->Conn->Query( sprintf($sql, $ci_table, reset($cats_left), $resource_id) );
}
}
}
/**
* replace not allowed symbols with "_" chars + remove duplicate "_" chars in result
*
* @param string $string
* @return string
*/
function stripDisallowed($filename)
{
$filenames_helper =& $this->Application->recallObject('FilenamesHelper');
+ /* @var $filenames_helper kFilenamesHelper */
+
$table = $this->IsTempTable() ? $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems', 'prefix:'.$this->Prefix) : TABLE_PREFIX.'CategoryItems';
return $filenames_helper->stripDisallowed($table, 'ItemResourceId', $this->GetDBField('ResourceId'), $filename);
}
/* commented out because it's called only from stripDisallowed body, which is moved to helper
function checkAutoFilename($filename)
{
$filenames_helper =& $this->Application->recallObject('FilenamesHelper');
return $filenames_helper->checkAutoFilename($this->TableName, $this->IDField, $this->GetID(), $filename);
}*/
/**
* Generate item's filename based on it's title field value
*
- * @return string
+ * @return void
+ * @access protected
*/
- function generateFilename()
+ protected function generateFilename()
{
- if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) return false;
+ if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) {
+ return ;
+ }
$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
- if (preg_match('/l([\d]+)_(.*)/', $title_field, $regs)) {
+
+ if ( preg_match('/l([\d]+)_(.*)/', $title_field, $regs) ) {
// if title field is multilingual, then use it's name from primary language
- $title_field = 'l'.$this->Application->GetDefaultLanguageId().'_'.$regs[2];
+ $title_field = 'l' . $this->Application->GetDefaultLanguageId() . '_' . $regs[2];
}
- $name = $this->stripDisallowed( $this->GetDBField($title_field) );
- if ( $name != $this->GetDBField('Filename') ) $this->SetDBField('Filename', $name);
- }
+ $name = $this->stripDisallowed( $this->GetDBField($title_field) );
- /**
- * Check if value is set for required field
- *
- * @param string $field field name
- * @param Array $params field options from config
- * @return bool
- * @access private
- */
- function ValidateRequired($field, $params)
- {
- $res = true;
- if (getArrayValue($params, 'required')) {
- $res = ( (string) $this->FieldValues[$field] != '');
+ if ( $name != $this->GetDBField('Filename') ) {
+ $this->SetDBField('Filename', $name);
}
- if (!$res) {
- $this->SetError($field, 'required');
- }
- return $res;
}
/**
* Adds item to other category
*
* @param int $category_id
* @param bool $is_primary
+ * @return void
+ * @access public
*/
- function assignToCategory($category_id, $is_primary = false)
+ public function assignToCategory($category_id, $is_primary = false)
{
$table = $this->CategoryItemsTable();
- $key_clause = '(ItemResourceId = '.$this->GetDBField('ResourceId').')';
+ $key_clause = '(ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
- // get all cateories, where item is in
- $sql = 'SELECT PrimaryCat, CategoryId FROM '.$table.' WHERE '.$key_clause;
+ // get all categories, where item is in
+ $sql = 'SELECT PrimaryCat, CategoryId
+ FROM ' . $table . '
+ WHERE ' . $key_clause;
$item_categories = $this->Conn->GetCol($sql, 'CategoryId');
- if (!$item_categories) {
- $item_categories = Array();
- $primary_found = false;
- }
- // find primary category
- foreach ($item_categories as $item_category_id => $primary_found) {
- if ($primary_found) {
- break;
+ $primary_found = $item_category_id = false;
+
+ if ( $item_categories ) {
+ // find primary category
+ foreach ($item_categories as $item_category_id => $primary_found) {
+ if ( $primary_found ) {
+ break;
+ }
}
}
- if ($primary_found && ($item_category_id == $category_id) && !$is_primary) {
+ if ( $primary_found && ($item_category_id == $category_id) && !$is_primary ) {
// want to make primary category as non-primary :(
- return true;
+ return;
}
- else if (!$primary_found) {
+ elseif ( !$primary_found ) {
$is_primary = true;
}
- if ($is_primary && $item_categories) {
+ if ( $is_primary && $item_categories ) {
// reset primary mark from all other categories
- $sql = 'UPDATE '.$table.' SET PrimaryCat = 0 WHERE '.$key_clause;
+ $sql = 'UPDATE ' . $table . '
+ SET PrimaryCat = 0
+ WHERE ' . $key_clause;
$this->Conn->Query($sql);
}
// UPDATE & INSERT instead of REPLACE because CategoryItems table has no primary key defined in database
- if (isset($item_categories[$category_id])) {
- $sql = 'UPDATE '.$table.' SET PrimaryCat = '.($is_primary ? 1 : 0).' WHERE '.$key_clause.' AND (CategoryId = '.$category_id.')';
+ if ( isset($item_categories[$category_id]) ) {
+ $sql = 'UPDATE ' . $table . '
+ SET PrimaryCat = ' . ($is_primary ? 1 : 0) . '
+ WHERE ' . $key_clause . ' AND (CategoryId = ' . $category_id . ')';
$this->Conn->Query($sql);
}
else {
$fields_hash = Array(
'CategoryId' => $category_id,
'ItemResourceId' => $this->GetField('ResourceId'),
'PrimaryCat' => $is_primary ? 1 : 0,
'ItemPrefix' => $this->Prefix,
'Filename' => $this->useFilenames ? (string)$this->GetDBField('Filename') : '', // because some prefixes does not use filenames,
);
+
$this->Conn->doInsert($fields_hash, $table);
}
+
// to ensure filename update after adding to another category
// this is critical since there may be an item with same filename in newly added category!
$this->Update();
}
/**
* Removes item from category specified
*
* @param int $category_id
*/
function removeFromCategory($category_id)
{
$sql = 'DELETE FROM '.TABLE_PREFIX.'CategoryItems WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
$this->Conn->Query( sprintf($sql, $category_id, $this->GetDBField('ResourceId')) );
}
/**
* Returns list of columns, that could exist in imported file
*
* @return Array
*/
function getPossibleExportColumns()
{
static $columns = null;
if (!is_array($columns)) {
$columns = array_merge($this->Fields['AvailableColumns']['options'], $this->Fields['ExportColumns']['options']);
}
return $columns;
}
/**
* Returns item's primary image data
*
* @return Array
*/
function getPrimaryImageData()
{
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'Images
WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (DefaultImg = 1)';
$image_data = $this->Conn->GetRow($sql);
if (!$image_data) {
// 2. no primary image, then get image with name "main"
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'Images
WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (Name = "main")';
$image_data = $this->Conn->GetRow($sql);
}
return $image_data;
}
function ChangeStatus($new_status, $pending_editing = false)
{
$status_field = array_shift( $this->Application->getUnitOption($this->Prefix,'StatusField') );
if ($new_status != $this->GetDBField($status_field)) {
// status was changed
$this->sendEmailEvents($new_status, $pending_editing);
}
$this->SetDBField($status_field, $new_status);
return $this->Update();
}
function sendEmailEvents($new_status, $pending_editing = false)
{
$owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
if (!$owner_field) {
$owner_field = 'CreatedById';
}
$event_name = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix');
if ($pending_editing) {
$event_name .= '.MODIFY';
}
$event_name .= $new_status == STATUS_ACTIVE ? '.APPROVE' : '.DENY';
$this->Application->EmailEventUser($event_name, $this->GetDBField($owner_field));
}
/**
* Approves changes made to category item
*
* @return bool
*/
function ApproveChanges()
{
$original_id = $this->GetDBField('OrgId');
- if (!($this->usePendingEditing && $original_id)) {
+ if ( !($this->usePendingEditing && $original_id) ) {
// non-pending copy of original link
return $this->ChangeStatus(STATUS_ACTIVE);
}
- if ($this->raiseEvent('OnBeforeDeleteOriginal', null, Array('original_id' => $original_id))) {
+ if ( $this->raiseEvent('OnBeforeDeleteOriginal', null, Array ('original_id' => $original_id)) ) {
// delete original item, because changes made in pending copy (this item) got to be approved in this method
- $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($original_id));
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, Array ($original_id));
$this->SetDBField('OrgId', 0);
return $this->ChangeStatus(STATUS_ACTIVE, true);
}
return false;
}
/**
* Decline changes made to category item
*
* @return bool
*/
function DeclineChanges()
{
$original_id = $this->GetDBField('OrgId');
- if (!($this->usePendingEditing && $original_id)) {
+ if ( !($this->usePendingEditing && $original_id) ) {
// non-pending copy of original link
return $this->ChangeStatus(STATUS_DISABLED);
}
// delete this item, because changes made in pending copy (this item) will be declined in this method
- $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($this->GetID()));
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, Array ($this->GetID()));
$this->sendEmailEvents(STATUS_DISABLED, true);
// original item is not changed here, because it is already enabled (thrus pending copy is visible to item's owner or admin with permission)
return true;
}
function RegisterHit()
{
$already_viewed = $this->Application->RecallVar($this->getPrefixSpecial().'_already_viewed');
$already_viewed = $already_viewed ? unserialize($already_viewed) : Array ();
$id = $this->GetID();
if (!in_array($id, $already_viewed)) {
$property_map = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
if (!$property_map) {
return ;
}
$hits_field = $property_map['ClickField'];
$new_hits = $this->GetDBField($hits_field) + 1;
$sql = 'SELECT MAX('.$hits_field.')
FROM '.$this->TableName.'
WHERE FLOOR('.$hits_field.') = '.$new_hits;
$max_hits = $this->Conn->GetOne($sql);
if ($max_hits) {
$new_hits = $max_hits + 0.000001;
}
$fields_hash = Array (
$hits_field => $new_hits,
);
$this->Conn->doUpdate($fields_hash, $this->TableName, $this->IDField.' = '.$id);
array_push($already_viewed, $id);
$this->Application->StoreVar($this->getPrefixSpecial().'_already_viewed', serialize($already_viewed));
}
}
/**
- * Returns part of SQL WHERE clause identifing the record, ex. id = 25
- *
- * @access public
- * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
- * @param Array $keys_hash alternative, then item id, keys hash to load item by
- * @return void
- * @see kDBItem::Load()
- * @see kDBItem::Update()
- * @see kDBItem::Delete()
- */
- function GetKeyClause($method = null, $keys_hash = null)
+ * Returns part of SQL WHERE clause identifying the record, ex. id = 25
+ *
+ * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
+ * @param Array $keys_hash alternative, then item id, keys hash to load item by
+ * @see kDBItem::Load()
+ * @see kDBItem::Update()
+ * @see kDBItem::Delete()
+ * @return string
+ * @access protected
+ */
+ protected function GetKeyClause($method = null, $keys_hash = null)
{
if ($method == 'load') {
// for item with many categories makes primary to load
$ci_table = TABLE_PREFIX . 'CategoryItems';
if ($this->IsTempTable()) {
$ci_table = $this->Application->GetTempName($ci_table, 'prefix:' . $this->Prefix);
}
$primary_category_clause = Array ('`' . $ci_table . '`.`PrimaryCat`' => 1);
if (!isset($keys_hash)) {
$keys_hash = Array ($this->IDField => $this->ID);
}
// merge primary category clause in any case to be sure, that
// CategoryId field will always contain primary category of item
$keys_hash = array_merge($keys_hash, $primary_category_clause);
}
return parent::GetKeyClause($method, $keys_hash);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/db/db_tag_processor.php
===================================================================
--- branches/5.2.x/core/kernel/db/db_tag_processor.php (revision 14595)
+++ branches/5.2.x/core/kernel/db/db_tag_processor.php (revision 14596)
@@ -1,2769 +1,2887 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 kDBTagProcessor extends kTagProcessor {
/**
* Returns true if "new" button was pressed in toolbar
*
* @param Array $params
* @return bool
*/
function IsNewMode($params)
{
$object =& $this->getObject($params);
return $object->GetID() <= 0;
}
/**
* Returns view menu name for current prefix
*
* @param Array $params
* @return string
*/
function GetItemName($params)
{
$item_name = $this->Application->getUnitOption($this->Prefix, 'ViewMenuPhrase');
return $this->Application->Phrase($item_name);
}
function ViewMenu($params)
{
$block_params = $params;
unset($block_params['block']);
$block_params['name'] = $params['block'];
$list =& $this->GetList($params);
$block_params['PrefixSpecial'] = $list->getPrefixSpecial();
return $this->Application->ParseBlock($block_params);
}
function SearchKeyword($params)
{
$list =& $this->GetList($params);
return $this->Application->RecallVar($list->getPrefixSpecial() . '_search_keyword');
}
/**
* Draw filter menu content (for ViewMenu) based on filters defined in config
*
* @param Array $params
* @return string
*/
function DrawFilterMenu($params)
{
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['spearator_block'];
$separator = $this->Application->ParseBlock($block_params);
$filter_menu = $this->Application->getUnitOption($this->Prefix,'FilterMenu');
if (!$filter_menu) {
trigger_error('<span class="debug_error">no filters defined</span> for prefix <b>'.$this->Prefix.'</b>, but <b>DrawFilterMenu</b> tag used', E_USER_NOTICE);
return '';
}
// Params: label, filter_action, filter_status
$block_params['name'] = $params['item_block'];
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter');
if ($view_filter === false) {
$event_params = Array ('prefix' => $this->Prefix, 'special' => $this->Special, 'name' => 'OnRemoveFilters');
$this->Application->HandleEvent( new kEvent($event_params) );
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter');
}
$view_filter = unserialize($view_filter);
$filters = Array();
$prefix_special = $this->getPrefixSpecial();
foreach ($filter_menu['Filters'] as $filter_key => $filter_params) {
$group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][ $filter_params['group_id'] ] : Array();
if (!isset($group_params['element_type'])) {
$group_params['element_type'] = 'checkbox';
}
if (!$filter_params) {
$filters[] = $separator;
continue;
}
$block_params['label'] = addslashes( $this->Application->Phrase($filter_params['label']) );
if (getArrayValue($view_filter,$filter_key)) {
$submit = 0;
if (isset($params['old_style'])) {
$status = $group_params['element_type'] == 'checkbox' ? 1 : 2;
}
else {
$status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']';
}
}
else {
$submit = 1;
$status = 'null';
}
$block_params['filter_action'] = 'set_filter("'.$prefix_special.'","'.$filter_key.'","'.$submit.'",'.$params['ajax'].');';
$block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image
$filters[] = $this->Application->ParseBlock($block_params);
}
return implode('', $filters);
}
/**
* Draws auto-refresh submenu in View Menu.
*
* @param Array $params
* @return string
*/
function DrawAutoRefreshMenu($params)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
if (!$refresh_intervals) {
trigger_error('<span class="debug_error">no refresh intervals defined</span> for prefix <strong>'.$this->Prefix.'</strong>, but <strong>DrawAutoRefreshMenu</strong> tag used', E_USER_NOTICE);
return '';
}
$refresh_intervals = explode(',', $refresh_intervals);
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
if ($current_refresh_interval === false) {
// if no interval was selected before, then choose 1st interval
$current_refresh_interval = $refresh_intervals[0];
}
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($refresh_intervals as $refresh_interval) {
$block_params['label'] = $this->_formatInterval($refresh_interval);
$block_params['refresh_interval'] = $refresh_interval;
$block_params['selected'] = $current_refresh_interval == $refresh_interval;
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Tells, that current grid is using auto refresh
*
* @param Array $params
* @return bool
*/
function UseAutoRefresh($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name);
}
/**
* Returns current grid refresh interval
*
* @param Array $params
* @return bool
*/
function AutoRefreshInterval($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
}
/**
* Formats time interval using given text for hours and minutes
*
* @param int $intervalmMinutes
* @param string $hour_text Text for hours
* @param string $min_text Text for minutes
* @return unknown
*/
function _formatInterval($interval, $hour_text = 'h', $min_text = 'min')
{
// 65
$minutes = $interval % 60;
$hours = ($interval - $minutes) / 60;
$ret = '';
if ($hours) {
$ret .= $hours.$hour_text.' ';
}
if ($minutes) {
$ret .= $minutes.$min_text;
}
return $ret;
}
function IterateGridFields($params)
{
$mode = $params['mode'];
$def_block = isset($params['block']) ? $params['block'] : '';
$force_block = isset($params['force_block']) ? $params['force_block'] : false;
$grids = $this->Application->getUnitOption($this->Prefix,'Grids');
$grid_config = $grids[$params['grid']]['Fields'];
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
$picker_helper->ApplyPicker($this->getPrefixSpecial(), $grid_config, $params['grid']);
if ($mode == 'fields') {
return "'".join("','", array_keys($grid_config))."'";
}
$object =& $this->GetList($params);
$o = '';
$i = 0;
foreach ($grid_config as $field => $options) {
$i++;
$block_params = $this->prepareTagParams($params);
$block_params = array_merge($block_params, $options);
$block_params['block_name'] = array_key_exists($mode . '_block', $block_params) ? $block_params[$mode . '_block'] : $def_block;
$block_params['name'] = $force_block ? $force_block : $block_params['block_name'];
$block_params['field'] = $field;
$block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field;
$block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field;
$w = $picker_helper->GetWidth($field);
if ($w) {
// column picker width overrides width from unit config
$block_params['width'] = $w;
}
$field_options = $object->GetFieldOptions($field);
if (array_key_exists('use_phrases', $field_options)) {
$block_params['use_phrases'] = $field_options['use_phrases'];
}
$block_params['is_last'] = ($i == count($grid_config));
$o.= $this->Application->ParseBlock($block_params, 1);
}
return $o;
}
function PickerCRC($params)
{
/* @var $picker_helper kColumnPickerHelper */
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
$picker_helper->SetGridName($params['grid']);
$data = $picker_helper->LoadColumns($this->getPrefixSpecial());
return $data['crc'];
}
function FreezerPosition($params)
{
/* @var $picker_helper kColumnPickerHelper */
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
$picker_helper->SetGridName($params['grid']);
$data = $picker_helper->LoadColumns($this->getPrefixSpecial());
$freezer_pos = array_search('__FREEZER__', $data['order']);
return $freezer_pos === false || in_array('__FREEZER__', $data['hidden_fields']) ? 1 : ++$freezer_pos;
}
function GridFieldsCount($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$grid_config = $grids[$params['grid']]['Fields'];
return count($grid_config);
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList($params)
{
$params['no_table'] = 1;
return $this->PrintList2($params);
}
function InitList($params)
{
$list_name = isset($params['list_name']) ? $params['list_name'] : '';
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping');
if( !getArrayValue($names_mapping, $this->Prefix, $list_name) )
{
$list =& $this->GetList($params);
}
}
function BuildListSpecial($params)
{
return $this->Special;
}
/**
* Returns key, that identifies each list on template (used internally, not tag)
*
* @param Array $params
* @return string
*/
function getUniqueListKey($params)
{
$types = array_key_exists('types', $params) ? $params['types'] : '';
$except = array_key_exists('except', $params) ? $params['except'] : '';
$list_name = array_key_exists('list_name', $params) ? $params['list_name'] : '';
if (!$list_name) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
return $types . $except . $list_name;
}
/**
* Enter description here...
*
* @param Array $params
* @return kDBList
*/
function &GetList($params)
{
$list_name = $this->SelectParam($params, 'list_name,name');
if (!$list_name) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
$requery = isset($params['requery']) && $params['requery'];
$main_list = array_key_exists('main_list', $params) && $params['main_list'];
if ($list_name && !$requery) {
// list with "list_name" parameter
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping', Array ());
if (!array_key_exists($this->Prefix, $names_mapping)) {
// create prefix-based array to special mapping storage
$names_mapping[$this->Prefix] = Array ();
}
if (!array_key_exists($list_name, $names_mapping[$this->Prefix])) {
// special missing -> generate one
$special = $main_list ? $this->Special : $this->BuildListSpecial($params);
}
else {
// get special, formed during list initialization
$special = $names_mapping[$this->Prefix][$list_name];
}
}
else {
// list without "list_name" parameter
$special = $main_list ? $this->Special : $this->BuildListSpecial($params);
}
$prefix_special = rtrim($this->Prefix.'.'.$special, '.');
$params['skip_counting'] = true;
$list =& $this->Application->recallObject( $prefix_special, $this->Prefix.'_List', $params);
/* @var $list kDBList */
if (!array_key_exists('skip_quering', $params) || !$params['skip_quering']) {
if ($requery) {
$this->Application->HandleEvent($an_event, $prefix_special.':OnListBuild', $params);
}
if (array_key_exists('offset', $params)) {
$list->SetOffset( $list->GetOffset() + $params['offset'] ); // apply custom offset
}
$list->Query($requery);
if (array_key_exists('offset', $params)) {
$list->SetOffset( $list->GetOffset() - $params['offset'] ); // remove custom offset
}
}
$this->Init($this->Prefix, $special);
if ($list_name) {
$names_mapping[$this->Prefix][$list_name] = $special;
$this->Application->SetVar('NamesToSpecialMapping', $names_mapping);
}
return $list;
}
function ListMarker($params)
{
$list =& $this->GetList($params);
$ret = $list->getPrefixSpecial();
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
return $ret;
}
function CombinedSortingDropDownName($params)
{
$list =& $this->GetList($params);
return $list->getPrefixSpecial() . '_CombinedSorting';
}
/**
* Prepares name for field with event in it (used only on front-end)
*
* @param Array $params
* @return string
*/
function SubmitName($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
return 'events[' . $prefix_special . '][' . $params['event'] . ']';
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList2($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
if ($per_page !== false) $params['per_page'] = $per_page;
$list =& $this->GetList($params);
$o = '';
$direction = (isset($params['direction']) && $params['direction']=="H")?"H":"V";
$columns = (isset($params['columns'])) ? $params['columns'] : 1;
$id_field = (isset($params['id_field'])) ? $params['id_field'] : $this->Application->getUnitOption($this->Prefix, 'IDField');
if ($columns > 1 && $direction == 'V') {
$records_left = array_splice($list->Records, $list->GetSelectedCount()); // because we have 1 more record for "More..." link detection (don't need to sort it)
$list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage());
$list->Records = array_merge($list->Records, $records_left);
}
$list->GoFirst();
$block_params=$this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
$block_params['column_width'] = $params['column_width'] = 100 / $columns;
$block_start_row_params = $this->prepareTagParams($params);
$block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block');
$block_end_row_params=$this->prepareTagParams($params);
$block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block');
$block_empty_cell_params = $this->prepareTagParams($params);
$block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block');
$i=0;
$backup_id=$this->Application->GetVar($this->Prefix."_id");
$displayed = array();
$column_number = 1;
$cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') &&
$this->Application->RewriteURLs() && !$this->Application->isCachingType(CACHING_TYPE_MEMORY);
$limit = isset($params['limit']) ? $params['limit'] : false;
while (!$list->EOL() && (!$limit || $i<$limit)) {
$this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
$this->Application->SetVar( $this->Prefix.'_id', $list->GetDBField($id_field) );
$block_params['is_last'] = ($i == $list->GetSelectedCount() - 1);
$block_params['last_row'] = ($i + (($i+1) % $columns) >= $list->GetSelectedCount() - 1);
$block_params['not_last'] = !$block_params['is_last']; // for front-end
if ($cache_mod_rw) {
$serial_name = $this->Application->incrementCacheSerial($this->Prefix, $list->GetDBField($id_field), false);
if ($this->Prefix == 'c') {
// for listing subcategories in category
$this->Application->setCache('filenames[%' . $serial_name . '%]' , $list->GetDBField('NamedParentPath'));
$this->Application->setCache('category_tree[%CIDSerial:' . $list->GetDBField($id_field) . '%]', $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight'));
} else {
// for listing items in category
$this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('Filename'));
$serial_name = $this->Application->incrementCacheSerial('c', $list->GetDBField('CategoryId'), false);
$this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('CategoryFilename'));
}
}
if ($i % $columns == 0) {
// record in this iteration is first in row, then open row
$column_number = 1;
$o.= $block_start_row_params['name'] ?
$this->Application->ParseBlock($block_start_row_params) :
(!isset($params['no_table']) ? '<tr>' : '');
}
else {
$column_number++;
}
$block_params['first_col'] = $column_number == 1 ? 1 : 0;
$block_params['last_col'] = $column_number == $columns ? 1 : 0;
$block_params['column_number'] = $column_number;
$block_params['num'] = ($i+1);
$this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList
$o.= $this->Application->ParseBlock($block_params);
array_push($displayed, $list->GetDBField($id_field));
if($direction == 'V' && $list->GetSelectedCount() % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->GetSelectedCount() % ceil($list->GetSelectedCount() / $columns)) {
// if vertical output, then draw empty cells vertically, not horizontally
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : '<td>&nbsp;</td>';
$i++;
}
if (($i + 1) % $columns == 0) {
// record in next iteration is first in row too, then close this row
$o.= $block_end_row_params['name'] ?
$this->Application->ParseBlock($block_end_row_params) :
(!isset($params['no_table']) ? '</tr>' : '');
}
$list->GoNext();
$i++;
}
// append empty cells in place of missing cells in last row
while ($i % $columns != 0) {
// until next cell will be in new row append empty cells
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : '<td>&nbsp;</td>';
if (($i+1) % $columns == 0) {
// record in next iteration is first in row too, then close this row
$o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params) : '</tr>';
}
$i++;
}
$cur_displayed = $this->Application->GetVar($this->Prefix.'_displayed_ids');
if (!$cur_displayed) {
$cur_displayed = Array();
}
else {
$cur_displayed = explode(',', $cur_displayed);
}
$displayed = array_unique(array_merge($displayed, $cur_displayed));
$this->Application->SetVar($this->Prefix.'_displayed_ids', implode(',',$displayed));
$this->Application->SetVar( $this->Prefix.'_id', $backup_id);
$this->Application->SetVar( $this->getPrefixSpecial().'_id', '');
if (isset($params['more_link_render_as'])) {
$block_params = $params;
$params['render_as'] = $params['more_link_render_as'];
$o .= $this->MoreLink($params);
}
return $o;
}
/**
* Allows to modify block params & current list record before PrintList parses record
*
* @param kDBList $object
* @param Array $block_params
+ * @return void
+ * @access protected
*/
- function PrepareListElementParams(&$object, &$block_params)
+ protected function PrepareListElementParams(&$object, &$block_params)
{
// $fields_hash =& $object->getCurrentRecord();
}
- function MoreLink($params)
+ /**
+ * Renders given block name, when there there is more data in list, then are displayed right now
+ *
+ * @param Array $params
+ * @return string
+ * @access protected
+ */
+ protected function MoreLink($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
- if ($per_page !== false) {
+ if ( $per_page !== false ) {
$params['per_page'] = $per_page;
}
$list =& $this->GetList($params);
if ( $list->isCounted() ) {
$has_next_page = $list->GetPage() < $list->GetTotalPages();
}
else {
// selected more, then on the page -> has more
$has_next_page = $list->GetPerPage() < $list->GetRecordsCount();
}
- if ($has_next_page) {
- $block_params = Array (
- 'name' => $this->SelectParam($params, 'render_as,block'),
- );
+ if ( $has_next_page ) {
+ $block_params = Array ('name' => $this->SelectParam($params, 'render_as,block'));
return $this->Application->ParseBlock($block_params);
}
+
+ return '';
}
function PageLink($params)
{
static $default_per_page = Array ();
$object =& $this->GetList($params);
/* @var $object kDBList */
// process sorting
if ($object->isMainList()) {
if (!array_key_exists('sort_by', $params)) {
$sort_by = $this->Application->GetVar('sort_by');
if ($sort_by !== false) {
$params['sort_by'] = $sort_by;
}
}
}
$prefix_special = $this->getPrefixSpecial();
// process page
$page = array_key_exists('page', $params) ? $params['page'] : $this->Application->GetVar($prefix_special . '_Page');
if (!$page) {
// ensure, that page is always present
if ($object->isMainList()) {
$params[$prefix_special . '_Page'] = $this->Application->GetVar('page', 1);
}
else {
$params[$prefix_special . '_Page'] = 1;
}
}
if (array_key_exists('page', $params)) {
$params[$prefix_special . '_Page'] = $params['page'];
unset($params['page']);
}
// process per-page
$per_page = array_key_exists('per_page', $params) ? $params['per_page'] : $this->Application->GetVar($prefix_special . '_PerPage');
if (!$per_page) {
// ensure, that per-page is always present
list ($prefix, ) = explode('.', $prefix_special);
if (!array_key_exists($prefix, $default_per_page)) {
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$default_per_page[$prefix] = $list_helper->getDefaultPerPage($prefix);
}
if ($object->isMainList()) {
$params[$prefix_special . '_PerPage'] = $this->Application->GetVar('per_page', $default_per_page[$prefix]);
}
else {
$params[$prefix_special . '_PerPage'] = $default_per_page[$prefix];
}
}
if (array_key_exists('per_page', $params)) {
$params[$prefix_special . '_PerPage'] = $params['per_page'];
unset($params['per_page']);
}
if (!array_key_exists('pass', $params)) {
$params['pass'] = 'm,' . $prefix_special;
}
// process template
$t = array_key_exists('template', $params) ? $params['template'] : '';
unset($params['template']);
if (!$t) {
$t = $this->Application->GetVar('t');
}
return $this->Application->HREF($t, '', $params);
}
/**
* Depricated
*
* @param array $params
* @return int
* @deprecated Parameter "column_width" of "PrintList" tag does that
*/
function ColumnWidth($params)
{
$columns = $this->Application->Parser->GetParam('columns');
return round(100/$columns).'%';
}
/**
* Append prefix and special to tag
* params (get them from tagname) like
* they were really passed as params
*
* @param Array $tag_params
* @return Array
* @access protected
*/
function prepareTagParams($tag_params = Array())
{
$ret = $tag_params;
$ret['Prefix'] = $this->Prefix;
$ret['Special'] = $this->Special;
$ret['PrefixSpecial'] = $this->getPrefixSpecial();
return $ret;
}
function GetISO($currency)
{
if ($currency == 'selected') {
$iso = $this->Application->RecallVar('curr_iso');
}
elseif ($currency == 'primary' || $currency == '') {
$iso = $this->Application->GetPrimaryCurrency();
}
else { //explicit currency
$iso = $currency;
}
return $iso;
}
+ /**
+ * Convert primary currency to selected (if they are the same, converter will just return)
+ *
+ * @param float $value
+ * @param string $iso
+ * @return float
+ */
function ConvertCurrency($value, $iso)
{
$converter =& $this->Application->recallObject('kCurrencyRates');
- // convery primary currency to selected (if they are the same, converter will just return)
- $value = $converter->Convert($value, 'PRIMARY', $iso);
- return $value;
+ /* @var $converter kCurrencyRates */
+
+ return $converter->Convert($value, 'PRIMARY', $iso);
}
function AddCurrencySymbol($value, $iso)
{
$cache_key = 'iso_masks[%CurrSerial%]';
$iso_masks = $this->Application->getCache($cache_key);
if ($iso_masks === false) {
$this->Conn->nextQueryCachable = true;
$symbol_sql = 'IF(COALESCE(Symbol, "") = "", CONCAT(ISO, "&nbsp;"), Symbol)';
$sql = 'SELECT IF(SymbolPosition = 0, CONCAT(' . $symbol_sql . ', "%s"), CONCAT("%s", ' . $symbol_sql . ')), LOWER(ISO) AS ISO
FROM ' . $this->Application->getUnitOption('curr', 'TableName') . '
WHERE Status = ' . STATUS_ACTIVE;
$iso_masks = $this->Conn->GetCol($sql, 'ISO');
$this->Application->setCache($cache_key, $iso_masks);
}
$iso = strtolower($iso);
return array_key_exists($iso, $iso_masks) ? sprintf($iso_masks[$iso], $value) : $value;
}
/**
* Get's requested field value
*
* @param Array $params
* @return string
* @access public
*/
function Field($params)
{
$field = $this->SelectParam($params, 'name,field');
if (!$this->Application->isAdmin) {
// apply htmlspecialchars on all field values on Front-End
$params['no_special'] = 'no_special';
}
$object =& $this->getObject($params);
/* @var $object kDBItem */
if (array_key_exists('db', $params) && $params['db']) {
$value = $object->GetDBField($field);
}
else {
if (array_key_exists('currency', $params) && $params['currency']) {
$iso = $this->GetISO($params['currency']);
$original = $object->GetDBField($field);
$value = $this->ConvertCurrency($original, $iso);
$object->SetDBField($field, $value);
$object->SetFieldOption($field, 'converted', true);
}
$format = array_key_exists('format', $params) ? $params['format'] : false;
if (!$format || $format == '$format') {
$format = null;
}
$value = $object->GetField($field, $format);
if (array_key_exists('negative', $params) && $params['negative']) {
if (strpos($value, '-') === 0) {
$value = substr($value, 1);
}
else {
$value = '-' . $value;
}
}
if (array_key_exists('currency', $params) && $params['currency']) {
$value = $this->AddCurrencySymbol($value, $iso);
$params['no_special'] = 1;
}
}
if (!array_key_exists('no_special', $params) || !$params['no_special']) {
// when no_special parameter NOT SET apply htmlspecialchars
$value = htmlspecialchars($value);
}
if (array_key_exists('checked', $params) && $params['checked']) {
$value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : '';
}
if (array_key_exists('plus_or_as_label', $params) && $params['plus_or_as_label']) {
$value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value);
}
elseif (array_key_exists('as_label', $params) && $params['as_label']) {
$value = $this->Application->Phrase($value);
}
$first_chars = $this->SelectParam($params,'first_chars,cut_first');
if ($first_chars) {
$stripped_value = strip_tags($value, $this->SelectParam($params, 'allowed_tags'));
if ( mb_strlen($stripped_value) > $first_chars ) {
$value = preg_replace('/\s+?(\S+)?$/', '', mb_substr($stripped_value, 0, $first_chars + 1)) . ' ...';
}
}
if (array_key_exists('nl2br', $params) && $params['nl2br']) {
$value = nl2br($value);
}
if ($value != '') {
$this->Application->Parser->DataExists = true;
}
if (array_key_exists('currency', $params) && $params['currency']) {
// restoring value in original currency, for other Field tags to work properly
$object->SetDBField($field, $original);
}
return $value;
}
function FieldHintLabel($params)
{
if ( isset($params['direct_label']) && $params['direct_label'] ) {
$label = $params['direct_label'];
$hint = $this->Application->Phrase($label, false);
}
else {
$label = $params['title_label'];
$hint = $this->Application->Phrase('hint:' . $label, false);
}
return $hint; // $hint != strtoupper('!' . $label . '!') ? $hint : '';
}
/**
* Returns formatted date + time on current language
*
* @param $params
*/
function DateField($params)
{
$field = $this->SelectParam($params, 'name,field');
if ($field) {
$object =& $this->getObject($params);
/* @var $object kDBItem */
$timestamp = $object->GetDBField($field);
}
else {
$timestamp = $params['value'];
}
$date = $timestamp;
// prepare phrase replacements
$replacements = Array (
'l' => 'la_WeekDay',
'D' => 'la_WeekDay',
'M' => 'la_Month',
'F' => 'la_Month',
);
// cases allow to append phrase suffix based on requested case (e.g. Genitive)
$case_suffixes = array_key_exists('case_suffixes', $params) ? $params['case_suffixes'] : false;
if ($case_suffixes) {
// apply case suffixes (for russian language only)
$case_suffixes = explode(',', $case_suffixes);
foreach ($case_suffixes as $case_suffux) {
list ($replacement_name, $case_suffix_value) = explode('=', $case_suffux, 2);
$replacements[$replacement_name] .= $case_suffix_value;
}
}
$format = array_key_exists('format', $params) ? $params['format'] : false;
if (preg_match('/_regional_(.*)/', $format, $regs)) {
$language =& $this->Application->recallObject('lang.current');
/* @var $language kDBItem */
$format = $language->GetDBField($regs[1]);
}
elseif (!$format) {
$format = null;
}
// escape formats, that are resolved to words by adodb_date
foreach ($replacements as $format_char => $phrase_prefix) {
if (strpos($format, $format_char) === false) {
unset($replacements[$format_char]);
continue;
}
$replacements[$format_char] = $this->Application->Phrase($phrase_prefix . adodb_date($format_char, $date));
$format = str_replace($format_char, '#' . ord($format_char) . '#', $format);
}
$date_formatted = adodb_date($format, $date);
// unescape formats, that are resolved to words by adodb_date
foreach ($replacements as $format_char => $format_replacement) {
$date_formatted = str_replace('#' . ord($format_char) . '#', $format_replacement, $date_formatted);
}
return $date_formatted;
}
function SetField($params)
{
// <inp2:SetField field="Value" src=p:cust_{$custom_name}"/>
$object =& $this->getObject($params);
- $dst_field = $this->SelectParam($params, 'name,field');
+ /* @var $object kDBItem */
+ $dst_field = $this->SelectParam($params, 'name,field');
list($prefix_special, $src_field) = explode(':', $params['src']);
+
$src_object =& $this->Application->recallObject($prefix_special);
+ /* @var $src_object kDBItem */
+
$object->SetDBField($dst_field, $src_object->GetDBField($src_field));
}
/**
* Depricated
*
* @param Array $params
* @return string
* @deprecated parameter "as_label" of "Field" tag does the same
*/
function PhraseField($params)
{
$field_label = $this->Field($params);
$translation = $this->Application->Phrase( $field_label );
return $translation;
}
function Error($params)
{
- $field = $this->SelectParam($params, 'name,field');
$object =& $this->getObject($params);
- $msg = $object->GetErrorMsg($field, false);
- return $msg;
+ /* @var $object kDBItem */
+
+ $field = $this->SelectParam($params, 'name,field');
+
+ return $object->GetErrorMsg($field, false);
}
function HasError($params)
{
- if ($params['field'] == 'any')
- {
+ if ($params['field'] == 'any') {
$object =& $this->getObject($params);
+ /* @var $object kDBItem */
$skip_fields = array_key_exists('except', $params) ? $params['except'] : false;
$skip_fields = $skip_fields ? explode(',', $skip_fields) : Array();
return $object->HasErrors($skip_fields);
}
- else
- {
- $fields = $this->SelectParam($params, 'field,fields');
- $fields = explode(',', $fields);
+ else {
$res = false;
- foreach($fields as $field)
- {
+ $fields = explode(',', $this->SelectParam($params, 'field,fields'));
+
+ foreach ($fields as $field) {
+ // call kDBTagProcessor::Error instead of kDBItem::GetErrorPseudo to have ability to override Error tag
$params['field'] = $field;
$res = $res || ($this->Error($params) != '');
}
+
return $res;
}
}
- function ErrorWarning($params)
+ /**
+ * Renders error message block, when there are errors on a form
+ *
+ * @param Array $params
+ * @return string
+ * @access protected
+ */
+ protected function ErrorWarning($params)
{
- if (!isset($params['field'])) {
+ if ( !isset($params['field']) ) {
$params['field'] = 'any';
}
- if ($this->HasError($params)) {
+
+ if ( $this->HasError($params) ) {
$params['prefix'] = $this->getPrefixSpecial();
+
return $this->Application->ParseBlock($params);
}
+
+ return '';
}
function IsRequired($params)
{
- $field = $params['field'];
$object =& $this->getObject($params);
+ /* @var $object kDBItem */
+ $field = $params['field'];
$formatter_class = $object->GetFieldOption($field, 'formatter');
- if ($formatter_class == 'kMultiLanguage')
- {
+
+ if ( $formatter_class == 'kMultiLanguage' ) {
$formatter =& $this->Application->recallObject($formatter_class);
+ /* @var $formatter kMultiLanguage */
+
$field = $formatter->LangFieldName($field);
}
- return $object->GetFieldOption($field, 'required');
+ return $object->isRequired($field);
}
function FieldOption($params)
{
$object =& $this->getObject($params);;
$options = $object->GetFieldOptions($params['field']);
$ret = isset($options[$params['option']]) ? $options[$params['option']] : '';
if (isset($params['as_label']) && $params['as_label']) $ret = $this->Application->ReplaceLanguageTags($ret);
return $ret;
}
- function PredefinedOptions($params)
+ /**
+ * Prints list a all possible field options
+ *
+ * @param Array $params
+ * @return string
+ * @access protected
+ */
+ protected function PredefinedOptions($params)
{
$object =& $this->getObject($params);
-
+ /* @var $object kDBList */
+
$field = $params['field'];
$value = array_key_exists('value', $params) ? $params['value'] : $object->GetDBField($field);
$field_options = $object->GetFieldOptions($field);
if (!array_key_exists('options', $field_options) || !is_array($field_options['options'])) {
trigger_error('Options not defined for <strong>'.$object->Prefix.'</strong> field <strong>'.$field.'</strong>', E_USER_WARNING);
return '';
}
$options = $field_options['options'];
if (array_key_exists('has_empty', $params) && $params['has_empty']) {
$empty_value = array_key_exists('empty_value', $params) ? $params['empty_value'] : '';
$options = kUtil::array_merge_recursive(Array ($empty_value => ''), $options); // don't use other array merge function, because they will reset keys !!!
}
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
if (method_exists($object, 'EOL') && count($object->Records) == 0) {
// for drawing grid column filter
$block_params['field_name'] = '';
}
else {
$block_params['field_name'] = $this->InputName($params); // depricated (produces warning when used as grid filter), but used in Front-End (submission create), admin (submission view)
}
$selected_param_name = array_key_exists('selected_param', $params) ? $params['selected_param'] : false;
if (!$selected_param_name) {
$selected_param_name = $params['selected'];
}
$selected = $params['selected'];
$o = '';
if (array_key_exists('no_empty', $params) && $params['no_empty'] && !getArrayValue($options, '')) {
// removes empty option, when present (needed?)
array_shift($options);
}
$index = 0;
$option_count = count($options);
if (strpos($value, '|') !== false) {
// multiple checkboxes OR multiselect
$value = explode('|', substr($value, 1, -1) );
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : '');
$block_params['is_last'] = $index == $option_count - 1;
$o .= $this->Application->ParseBlock($block_params);
$index++;
}
}
else {
// single selection radio OR checkboxes OR dropdown
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : '');
$block_params['is_last'] = $index == $option_count - 1;
$o .= $this->Application->ParseBlock($block_params);
$index++;
}
}
return $o;
}
function PredefinedSearchOptions($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$params['value'] = $this->SearchField($params);
return $this->PredefinedOptions($params);
}
function Format($params)
{
$field = $this->SelectParam($params, 'name,field');
$object =& $this->getObject($params);
$options = $object->GetFieldOptions($field);
-
- $format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ];
-
+ $format = $options[$this->SelectParam($params, 'input_format') ? 'input_format' : 'format'];
$formatter_class = array_key_exists('formatter', $options) ? $options['formatter'] : false;
- if ($formatter_class) {
+ if ( $formatter_class ) {
$formatter =& $this->Application->recallObject($formatter_class);
+ /* @var $formatter kFormatter */
+
$human_format = array_key_exists('human', $params) ? $params['human'] : false;
$edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false;
$sample = array_key_exists('sample', $params) ? $params['sample'] : false;
- if ($sample) {
+
+ if ( $sample ) {
return $formatter->GetSample($field, $options, $object);
}
- elseif ($human_format || $edit_size) {
+ elseif ( $human_format || $edit_size ) {
$format = $formatter->HumanFormat($format);
+
return $edit_size ? strlen($format) : $format;
}
}
return $format;
}
/**
* Returns grid padination information
* Can return links to pages
*
* @param Array $params
* @return mixed
*/
function PageInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$type = $params['type'];
unset($params['type']); // remove parameters used only by current tag
$ret = '';
switch ($type) {
case 'current':
$ret = $object->GetPage();
break;
case 'total':
$ret = $object->GetTotalPages();
break;
case 'prev':
$ret = $object->GetPage() > 1 ? $object->GetPage() - 1 : false;
break;
case 'next':
$ret = $object->GetPage() < $object->GetTotalPages() ? $object->GetPage() + 1 : false;
break;
}
if ($ret && isset($params['as_link']) && $params['as_link']) {
unset($params['as_link']); // remove parameters used only by current tag
$params['page'] = $ret;
$current_page = $object->GetPage(); // backup current page
$ret = $this->PageLink($params);
$this->Application->SetVar($object->getPrefixSpecial().'_Page', $current_page); // restore page
}
return $ret;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintPages($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
$total_pages = $list->GetTotalPages();
if ($total_pages > 1) $this->Application->Parser->DataExists = true;
if($total_pages == 0) $total_pages = 1; // display 1st page as selected in case if we have no pages at all
$o = '';
// what are these 2 lines for?
$this->Application->SetVar($prefix_special.'_event','');
$this->Application->SetVar($prefix_special.'_id','');
$current_page = $list->GetPage(); // $this->Application->RecallVar($prefix_special.'_Page');
$block_params = $this->prepareTagParams($params);
$split = ( isset($params['split'] ) ? $params['split'] : 10 );
$split_start = $current_page - ceil($split/2);
if ($split_start < 1){
$split_start = 1;
}
$split_end = $split_start + $split-1;
if ($split_end > $total_pages) {
$split_end = $total_pages;
$split_start = max($split_end - $split + 1, 1);
}
if ($current_page > 1){
$prev_block_params = $this->prepareTagParams($params);
if ($total_pages > $split){
$prev_block_params['page'] = max($current_page-$split, 1);
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_split_render_as,prev_page_split_block');
if ($prev_block_params['name']){
$o .= $this->Application->ParseBlock($prev_block_params);
}
}
$prev_block_params['name'] = 'page';
$prev_block_params['page'] = $current_page-1;
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_render_as,block_prev_page,prev_page_block');
if ($prev_block_params['name']) {
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page-1);
$o .= $this->Application->ParseBlock($prev_block_params);
}
}
else {
if ( $no_prev_page_block = $this->SelectParam($params, 'no_prev_page_render_as,block_no_prev_page') ) {
$block_params['name'] = $no_prev_page_block;
$o .= $this->Application->ParseBlock($block_params);
}
}
$separator_params['name'] = $this->SelectParam($params, 'separator_render_as,block_separator');
for ($i = $split_start; $i <= $split_end; $i++)
{
if ($i == $current_page) {
$block = $this->SelectParam($params, 'current_render_as,active_render_as,block_current,active_block');
}
else {
$block = $this->SelectParam($params, 'link_render_as,inactive_render_as,block_link,inactive_block');
}
$block_params['name'] = $block;
$block_params['page'] = $i;
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $i);
$o .= $this->Application->ParseBlock($block_params);
if ($this->SelectParam($params, 'separator_render_as,block_separator')
&& $i < $split_end)
{
$o .= $this->Application->ParseBlock($separator_params);
}
}
if ($current_page < $total_pages){
$next_block_params = $this->prepareTagParams($params);
$next_block_params['page']=$current_page+1;
$next_block_params['name'] = $this->SelectParam($params, 'next_page_render_as,block_next_page,next_page_block');
if ($next_block_params['name']){
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page+1);
$o .= $this->Application->ParseBlock($next_block_params);
}
if ($total_pages > $split){
$next_block_params['page']=min($current_page+$split, $total_pages);
$next_block_params['name'] = $this->SelectParam($params, 'next_page_split_render_as,next_page_split_block');
if ($next_block_params['name']){
$o .= $this->Application->ParseBlock($next_block_params);
}
}
}
else {
if ( $no_next_page_block = $this->SelectParam($params, 'no_next_page_render_as,block_no_next_page') ) {
$block_params['name'] = $no_next_page_block;
$o .= $this->Application->ParseBlock($block_params);
}
}
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page);
return $o;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PaginationBar($params)
{
return $this->PrintPages($params);
}
function PerPageBar($params)
{
$object =& $this->GetList($params);
$ret = '';
$per_pages = explode(';', $params['per_pages']);
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($per_pages as $per_page) {
$block_params['per_page'] = $per_page;
$this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $per_page);
$block_params['selected'] = $per_page == $object->GetPerPage();
$ret .= $this->Application->ParseBlock($block_params, 1);
}
$this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $object->GetPerPage());
return $ret;
}
/**
* Returns field name (processed by kMultiLanguage formatter
* if required) and item's id from it's IDField or field required
*
* @param Array $params
* @return Array (id,field)
* @access private
*/
function prepareInputName($params)
{
$object =& $this->getObject($params);
/* @var $object kDBItem */
-
+
$field = $this->SelectParam($params, 'name,field');
$formatter_class = $object->GetFieldOption($field, 'formatter');
if ($formatter_class == 'kMultiLanguage') {
$formatter =& $this->Application->recallObject($formatter_class);
/* @var $formatter kMultiLanguage */
$force_primary = $object->GetFieldOption($field, 'force_primary');
$field = $formatter->LangFieldName($field, $force_primary);
}
if (array_key_exists('force_id', $params)) {
$id = $params['force_id'];
}
else {
$id_field = array_key_exists('IdField', $params) ? $params['IdField'] : false;
$id = $id_field ? $object->GetDBField($id_field) : $object->GetID();
}
return Array($id, $field);
}
/**
* Returns input field name to
* be placed on form (for correct
* event processing)
*
* @param Array $params
* @return string
* @access public
*/
function InputName($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = $this->getPrefixSpecial().'['.$id.']['.$field.']';
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
return $ret;
}
/**
* Allows to override various field options through hidden fields with specific names in submit.
* This tag generates this special names
*
* @param Array $params
* @return string
* @author Alex
*/
function FieldModifier($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = 'field_modifiers['.$this->getPrefixSpecial().']['.$field.']['.$params['type'].']';
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
if (isset($params['value'])) {
$object =& $this->getObject($params);
$field_modifiers[$field][$params['type']] = $params['value'];
$object->ApplyFieldModifiers($field_modifiers);
}
return $ret;
}
/**
* Returns index where 1st changable sorting field begins
*
* @return int
* @access private
*/
function getUserSortIndex()
{
$list_sortings = $this->Application->getUnitOption($this->Prefix, 'ListSortings', Array ());
$sorting_prefix = getArrayValue($list_sortings, $this->Special) ? $this->Special : '';
$user_sorting_start = 0;
if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) {
$user_sorting_start = count($forced_sorting);
}
return $user_sorting_start;
}
/**
* Returns order direction for given field
*
*
*
* @param Array $params
* @return string
* @access public
*/
function Order($params)
{
$field = $params['field'];
$user_sorting_start = $this->getUserSortIndex();
$list =& $this->GetList($params);
if ($list->GetOrderField($user_sorting_start) == $field)
{
return strtolower($list->GetOrderDirection($user_sorting_start));
}
elseif($this->Application->ConfigValue('UseDoubleSorting') && $list->GetOrderField($user_sorting_start+1) == $field)
{
return '2_'.strtolower($list->GetOrderDirection($user_sorting_start+1));
}
else
{
return 'no';
}
}
/**
* Detects, that current sorting is not default
*
* @param Array $params
* @return bool
*/
function OrderChanged($params)
{
$list =& $this->GetList($params);
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
return $list_helper->hasUserSorting($list);
}
/**
- * Get's information of sorting field at "pos" position,
+ * Gets information of sorting field at "pos" position,
* like sorting field name (type="field") or sorting direction (type="direction")
*
* @param Array $params
- * @return mixed
+ * @return string
+ * @access protected
*/
- function OrderInfo($params)
+ protected function OrderInfo($params)
{
$user_sorting_start = $this->getUserSortIndex() + --$params['pos'];
$list =& $this->GetList($params);
- if($params['type'] == 'field') return $list->GetOrderField($user_sorting_start);
- if($params['type'] == 'direction') return $list->GetOrderDirection($user_sorting_start);
+ if ( $params['type'] == 'field' ) {
+ return $list->GetOrderField($user_sorting_start);
+ }
+
+ if ( $params['type'] == 'direction' ) {
+ return $list->GetOrderDirection($user_sorting_start);
+ }
+
+ return '';
}
/**
* Checks if sorting field/direction matches passed field/direction parameter
*
* @param Array $params
* @return bool
+ * @access protected
*/
- function IsOrder($params)
+ protected function IsOrder($params)
{
$params['type'] = isset($params['field']) ? 'field' : 'direction';
$value = $this->OrderInfo($params);
- if( isset($params['field']) ) return $params['field'] == $value;
- if( isset($params['direction']) ) return $params['direction'] == $value;
+ if ( isset($params['field']) ) {
+ return $params['field'] == $value;
+ }
+ elseif ( isset($params['direction']) ) {
+ return $params['direction'] == $value;
+ }
+
+ return false;
}
/**
- * Returns list perpage
+ * Returns list per-page
*
* @param Array $params
* @return int
*/
function PerPage($params)
{
$object =& $this->GetList($params);
return $object->GetPerPage();
}
/**
* Checks if list perpage matches value specified
*
* @param Array $params
* @return bool
*/
function PerPageEquals($params)
{
$object =& $this->GetList($params);
return $object->GetPerPage() == $params['value'];
}
function SaveEvent($params)
{
// SaveEvent is set during OnItemBuild, but we may need it before any other tag calls OnItemBuild
$object =& $this->getObject($params);
return $this->Application->GetVar($this->getPrefixSpecial().'_SaveEvent');
}
function NextId($params)
{
$object =& $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i < count($ids) - 1 ? $ids[$i + 1] : '';
}
return '';
}
function PrevId($params)
{
$object =& $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i > 0 ? $ids[$i - 1] : '';
}
return '';
}
function IsSingle($params)
{
return ($this->NextId($params) === '' && $this->PrevId($params) === '');
}
function IsLast($params)
{
return ($this->NextId($params) === '');
}
function IsFirst($params)
{
return ($this->PrevId($params) === '');
}
/**
* Checks if field value is equal to proposed one
*
* @param Array $params
* @return bool
*/
function FieldEquals($params)
{
$object =& $this->getObject($params);
return $object->GetDBField( $this->SelectParam($params, 'name,field') ) == $params['value'];
}
/**
* Checks, that grid has icons defined and they should be shown
*
* @param Array $params
* @return bool
*/
function UseItemIcons($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
return array_key_exists('Icons', $grids[ $params['grid'] ]);
}
/**
* Returns corresponding to grid layout selector column width
*
* @param Array $params
* @return int
*/
function GridSelectorColumnWidth($params)
{
$width = 0;
if ($params['selector']) {
$width += $params['selector_width'];
}
if ($this->UseItemIcons($params)) {
$width += $params['icon_width'];
}
return $width;
}
/**
* Returns grids item selection mode (checkbox, radio, )
*
* @param Array $params
* @return string
*/
function GridSelector($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
return array_key_exists('Selector', $grids[ $params['grid'] ]) ? $grids[ $params['grid'] ]['Selector'] : $params['default'];
}
function ItemIcon($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$grid = $grids[ $params['grid'] ];
- if (!array_key_exists('Icons', $grid)) {
+ if ( !isset($grid['Icons']) ) {
return '';
}
$icons = $grid['Icons'];
- if (array_key_exists('name', $params)) {
+ if ( isset($params['name']) ) {
$icon_name = $params['name'];
- return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : '';
+
+ return isset($icons[$icon_name]) ? $icons[$icon_name] : '';
}
- $status_fields = $this->Application->getUnitOption($this->Prefix, 'StatusField');
+ $status_fields = $this->Application->getUnitOption($this->Prefix, 'StatusField', Array ());
+ /* @var $status_fields Array */
- if (!$status_fields) {
+ if ( !$status_fields ) {
return $icons['default'];
}
$object =& $this->getObject($params);
/* @var $object kDBList */
$icon = '';
foreach ($status_fields as $status_field) {
$icon .= $object->GetDBField($status_field) . '_';
}
$icon = rtrim($icon, '_');
- return array_key_exists($icon, $icons) ? $icons[$icon] : $icons['default'];
+ return isset($icons[$icon]) ? $icons[$icon] : $icons['default'];
}
/**
* Generates bluebar title + initializes prefixes used on page
*
* @param Array $params
* @return string
*/
function SectionTitle($params)
{
$preset_name = kUtil::replaceModuleSection($params['title_preset']);
$title_presets = $this->Application->getUnitOption($this->Prefix,'TitlePresets');
$title_info = array_key_exists($preset_name, $title_presets) ? $title_presets[$preset_name] : false;
if ($title_info === false) {
$title = str_replace('#preset_name#', $preset_name, $params['title']);
if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) {
$title .= ' - '.$params['group_title'];
}
return $title;
}
if (array_key_exists('default', $title_presets) && $title_presets['default']) {
// use default labels + custom labels specified in preset used
$title_info = kUtil::array_merge_recursive($title_presets['default'], $title_info);
}
$title = $title_info['format'];
// 1. get objects in use for title construction
$objects = Array();
$object_status = Array();
$status_labels = Array();
$prefixes = array_key_exists('prefixes', $title_info) ? $title_info['prefixes'] : false;
$all_tag_params = array_key_exists('tag_params', $title_info) ? $title_info['tag_params'] : false;
-
+ /* @var $prefixes Array */
+
if ($prefixes) {
- // extract tag_perams passed directly to SectionTitle tag for specific prefix
+ // extract tag_params passed directly to SectionTitle tag for specific prefix
foreach ($params as $tp_name => $tp_value) {
if (preg_match('/(.*)\[(.*)\]/', $tp_name, $regs)) {
$all_tag_params[ $regs[1] ][ $regs[2] ] = $tp_value;
unset($params[$tp_name]);
}
}
$tag_params = Array();
foreach ($prefixes as $prefix_special) {
$prefix_data = $this->Application->processPrefix($prefix_special);
$prefix_data['prefix_special'] = rtrim($prefix_data['prefix_special'],'.');
if ($all_tag_params) {
$tag_params = getArrayValue($all_tag_params, $prefix_data['prefix_special']);
if (!$tag_params) {
$tag_params = Array();
}
}
$tag_params = array_merge($params, $tag_params);
$objects[ $prefix_data['prefix_special'] ] =& $this->Application->recallObject($prefix_data['prefix_special'], $prefix_data['prefix'], $tag_params);
$object_status[ $prefix_data['prefix_special'] ] = $objects[ $prefix_data['prefix_special'] ]->IsNewItem() ? 'new' : 'edit';
// a. set object's status field (adding item/editing item) for each object in title
if (getArrayValue($title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ],$prefix_data['prefix_special'])) {
$status_labels[ $prefix_data['prefix_special'] ] = $title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ][ $prefix_data['prefix_special'] ];
$title = str_replace('#'.$prefix_data['prefix_special'].'_status#', $status_labels[ $prefix_data['prefix_special'] ], $title);
}
// b. setting object's titlefield value (in titlebar ONLY) to default in case if object beeing created with no titlefield filled in
if ($object_status[ $prefix_data['prefix_special'] ] == 'new') {
$new_value = $this->getInfo( $objects[ $prefix_data['prefix_special'] ], 'titlefield' );
if(!$new_value && getArrayValue($title_info['new_titlefield'],$prefix_data['prefix_special']) ) $new_value = $this->Application->Phrase($title_info['new_titlefield'][ $prefix_data['prefix_special'] ]);
$title = str_replace('#'.$prefix_data['prefix_special'].'_titlefield#', $new_value, $title);
}
}
}
// replace to section title
$section = array_key_exists('section', $params) ? $params['section'] : false;
if ($section) {
$sections_helper =& $this->Application->recallObject('SectionsHelper');
/* @var $sections_helper kSectionsHelper */
$section_data =& $sections_helper->getSectionData($section);
$title = str_replace('#section_label#', '!' . $section_data['label'] . '!', $title);
}
// 2. replace phrases if any found in format string
$title = $this->Application->ReplaceLanguageTags($title, false);
// 3. find and replace any replacement vars
preg_match_all('/#(.*_.*)#/Uis',$title,$rets);
if ($rets[1]) {
$replacement_vars = array_keys( array_flip($rets[1]) );
foreach ($replacement_vars as $replacement_var) {
$var_info = explode('_',$replacement_var,2);
$object =& $objects[ $var_info[0] ];
$new_value = $this->getInfo($object,$var_info[1]);
$title = str_replace('#'.$replacement_var.'#', $new_value, $title);
}
}
// replace trailing spaces inside title preset + '' occurences into single space
$title = preg_replace('/[ ]*\'\'[ ]*/', ' ', $title);
if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) {
$title .= ' - '.$params['group_title'];
}
$first_chars = $this->SelectParam($params, 'first_chars,cut_first');
if ($first_chars && !preg_match('/<a href="(.*)".*>(.*)<\/a>/', $title)) {
// don't cut titles, that contain phrase translation links
$stripped_title = strip_tags($title, $this->SelectParam($params, 'allowed_tags'));
if (mb_strlen($stripped_title) > $first_chars) {
$title = mb_substr($stripped_title, 0, $first_chars) . ' ...';
}
}
return $title;
}
- function getInfo(&$object, $info_type)
+ /**
+ * Returns information about list
+ *
+ * @param kDBList $object
+ * @param string $info_type
+ * @return string
+ * @access protected
+ */
+ protected function getInfo(&$object, $info_type)
{
- switch ($info_type)
- {
+ switch ( $info_type ) {
case 'titlefield':
- $field = $this->Application->getUnitOption($object->Prefix,'TitleField');
+ $field = $this->Application->getUnitOption($object->Prefix, 'TitleField');
return $field !== false ? $object->GetField($field) : 'TitleField Missing';
break;
case 'recordcount':
- $of_phrase = $this->Application->Phrase('la_of');
- return $object->GetRecordsCount(false) != $object->GetRecordsCount() ? $object->GetRecordsCount().' '.$of_phrase.' '.$object->GetRecordsCount(false) : $object->GetRecordsCount();
- break;
-
- default:
- return $object->GetField($info_type);
+ if ( $object->GetRecordsCount(false) != $object->GetRecordsCount() ) {
+ $of_phrase = $this->Application->Phrase('la_of');
+ return $object->GetRecordsCount() . ' ' . $of_phrase . ' ' . $object->GetRecordsCount(false);
+ }
+
+ return $object->GetRecordsCount();
break;
}
+
+ return $object->GetField($info_type);
}
function GridInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
switch ( $params['type'] ) {
case 'filtered':
return $object->GetRecordsCount();
case 'total':
return $object->GetRecordsCount(false);
case 'from':
return $object->GetRecordsCount() ? $object->GetOffset() + 1 : 0; //0-based
case 'to':
$record_count = $object->GetRecordsCount();
return $object->GetPerPage(true) != -1 ? min($object->GetOffset() + $object->GetPerPage(), $record_count) : $record_count;
case 'total_pages':
return $object->GetTotalPages();
case 'needs_pagination':
return ($object->GetPerPage(true) != -1) && (($object->GetRecordsCount() > $object->GetPerPage()) || ($object->GetPage() > 1));
}
return false;
}
/**
* Parses block depending on its element type.
* For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2
* format. key=value can be substituted by <SQL>SELECT f1 AS OptionName, f2 AS OptionValue... FROM <PREFIX>TableName </SQL>
* where prefix is TABLE_PREFIX
*
* @param Array $params
* @return string
*/
function ConfigFormElement($params)
{
$object =& $this->getObject($params);
$field = $params['field'];
$helper =& $this->Application->recallObject('InpCustomFieldsHelper');
/* @var $helper InpCustomFieldsHelper */
$element_type = $object->GetDBField($params['element_type_field']);
if ($element_type == 'label') {
$element_type = 'text';
}
switch ($element_type) {
case 'select':
case 'multiselect':
case 'radio':
$field_options = $object->GetFieldOptions($field, 'options');
if ($object->GetDBField('DirectOptions')) {
// used for custom fields
$field_options['options'] = $object->GetDBField('DirectOptions');
}
else {
// used for configuration
$field_options['options'] = $helper->GetValuesHash( $object->GetDBField($params['value_list_field']) );
}
$object->SetFieldOptions($field, $field_options);
break;
case 'text':
case 'textarea':
$params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field']));
break;
case 'password':
case 'checkbox':
default:
break;
}
if (!$element_type) {
throw new Exception('Element type missing for "<strong>' . $object->GetDBField('VariableName') . '</strong>" configuration variable');
return '';
}
$params['name'] = $params['blocks_prefix'] . $element_type;
// use $pass_params to pass 'SourcePrefix' parameter from PrintList to CustomInputName tag
return $this->Application->ParseBlock($params, 1);
}
/**
* Get's requested custom field value
*
* @param Array $params
* @return string
* @access public
*/
function CustomField($params)
{
$params['name'] = 'cust_'.$this->SelectParam($params, 'name,field');
return $this->Field($params);
}
function CustomFieldLabel($params)
{
$object =& $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
$sql = 'SELECT FieldLabel
FROM '.$this->Application->getUnitOption('cf', 'TableName').'
WHERE FieldName = '.$this->Conn->qstr($field);
return $this->Application->Phrase($this->Conn->GetOne($sql));
}
/**
* transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters
*
* @param array $arr
* @param int $columns
* @param int $per_page
* @return array
*/
function LinearToVertical(&$arr, $columns, $per_page)
{
$rows = $columns;
// in case if after applying per_page limit record count less then
// can fill requrested column count, then fill as much as we can
$cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns));
$imatrix = array();
for ($row = 0; $row < $rows; $row++) {
for ($col = 0; $col < $cols; $col++) {
$source_index = $row * $cols + $col;
if (!isset($arr[$source_index])) {
// in case if source array element count is less then element count in one row
continue;
}
$imatrix[$col * $rows + $row] = $arr[$source_index];
}
}
ksort($imatrix);
return array_values($imatrix);
}
/**
- * If data was modfied & is in TempTables mode, then parse block with name passed;
+ * If data was modified & is in TempTables mode, then parse block with name passed;
* remove modification mark if not in TempTables mode
*
* @param Array $params
* @return string
- * @access public
- * @author Alexey
+ * @access protected
*/
- function SaveWarning($params)
+ protected function SaveWarning($params)
{
$main_prefix = array_key_exists('main_prefix', $params) ? $params['main_prefix'] : false;
- if ($main_prefix) {
+
+ if ( $main_prefix ) {
$top_prefix = $main_prefix;
}
else {
$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
}
- $temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't';
- $modified = $this->Application->RecallVar($top_prefix.'_modified');
+ $temp_tables = substr($this->Application->GetVar($top_prefix . '_mode'), 0, 1) == 't';
+ $modified = $this->Application->RecallVar($top_prefix . '_modified');
- if ($temp_tables && $modified) {
+ if ( $temp_tables && $modified ) {
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,name');
$block_params['edit_mode'] = $temp_tables ? 1 : 0;
return $this->Application->ParseBlock($block_params);
}
- $this->Application->RemoveVar($top_prefix.'_modified');
+
+ $this->Application->RemoveVar($top_prefix . '_modified');
return '';
}
/**
* Returns list record count queries (on all pages)
*
* @param Array $params
* @return int
*/
function TotalRecords($params)
{
$list =& $this->GetList($params);
return $list->GetRecordsCount();
}
/**
* Range filter field name
*
* @param Array $params
* @return string
*/
function SearchInputName($params)
{
$field = $this->SelectParam($params, 'field,name');
$ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']';
if (isset($params['type'])) {
$ret .= '['.$params['type'].']';
}
return $ret;
}
/**
* Return range filter field value
*
* @param Array $params
* @return string
+ * @access protected
*/
- function SearchField($params) // RangeValue
+ protected function SearchField($params) // RangeValue
{
$field = $this->SelectParam($params, 'field,name');
- $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
- $custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/);
- $custom_filter = $custom_filter ? unserialize($custom_filter) : Array();
+ $view_name = $this->Application->RecallVar($this->getPrefixSpecial() . '_current_view');
+ $custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial() . '_custom_filter.' . $view_name /*, ALLOW_DEFAULT_SETTINGS*/);
+ $custom_filter = $custom_filter ? unserialize($custom_filter) : Array ();
- if (isset($custom_filter[ $params['grid'] ][$field])) {
- $ret = $custom_filter[ $params['grid'] ][$field][ $params['filter_type'] ]['submit_value'];
- if (isset($params['type'])) {
- $ret = $ret[ $params['type'] ];
+ if ( isset($custom_filter[$params['grid']][$field]) ) {
+ $ret = $custom_filter[$params['grid']][$field][$params['filter_type']]['submit_value'];
+ if ( isset($params['type']) ) {
+ $ret = $ret[$params['type']];
}
- if (array_key_exists('formatted', $params) && $params['formatted']) {
+ if ( array_key_exists('formatted', $params) && $params['formatted'] ) {
$object =& $this->GetList($params);
- $field_options = $object->GetFieldOptions($field);
-
- if (array_key_exists('formatter', $field_options)) {
- $formatter_class = $field_options['formatter'];
+ $formatter_class = $object->GetFieldOption($field, 'formatter');
+ if ( $formatter_class ) {
$formatter =& $this->Application->recallObject($formatter_class);
/* @var $formatter kFormatter */
$ret = $formatter->Format($ret, $field, $object);
}
}
- if (!array_key_exists('no_special', $params) || !$params['no_special']) {
+ if ( !array_key_exists('no_special', $params) || !$params['no_special'] ) {
$ret = htmlspecialchars($ret);
}
return $ret;
}
return '';
}
/**
* Tells, that at least one of search filters is used by now
*
* @param Array $params
* @return bool
*/
function SearchActive($params)
{
if ($this->Application->RecallVar($this->getPrefixSpecial() . '_search_keyword')) {
// simple search filter is used
return true;
}
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/);
$custom_filter = $custom_filter ? unserialize($custom_filter) : Array();
return array_key_exists($params['grid'], $custom_filter);
}
function SearchFormat($params)
{
$field = $params['field'];
$object =& $this->GetList($params);
$options = $object->GetFieldOptions($field);
$format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ];
$formatter_class = array_key_exists('formatter', $options) ? $options['formatter'] : false;
if ($formatter_class) {
$formatter =& $this->Application->recallObject($formatter_class);
+ /* @var $formatter kFormatter */
+
$human_format = array_key_exists('human', $params) ? $params['human'] : false;
$edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false;
$sample = array_key_exists('sample', $params) ? $params['sample'] : false;
if ($sample) {
return $formatter->GetSample($field, $options, $object);
}
elseif ($human_format || $edit_size) {
$format = $formatter->HumanFormat($format);
return $edit_size ? strlen($format) : $format;
}
}
return $format;
}
/**
* Returns error of range field
*
- * @param unknown_type $params
- * @return unknown
+ * @param Array $params
+ * @return string
+ * @access protected
*/
- function SearchError($params)
+ protected function SearchError($params)
{
$field = $this->SelectParam($params, 'field,name');
- $error_var_name = $this->getPrefixSpecial().'_'.$field.'_error';
+ $error_var_name = $this->getPrefixSpecial() . '_' . $field . '_error';
$pseudo = $this->Application->RecallVar($error_var_name);
- if ($pseudo) {
+ if ( $pseudo ) {
$this->Application->RemoveVar($error_var_name);
}
- $object =& $this->Application->recallObject($this->Prefix.'.'.$this->Special.'-item', null, Array('skip_autoload' => true));
+ $object =& $this->Application->recallObject($this->Prefix . '.' . $this->Special . '-item', null, Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->SetError($field, $pseudo);
return $object->GetErrorMsg($field, false);
}
/**
* Returns object used in tag processor
*
* @access public
* @return kDBBase
*/
function &getObject($params = Array())
{
$object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params);
if (isset($params['requery']) && $params['requery']) {
$this->Application->HandleEvent($q_event, $this->getPrefixSpecial().':LoadItem', $params);
}
return $object;
}
/**
* Checks if object propery value matches value passed
*
* @param Array $params
* @return bool
*/
function PropertyEquals($params)
{
$object =& $this->getObject($params);
$property_name = $this->SelectParam($params, 'name,var,property');
return $object->$property_name == $params['value'];
}
function DisplayOriginal($params)
{
return false;
}
/*function MultipleEditing($params)
{
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$selected_ids = explode(',', $this->Application->RecallVar($session_name));
$ret = '';
if ($selected_ids) {
$selected_ids = explode(',', $selected_ids);
$object =& $this->getObject( kUtil::array_merge_recursive($params, Array('skip_autoload' => true)) );
$params['name'] = $params['render_as'];
foreach ($selected_ids as $id) {
$object->Load($id);
$ret .= $this->Application->ParseBlock($params);
}
}
return $ret;
}*/
/**
* Returns import/export process percent
*
* @param Array $params
* @return int
* @deprecated Please convert to event-model, not tag based
*/
function ExportStatus($params)
{
$export_object =& $this->Application->recallObject('CatItemExportHelper');
-
+ /* @var $export_object kCatDBItemExportHelper */
+
$event = new kEvent($this->getPrefixSpecial().':OnDummy');
$action_method = 'perform'.ucfirst($this->Special);
$field_values = $export_object->$action_method($event);
// finish code is done from JS now
if ($field_values['start_from'] >= $field_values['total_records'])
{
if ($this->Special == 'import') {
// this is used?
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1, 'no_amp' => 1));
}
elseif ($this->Special == 'export') {
// used for orders export in In-Commerce
$finish_t = $this->Application->RecallVar('export_finish_t');
$this->Application->Redirect($finish_t, Array('pass' => 'all'));
$this->Application->RemoveVar('export_finish_t');
}
}
$export_options = $export_object->loadOptions($event);
return $export_options['start_from'] * 100 / $export_options['total_records'];
}
/**
* Returns path where exported category items should be saved
*
* @param Array $params
+ * @return string
+ * @access protected
*/
- function ExportPath($params)
+ protected function ExportPath($params)
{
- $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial().'_options'));
+ $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial() . '_options'));
$extension = $export_options['ExportFormat'] == 1 ? 'csv' : 'xml';
$filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $export_options['ExportFilename']) . '.' . $extension;
$path = EXPORT_PATH . '/';
- if (array_key_exists('as_url', $params) && $params['as_url']) {
- $path = str_replace( FULL_PATH . '/', $this->Application->BaseURL(), $path);
+
+ if ( array_key_exists('as_url', $params) && $params['as_url'] ) {
+ $path = str_replace(FULL_PATH . '/', $this->Application->BaseURL(), $path);
}
return $path . $filename;
}
function FieldTotal($params)
{
$list =& $this->GetList($params);
$field = $this->SelectParam($params, 'field,name');
$total_function = array_key_exists('function', $params) ? $params['function'] : $list->getTotalFunction($field);
if (array_key_exists('function_only', $params) && $params['function_only']) {
return $total_function;
}
if (array_key_exists('currency', $params) && $params['currency']) {
$iso = $this->GetISO($params['currency']);
$original = $list->getTotal($field, $total_function);
$value = $this->ConvertCurrency($original, $iso);
$list->setTotal($field, $total_function, $value);
}
$value = $list->GetFormattedTotal($field, $total_function);
if (array_key_exists('currency', $params) && $params['currency']) {
$value = $this->AddCurrencySymbol($value, $iso);
}
return $value;
}
/**
* Returns FCKEditor locale, that matches default site language
*
* @return string
*/
function _getFCKLanguage()
{
static $language_code = null;
if (!isset($language_code)) {
$language_code = 'en'; // defaut value
if ($this->Application->isAdmin) {
$language_id = $this->Application->Phrases->LanguageId;
}
else {
$language_id = $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang');
}
$sql = 'SELECT Locale
FROM '. $this->Application->getUnitOption('lang', 'TableName') . '
WHERE LanguageId = ' . $language_id;
$locale = strtolower( $this->Conn->GetOne($sql) );
if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js')) {
// found language file, that exactly matches locale name (e.g. "en")
$language_code = $locale;
}
else {
$locale = explode('-', $locale);
if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js')) {
// language file matches first part of locale (e.g. "ru-RU")
$language_code = $locale[0];
}
}
}
return $language_code;
}
function FCKEditor($params)
{
$params['no_special'] = 1;
$params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready';
$value = $this->Field($params);
$name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params);
$theme_path = substr($this->Application->GetFrontThemePath(), 1) . '/inc/';
if (!file_exists(FULL_PATH . '/' . $theme_path . 'style.css')) {
$theme_path = EDITOR_PATH;
}
$styles_xml = $this->Application->BaseURL() . $theme_path . 'styles.xml';
$styles_css = $this->Application->BaseURL() . $theme_path . 'style.css';
$bgcolor = array_key_exists('bgcolor', $params) ? $params['bgcolor'] : $this->Application->GetVar('bgcolor');
if (!$bgcolor) {
$bgcolor = '#ffffff';
}
$preview_url = '';
$page_id = $this->Application->GetVar('c_id');
$content_id = $this->Application->GetVar('content_id');
if ($page_id && $content_id) {
// editing content block from Front-End, not category in admin
$sql = 'SELECT NamedParentPath
FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('c', 'IDField') . ' = ' . (int)$page_id;
$template = strtolower( $this->Conn->GetOne($sql) );
$url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CONTENT, 'pass' => 'm');
$preview_url = $this->Application->HREF($template, '_FRONT_END_', $url_params, 'index.php');
$preview_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $preview_url);
}
include_once(FULL_PATH . EDITOR_PATH . 'fckeditor.php');
$oFCKeditor = new FCKeditor($name);
$oFCKeditor->FullUrl = $this->Application->BaseURL();
$oFCKeditor->BaseUrl = BASE_PATH . '/';
$oFCKeditor->BasePath = BASE_PATH . EDITOR_PATH;
$oFCKeditor->Width = $params['width'] ;
$oFCKeditor->Height = $params['height'] ;
$oFCKeditor->ToolbarSet = $page_id && $content_id ? 'Advanced' : 'Default';
$oFCKeditor->Value = $value;
$oFCKeditor->PreviewUrl = $preview_url;
$oFCKeditor->DefaultLanguage = $this->_getFCKLanguage();
$oFCKeditor->LateLoad = array_key_exists('late_load', $params) && $params['late_load'];
$oFCKeditor->Config = Array (
//'UserFilesPath' => $pathtoroot.'kernel/user_files',
'ProjectPath' => BASE_PATH . '/',
'CustomConfigurationsPath' => $this->Application->BaseURL() . 'core/admin_templates/js/inp_fckconfig.js',
'StylesXmlPath' => $styles_xml,
'EditorAreaCSS' => $styles_css,
'DefaultStyleLabel' => $this->Application->Phrase('la_editor_default_style'),
// 'Debug' => 1,
'Admin' => 1,
'K4' => 1,
'newBgColor' => $bgcolor,
'PreviewUrl' => $preview_url,
'BaseUrl' => BASE_PATH . '/',
'DefaultLanguage' => $this->_getFCKLanguage(),
'EditorAreaStyles' => 'body { background-color: '.$bgcolor.' }',
);
return $oFCKeditor->CreateHtml();
}
function IsNewItem($params)
{
$object =& $this->getObject($params);
return $object->IsNewItem();
}
/**
* Creates link to an item including only it's id
*
* @param Array $params
* @return string
+ * @access protected
*/
- function ItemLink($params)
+ protected function ItemLink($params)
{
$object =& $this->getObject($params);
+ /* @var $object kDBItem */
- if (!isset($params['pass'])) {
+ if ( !isset($params['pass']) ) {
$params['pass'] = 'm';
}
- $params[$object->getPrefixSpecial().'_id'] = $object->GetID();
+ $params[ $object->getPrefixSpecial() . '_id' ] = $object->GetID();
- $m =& $this->Application->recallObject('m_TagProcessor');
- return $m->t($params);
+ return $this->Application->ProcessParsedTag('m', 'T', $params);
}
/**
* Calls OnNew event from template, when no other event submitted
*
* @param Array $params
*/
function PresetFormFields($params)
{
$prefix = $this->getPrefixSpecial();
- if (!$this->Application->GetVar($prefix.'_event')) {
- $this->Application->HandleEvent(new kEvent($prefix.':OnNew'));
+ if ( !$this->Application->GetVar($prefix . '_event') ) {
+ $this->Application->HandleEvent(new kEvent($prefix . ':OnNew'));
}
}
function PrintSerializedFields($params)
{
$object =& $this->getObject();
$field = $this->SelectParam($params, 'field');
$data = unserialize($object->GetDBField($field));
$o = '';
$std_params['name'] = $params['render_as'];
$std_params['field'] = $params['field'];
$std_params['pass_params'] = true;
foreach ($data as $key => $row) {
$block_params = array_merge($std_params, $row, array('key'=>$key));
$o .= $this->Application->ParseBlock($block_params);
}
return $o;
}
/**
* Checks if current prefix is main item
*
* @param Array $params
* @return bool
*/
function IsTopmostPrefix($params)
{
return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix);
}
function PermSection($params)
{
$section = $this->SelectParam($params, 'section,name');
$perm_sections = $this->Application->getUnitOption($this->Prefix, 'PermSection');
return isset($perm_sections[$section]) ? $perm_sections[$section] : '';
}
function PerPageSelected($params)
{
$list =& $this->GetList($params);
return $list->GetPerPage() == $params['per_page'] ? $params['selected'] : '';
}
/**
* Returns prefix + generated sepcial + any word
*
* @param Array $params
* @return string
*/
function VarName($params)
{
$list =& $this->GetList($params);
return $list->getPrefixSpecial() . '_' . $params['type'];
}
/**
* Returns edit tabs by specified preset name or false in case of error
*
* @param string $preset_name
* @return mixed
*/
function getEditTabs($preset_name)
{
$presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets');
if (!$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0) {
return false;
}
return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false;
}
/**
* Detects if specified preset has tabs in it
*
* @param Array $params
* @return bool
*/
function HasEditTabs($params)
{
return $this->getEditTabs($params['preset_name']) ? true : false;
}
/**
* Sorts edit tabs based on their priority
*
* @param Array $tab_a
* @param Array $tab_b
* @return int
*/
function sortEditTabs($tab_a, $tab_b)
{
if ($tab_a['priority'] == $tab_b['priority']) {
return 0;
}
return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1;
}
/**
* Prints edit tabs based on preset name specified
*
* @param Array $params
* @return string
+ * @access protected
*/
- function PrintEditTabs($params)
+ protected function PrintEditTabs($params)
{
$edit_tabs = $this->getEditTabs($params['preset_name']);
- if (!$edit_tabs) {
- return ;
+ if ( !$edit_tabs ) {
+ return '';
}
usort($edit_tabs, Array (&$this, 'sortEditTabs'));
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($edit_tabs as $tab_info) {
$block_params['title'] = $tab_info['title'];
$block_params['template'] = $tab_info['t'];
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Performs image resize to required dimensions and returns resulting url (cached resized image)
*
* @param Array $params
* @return string
*/
function ImageSrc($params)
{
$max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false;
$max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false;
$logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false;
$logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false;
$logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false;
$object =& $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin);
}
/**
* Allows to retrieve given setting from unit config
*
* @param Array $params
* @return mixed
*/
function UnitOption($params)
{
return $this->Application->getUnitOption($this->Prefix, $params['name']);
}
/**
* Returns list of allowed toolbar buttons or false, when all is allowed
*
* @param Array $params
* @return string
*/
function VisibleToolbarButtons($params)
{
$preset_name = kUtil::replaceModuleSection($params['title_preset']);
$title_presets = $this->Application->getUnitOption($this->Prefix, 'TitlePresets');
if (!array_key_exists($preset_name, $title_presets)) {
trigger_error('Title preset not specified or missing (in tag "<strong>' . $this->getPrefixSpecial() . ':' . __METHOD__ . '</strong>")', E_USER_NOTICE);
return false;
}
$preset_info = $title_presets[$preset_name];
if (!array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons'])) {
return false;
}
// always add search buttons
array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt');
$toolbar_buttons = array_map('addslashes', $preset_info['toolbar_buttons']);
return $toolbar_buttons ? "'" . implode("', '", $toolbar_buttons) . "'" : 'false';
}
/**
* Checks, that "To" part of at least one of range filters is used
*
* @param Array $params
* @return bool
*/
function RangeFiltersUsed($params)
{
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']);
}
/**
* This is abstract tag, used to modify unit config data based on template, where it's used.
* Tag is called from "combined_header" block in admin only.
*
* @param Array $params
*/
function ModifyUnitConfig($params)
{
}
/**
* Checks, that field is visible on edit form
*
* @param Array $params
* @return bool
*/
function FieldVisible($params)
{
$check_field = $params['field'];
$fields = $this->Application->getUnitOption($this->Prefix, 'Fields');
if (!array_key_exists($check_field, $fields)) {
// field not found in real fields array -> it's 100% virtual then
$fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields', Array ());
}
if (!array_key_exists($check_field, $fields)) {
$params['field'] = 'Password';
return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true;
}
$show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true;
if ($show_mode === smDEBUG) {
return defined('DEBUG_MODE') && DEBUG_MODE;
}
return $show_mode;
}
/**
* Checks, that there area visible fields in given section on edit form
*
* @param Array $params
* @return bool
*/
function FieldsVisible($params)
{
if (!$params['fields']) {
return true;
}
$check_fields = explode(',', $params['fields']);
$fields = $this->Application->getUnitOption($this->Prefix, 'Fields');
$virtual_fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields');
foreach ($check_fields as $check_field) {
// when at least one field in subsection is visible, then subsection is visible too
if (array_key_exists($check_field, $fields)) {
$show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true;
}
else {
$show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true;
}
if (($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE))) {
// field is visible
return true;
}
}
return false;
}
/**
* Checks, that requested option is checked inside field value
*
* @param Array $params
* @return bool
*/
function Selected($params)
{
$object =& $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'name,field');
$value = $object->GetDBField($field);
if (strpos($value, '|') !== false) {
$value = explode('|', substr($value, 1, -1));
return in_array($params['value'], $value);
}
return $value;
}
+
+ /**
+ * Returns/sets form name for current object
+ *
+ * @param Array $params
+ * @return string
+ */
+ function FormName($params)
+ {
+ $form_name = $this->SelectParam($params, 'name,form,form_name');
+
+ if ( $form_name ) {
+ $prefix = $this->getPrefixSpecial();
+
+ if ( $this->Application->hasObject( $this->getPrefixSpecial() ) ) {
+ $object =& $this->getObject($params);
+ /* @var $object kDBItem */
+
+ if ( $object->getFormName() != $form_name ) {
+ trigger_error('Setting form to "<strong>' . $form_name . '</strong>" failed, since object "<strong>' . $this->getPrefixSpecial() . '</strong>" is created before FormName tag (e.g. in event or another tag).', E_USER_WARNING);
+ }
+ }
+ else {
+ $forms = $this->Application->GetVar('forms', Array ());
+ $forms[ $this->getPrefixSpecial() ] = $form_name;
+ $this->Application->SetVar('forms', $forms);
+ }
+
+ return '';
+ }
+
+ $object =& $this->getObject($params);
+ /* @var $object kDBItem */
+
+ return $object->getFormName();
+ }
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/db/db_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/db_event_handler.php (revision 14595)
+++ branches/5.2.x/core/kernel/db/db_event_handler.php (revision 14596)
@@ -1,2945 +1,3076 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
define('EH_CUSTOM_PROCESSING_BEFORE',1);
define('EH_CUSTOM_PROCESSING_AFTER',2);
/**
* Note:
* 1. When adressing variables from submit containing
* Prefix_Special as part of their name use
* $event->getPrefixSpecial(true) instead of
* $event->getPrefixSpecial() as usual. This is due PHP
* is converting "." symbols in variable names during
* submit info "_". $event->getPrefixSpecial optional
* 1st parameter returns correct corrent Prefix_Special
* for variables beeing submitted such way (e.g. variable
* name that will be converted by PHP: "users.read_only_id"
* will be submitted as "users_read_only_id".
*
* 2. When using $this->Application-LinkVar on variables submitted
* from form which contain $Prefix_Special then note 1st item. Example:
* LinkVar($event->getPrefixSpecial(true).'_varname',$event->getPrefixSpecial().'_varname')
*
*/
/**
* EventHandler that is used to process
* any database related events
*
*/
class kDBEventHandler extends kEventHandler {
/**
* Checks permissions of user
*
* @param kEvent $event
+ * @return bool
+ * @access public
*/
function CheckPermission(&$event)
{
$section = $event->getSection();
if (!$this->Application->isAdmin) {
$allow_events = Array('OnSearch', 'OnSearchReset', 'OnNew');
if (in_array($event->Name, $allow_events)) {
// allow search on front
return true;
}
}
elseif (($event->Name == 'OnPreSaveAndChangeLanguage') && !$this->UseTempTables($event)) {
// allow changing language in grids, when not in editing mode
return $this->Application->CheckPermission($section . '.view', 1);
}
if (!preg_match('/^CATEGORY:(.*)/', $section)) {
// only if not category item events
if ((substr($event->Name, 0, 9) == 'OnPreSave') || ($event->Name == 'OnSave')) {
if ($this->isNewItemCreate($event)) {
return $this->Application->CheckPermission($section.'.add', 1);
}
else {
return $this->Application->CheckPermission($section.'.add', 1) || $this->Application->CheckPermission($section.'.edit', 1);
}
}
}
if ($event->Name == 'OnPreCreate') {
// save category_id before item create (for item category selector not to destroy permission checking category)
$this->Application->LinkVar('m_cat_id');
}
if ($event->Name == 'OnSaveWidths') {
return $this->Application->isAdminUser;
}
return parent::CheckPermission($event);
}
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnLoad' => Array('self' => 'view', 'subitem' => 'view'),
'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'),
'OnSuggestValues' => Array('self' => 'view', 'subitem' => 'view'),
'OnBuild' => Array('self' => true),
'OnNew' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnCreate' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnUpdate' => Array('self' => 'edit', 'subitem' => 'add|edit'),
'OnSetPrimary' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnDeleteAll' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnMassDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnMassClone' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnCut' => array('self'=>'edit', 'subitem' => 'edit'),
'OnCopy' => array('self'=>'edit', 'subitem' => 'edit'),
'OnPaste' => array('self'=>'edit', 'subitem' => 'edit'),
'OnSelectItems' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnProcessSelected' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnStoreSelected' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnSelectUser' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnMassApprove' => Array('self' => 'advanced:approve|edit', 'subitem' => 'advanced:approve|add|edit'),
'OnMassDecline' => Array('self' => 'advanced:decline|edit', 'subitem' => 'advanced:decline|add|edit'),
'OnMassMoveUp' => Array('self' => 'advanced:move_up|edit', 'subitem' => 'advanced:move_up|add|edit'),
'OnMassMoveDown' => Array('self' => 'advanced:move_down|edit', 'subitem' => 'advanced:move_down|add|edit'),
'OnPreCreate' => Array('self' => 'add|add.pending', 'subitem' => 'edit|edit.pending'),
'OnEdit' => Array('self' => 'edit|edit.pending', 'subitem' => 'edit|edit.pending'),
'OnExport' => Array('self' => 'view|advanced:export'),
'OnExportBegin' => Array('self' => 'view|advanced:export'),
'OnExportProgress' => Array('self' => 'view|advanced:export'),
'OnSetAutoRefreshInterval' => Array ('self' => true, 'subitem' => true),
'OnAutoRefreshToggle' => Array ('self' => true, 'subitem' => true),
// theese event do not harm, but just in case check them too :)
'OnCancelEdit' => Array('self' => true, 'subitem' => true),
'OnCancel' => Array('self' => true, 'subitem' => true),
'OnReset' => Array('self' => true, 'subitem' => true),
'OnSetSorting' => Array('self' => true, 'subitem' => true),
'OnSetSortingDirect' => Array('self' => true, 'subitem' => true),
'OnResetSorting' => Array('self' => true, 'subitem' => true),
'OnSetFilter' => Array('self' => true, 'subitem' => true),
'OnApplyFilters' => Array('self' => true, 'subitem' => true),
'OnRemoveFilters' => Array('self' => true, 'subitem' => true),
'OnSetFilterPattern' => Array('self' => true, 'subitem' => true),
'OnSetPerPage' => Array('self' => true, 'subitem' => true),
'OnSetPage' => Array('self' => true, 'subitem' => true),
'OnSearch' => Array('self' => true, 'subitem' => true),
'OnSearchReset' => Array('self' => true, 'subitem' => true),
'OnGoBack' => Array('self' => true, 'subitem' => true),
// it checks permission itself since flash uploader does not send cookies
'OnUploadFile' => Array ('self' => true, 'subitem' => true),
'OnDeleteFile' => Array ('self' => true, 'subitem' => true),
'OnViewFile' => Array ('self' => true, 'subitem' => true),
'OnSaveWidths' => Array ('self' => true, 'subitem' => true),
'OnValidateMInputFields' => Array ('self' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function mapEvents()
{
$events_map = Array(
'OnRemoveFilters' => 'FilterAction',
'OnApplyFilters' => 'FilterAction',
'OnMassApprove'=>'iterateItems',
'OnMassDecline'=>'iterateItems',
'OnMassMoveUp'=>'iterateItems',
'OnMassMoveDown'=>'iterateItems',
);
$this->eventMethods = array_merge($this->eventMethods, $events_map);
}
/**
* Returns ID of current item to be edited
* by checking ID passed in get/post as prefix_id
* or by looking at first from selected ids, stored.
* Returned id is also stored in Session in case
* it was explicitly passed as get/post
*
* @param kEvent $event
* @return int
*/
function getPassedID(&$event)
{
if ($event->getEventParam('raise_warnings') === false) {
$event->setEventParam('raise_warnings', 1);
}
if (preg_match('/^auto-(.*)/', $event->Special, $regs) && $this->Application->prefixRegistred($regs[1])) {
// <inp2:lang.auto-phrase_Field name="DateFormat"/> - returns field DateFormat value from language (LanguageId is extracted from current phrase object)
$main_object =& $this->Application->recallObject($regs[1]);
/* @var $main_object kDBItem */
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
return $main_object->GetDBField($id_field);
}
// 1. get id from post (used in admin)
$ret = $this->Application->GetVar($event->getPrefixSpecial(true).'_id');
if (($ret !== false) && ($ret != '')) {
return $ret;
}
// 2. get id from env (used in front)
$ret = $this->Application->GetVar($event->getPrefixSpecial().'_id');
if (($ret !== false) && ($ret != '')) {
return $ret;
}
// recall selected ids array and use the first one
$ids = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids');
if ($ids != '') {
$ids = explode(',',$ids);
if ($ids) {
$ret = array_shift($ids);
}
}
else { // if selected ids are not yet stored
$this->StoreSelectedIDs($event);
return $this->Application->GetVar($event->getPrefixSpecial().'_id'); // StoreSelectedIDs sets this variable
}
return $ret;
}
/**
* Prepares and stores selected_ids string
* in Session and Application Variables
* by getting all checked ids from grid plus
* id passed in get/post as prefix_id
*
* @param kEvent $event
* @param Array $direct_ids
*
* @return Array ids stored
*/
function StoreSelectedIDs(&$event, $direct_ids = null)
{
$wid = $this->Application->GetTopmostWid($event->Prefix);
$session_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = $event->getEventParam('ids');
if (isset($direct_ids) || ($ids !== false)) {
// save ids directly if they given + reset array indexes
$resulting_ids = $direct_ids ? array_values($direct_ids) : ($ids ? array_values($ids) : false);
if ($resulting_ids) {
$this->Application->SetVar($event->getPrefixSpecial() . '_selected_ids', implode(',', $resulting_ids));
$this->Application->LinkVar($event->getPrefixSpecial() . '_selected_ids', $session_name, '', true);
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $resulting_ids[0]);
return $resulting_ids;
}
return Array ();
}
$ret = Array();
// May be we don't need this part: ?
$passed = $this->Application->GetVar($event->getPrefixSpecial(true).'_id');
if($passed !== false && $passed != '')
{
array_push($ret, $passed);
}
$ids = Array();
// get selected ids from post & save them to session
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
$id_field = $this->Application->getUnitOption($event->Prefix,'IDField');
foreach($items_info as $id => $field_values)
{
if( getArrayValue($field_values,$id_field) ) array_push($ids,$id);
}
//$ids=array_keys($items_info);
}
$ret = array_unique(array_merge($ret, $ids));
$this->Application->SetVar($event->getPrefixSpecial().'_selected_ids', implode(',',$ret));
$this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids', $session_name, '', !$ret); // optional when IDs are missing
// This is critical - otherwise getPassedID will return last ID stored in session! (not exactly true)
// this smells... needs to be refactored
$first_id = getArrayValue($ret,0);
if (($first_id === false) && ($event->getEventParam('raise_warnings') == 1)) {
if ( $this->Application->isDebugMode() ) {
$this->Application->Debugger->appendTrace();
}
trigger_error('Requested ID for prefix <strong>' . $event->getPrefixSpecial() . '</strong> <span class="debug_error">not passed</span>', E_USER_NOTICE);
}
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $first_id);
return $ret;
}
/**
* Returns stored selected ids as an array
*
* @param kEvent $event
* @param bool $from_session return ids from session (written, when editing was started)
* @return array
*/
function getSelectedIDs(&$event, $from_session = false)
{
if ($from_session) {
$wid = $this->Application->GetTopmostWid($event->Prefix);
$var_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ret = $this->Application->RecallVar($var_name);
}
else {
$ret = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids');
}
return explode(',', $ret);
}
/**
* Stores IDs, selected in grid in session
*
* @param kEvent $event
*/
function OnStoreSelected(&$event)
{
$this->StoreSelectedIDs($event);
$id = $this->Application->GetVar($event->getPrefixSpecial() . '_id');
if ($id !== false) {
$event->SetRedirectParam($event->getPrefixSpecial() . '_id', $id);
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
}
}
/**
* Returs associative array of submitted fields for current item
* Could be used while creating/editing single item -
* meaning on any edit form, except grid edit
*
* @param kEvent $event
*/
function getSubmittedFields(&$event)
{
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
$field_values = $items_info ? array_shift($items_info) : Array();
return $field_values;
}
/**
* Removes any information about current/selected ids
* from Application variables and Session
*
* @param kEvent $event
*/
function clearSelectedIDs(&$event)
{
$prefix_special = $event->getPrefixSpecial();
$ids = implode(',', $this->getSelectedIDs($event, true));
$event->setEventParam('ids', $ids);
$wid = $this->Application->GetTopmostWid($event->Prefix);
$session_name = rtrim($prefix_special.'_selected_ids_'.$wid, '_');
$this->Application->RemoveVar($session_name);
$this->Application->SetVar($prefix_special.'_selected_ids', '');
$this->Application->SetVar($prefix_special.'_id', ''); // $event->getPrefixSpecial(true).'_id' too may be
}
/**
* Common builder part for Item & List
*
* @param kDBBase $object
* @param kEvent $event
* @access private
*/
function dbBuild(&$object, &$event)
{
// for permission checking inside item/list build events
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
- $object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields') );
+ if ( $event->getEventParam('form_name') !== false ) {
+ $form_name = $event->getEventParam('form_name');
+ }
+ else {
+ $request_forms = $this->Application->GetVar('forms', Array ());
+ $form_name = (string)getArrayValue( $request_forms, $object->getPrefixSpecial() );
+ }
+
+ $object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields'), $form_name );
$this->PrepareObject($object, $event);
// force live table if specified or is original item
$live_table = $event->getEventParam('live_table') || $event->Special == 'original';
if( $this->UseTempTables($event) && !$live_table )
{
$object->SwitchToTemp();
}
$this->Application->setEvent($event->getPrefixSpecial(), '');
$save_event = $this->UseTempTables($event) && $this->Application->GetTopmostPrefix($event->Prefix) == $event->Prefix ? 'OnSave' : 'OnUpdate';
$this->Application->SetVar($event->getPrefixSpecial().'_SaveEvent',$save_event);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
$status_fields = $this->Application->getUnitOption($event->Prefix,'StatusField');
if (!$status_fields) {
return true;
}
$status_field = array_shift($status_fields);
if ($status_field == 'Status' || $status_field == 'Enabled') {
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
return $object->GetDBField($status_field) == STATUS_ACTIVE;
}
return true;
}
/**
* Shows not found template content
*
* @param kEvent $event
*
*/
function _errorNotFound(&$event)
{
if ($event->getEventParam('raise_warnings') === 0) {
// when it's possible, that autoload fails do nothing
return ;
}
if ( $this->Application->isDebugMode() ) {
$this->Application->Debugger->appendTrace();
}
trigger_error('ItemLoad Permission Failed for prefix [' . $event->getPrefixSpecial() . '] in <strong>checkItemStatus</strong>, leading to "404 Not Found"', E_USER_NOTICE);
header('HTTP/1.0 404 Not Found');
while (ob_get_level()) {
ob_end_clean();
}
// object is used inside template parsing, so break out any parsing and return error document
$error_template = $this->Application->ConfigValue('ErrorTemplate');
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$this->Application->SetVar('t', $error_template);
$this->Application->SetVar('m_cat_id', $themes_helper->getPageByTemplate($error_template));
// in case if missing item is recalled first from event (not from template)
$this->Application->InitParser();
$this->Application->HTML = $this->Application->ParseBlock( Array ('name' => $error_template) );
$this->Application->Done();
exit;
}
/**
* Builds item (loads if needed)
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
function OnItemBuild(&$event)
{
$object =& $event->getObject();
- $this->dbBuild($object,$event);
+ /* @var $object kDBItem */
+
+ $this->dbBuild($object, $event);
$sql = $this->ItemPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
// 2. loads if allowed
$auto_load = $this->Application->getUnitOption($event->Prefix,'AutoLoad');
$skip_autload = $event->getEventParam('skip_autoload');
if ($auto_load && !$skip_autload) {
$perm_status = true;
$user_id = $this->Application->RecallVar('user_id');
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
$status_checked = false;
if ($user_id == USER_ROOT || $this->CheckPermission($event)) {
// don't autoload item, when user doesn't have view permission
$this->LoadItem($event);
$status_checked = true;
$editing_mode = defined('EDITING_MODE') ? EDITING_MODE : false;
if ($user_id != USER_ROOT && !$this->Application->isAdmin && !($editing_mode || $this->checkItemStatus($event))) {
// non-root user AND on front-end AND (not editing mode || incorrect status)
$perm_status = false;
}
}
else {
$perm_status = false;
}
if (!$perm_status) {
// when no permission to view item -> redirect to no pemrission template
if ( $this->Application->isDebugMode() ) {
$this->Application->Debugger->appendTrace();
}
trigger_error('ItemLoad Permission Failed for prefix ['.$event->getPrefixSpecial().'] in <strong>'.($status_checked ? 'checkItemStatus' : 'CheckPermission').'</strong>', E_USER_NOTICE);
$template = $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
if (MOD_REWRITE) {
$redirect_params = Array (
'm_cat_id' => 0,
'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']),
);
}
else {
$redirect_params = Array (
'next_template' => $this->Application->GetVar('t'),
);
}
$this->Application->Redirect($template, $redirect_params);
}
}
$actions =& $this->Application->recallObject('kActions');
- $actions->Set($event->getPrefixSpecial().'_GoTab', '');
+ /* @var $actions Params */
+ $actions->Set($event->getPrefixSpecial().'_GoTab', '');
$actions->Set($event->getPrefixSpecial().'_GoId', '');
+ $actions->Set('forms[' . $event->getPrefixSpecial() . ']', $object->getFormName());
}
/**
* Build subtables array from configs
*
* @param kEvent $event
*/
function OnTempHandlerBuild(&$event)
{
$object =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $object kTempTablesHandler */
$object->BuildTables( $event->Prefix, $this->getSelectedIDs($event) );
}
/**
* Checks, that object used in event should use temp tables
*
* @param kEvent $event
* @return bool
*/
function UseTempTables(&$event)
{
$top_prefix = $this->Application->GetTopmostPrefix($event->Prefix); // passed parent, not always actual
$special = ($top_prefix == $event->Prefix) ? $event->Special : $this->getMainSpecial($event);
return $this->Application->IsTempMode($event->Prefix, $special);
}
/**
* Returns table prefix from event (temp or live)
*
* @param kEvent $event
* @return string
* @todo Needed? Should be refactored (by Alex)
*/
function TablePrefix(&$event)
{
return $this->UseTempTables($event) ? $this->Application->GetTempTablePrefix('prefix:'.$event->Prefix).TABLE_PREFIX : TABLE_PREFIX;
}
/**
* Load item if id is available
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function LoadItem(&$event)
+ protected function LoadItem(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $this->getPassedID($event);
- if ($object->isLoaded() && !is_array($id) && ($object->GetID() == $id)) {
+ if ( $object->isLoaded() && !is_array($id) && ($object->GetID() == $id) ) {
// object is already loaded by same id
return ;
}
- if ($object->Load($id)) {
+ if ( $object->Load($id) ) {
$actions =& $this->Application->recallObject('kActions');
- $actions->Set($event->getPrefixSpecial().'_id', $object->GetID() );
+ /* @var $actions Params */
+
+ $actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$object->setID($id);
}
}
/**
* Builds list
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
function OnListBuild(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
- $this->dbBuild($object,$event);
+ $this->dbBuild($object, $event);
- if (!$object->isMainList() && $event->getEventParam('main_list')) {
+ if ( !$object->isMainList() && $event->getEventParam('main_list') ) {
// once list is set to main, then even "requery" parameter can't remove that
/*$passed = $this->Application->GetVar('passed');
$this->Application->SetVar('passed', $passed . ',' . $event->Prefix);*/
$object->becameMain();
}
- $object->setGridName( $event->getEventParam('grid') );
+ $object->setGridName($event->getEventParam('grid'));
$sql = $this->ListPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
$object->reset();
$object->linkToParent( $this->getMainSpecial($event) );
$this->AddFilters($event);
- $this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex.
+ $this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex.
$this->SetPagination($event);
$this->SetSorting($event);
$actions =& $this->Application->recallObject('kActions');
- $actions->Set('remove_specials['.$event->getPrefixSpecial().']', '0');
- $actions->Set($event->getPrefixSpecial().'_GoTab', '');
+ /* @var $actions Params */
+
+ $actions->Set('remove_specials[' . $event->getPrefixSpecial() . ']', '0');
+ $actions->Set($event->getPrefixSpecial() . '_GoTab', '');
}
/**
* Get's special of main item for linking with subitem
*
* @param kEvent $event
* @return string
*/
function getMainSpecial(&$event)
{
$main_special = $event->getEventParam('main_special');
if ($main_special === false) {
// main item's special not passed
if (substr($event->Special, -5) == '-item') {
// temp handler added "-item" to given special -> process that here
return substr($event->Special, 0, -5);
}
// by default subitem's special is used for main item searching
return $event->Special;
}
return $main_special;
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
+ * @return void
* @access protected
- * @see OnListBuild
+ * @see kDBEventHandler::OnListBuild()
*/
- function SetCustomQuery(&$event)
+ protected function SetCustomQuery(&$event)
{
}
/**
* Set's new perpage for grid
*
* @param kEvent $event
*/
function OnSetPerPage(&$event)
{
$per_page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_PerPage');
$event->SetRedirectParam($event->getPrefixSpecial() . '_PerPage', $per_page);
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
if (!$this->Application->isAdminUser) {
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$this->_passListParams($event, 'per_page');
/*if ($per_page != $list_helper->getDefaultPerPage($event->Prefix)) {
$event->SetRedirectParam('per_page', $per_page);
}*/
}
}
/**
* Occurs when page is changed (only for hooking)
*
* @param kEvent $event
*/
function OnSetPage(&$event)
{
$page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_Page');
$event->SetRedirectParam($event->getPrefixSpecial() . '_Page', $page);
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
if (!$this->Application->isAdminUser) {
/*if ($page > 1) {
$event->SetRedirectParam('page', $page);
}*/
$this->_passListParams($event, 'page');
}
}
/**
* Passes through main list pagination and sorting
*
* @param kEvent $event
* @param string $skip_var
*/
function _passListParams(&$event, $skip_var)
{
$param_names = array_diff(Array ('page', 'per_page', 'sort_by'), Array ($skip_var));
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
foreach ($param_names as $param_name) {
$value = $this->Application->GetVar($param_name);
switch ($param_name) {
case 'page':
if ($value > 1) {
$event->SetRedirectParam('page', $value);
}
break;
case 'per_page':
if ($value > 0) {
if ($value != $list_helper->getDefaultPerPage($event->Prefix)) {
$event->SetRedirectParam('per_page', $value);
}
}
break;
case 'sort_by':
$event->setPseudoClass('_List');
$object =& $event->getObject( Array ('main_list' => 1) );
/* @var $object kDBList */
if ($list_helper->hasUserSorting($object)) {
$event->SetRedirectParam('sort_by', $value);
}
break;
}
}
}
/**
* Set's correct page for list
* based on data provided with event
*
* @param kEvent $event
* @access private
* @see OnListBuild
*/
function SetPagination(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
// get PerPage (forced -> session -> config -> 10)
$object->SetPerPage( $this->getPerPage($event) );
// main lists on Front-End have special get parameter for page
$page = $object->isMainList() ? $this->Application->GetVar('page') : false;
if (!$page) {
// page is given in "env" variable for given prefix
$page = $this->Application->GetVar($event->getPrefixSpecial() . '_Page');
}
if (!$page && $event->Special) {
// when not part of env, then variables like "prefix.special_Page" are
// replaced (by PHP) with "prefix_special_Page", so check for that too
$page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_Page');
}
if (!$object->isMainList()) {
// main lists doesn't use session for page storing
$this->Application->StoreVarDefault($event->getPrefixSpecial() . '_Page', 1, true); // true for optional
if ($page) {
// page found in request -> store in session
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', $page, true); //true for optional
}
else {
// page not found in request -> get from session
$page = $this->Application->RecallVar($event->getPrefixSpecial() . '_Page');
}
if ( !$event->getEventParam('skip_counting') ) {
// when stored page is larger, then maximal list page number
// (such case is also processed in kDBList::Query method)
$pages = $object->GetTotalPages();
if ($page > $pages) {
$page = 1;
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', 1, true);
}
}
}
$object->SetPage($page);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
*/
function getPerPage(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
$per_page = $event->getEventParam('per_page');
if ($per_page) {
// per-page is passed as tag parameter to PrintList, InitList, etc.
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
// 2. per-page setting is stored in configuration variable
if ($config_mapping) {
// such pseudo per-pages are only defined in templates directly
switch ($per_page) {
case 'short_list':
$per_page = $this->Application->ConfigValue($config_mapping['ShortListPerPage']);
break;
case 'default':
$per_page = $this->Application->ConfigValue($config_mapping['PerPage']);
break;
}
}
return $per_page;
}
if (!$per_page && $object->isMainList()) {
// main lists on Front-End have special get parameter for per-page
$per_page = $this->Application->GetVar('per_page');
}
if (!$per_page) {
// per-page is given in "env" variable for given prefix
$per_page = $this->Application->GetVar($event->getPrefixSpecial() . '_PerPage');
}
if (!$per_page && $event->Special) {
// when not part of env, then variables like "prefix.special_PerPage" are
// replaced (by PHP) with "prefix_special_PerPage", so check for that too
$per_page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_PerPage');
}
if (!$object->isMainList()) {
// per-page given in env and not in main list
$view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
if ($per_page) {
// per-page found in request -> store in session and persistent session
$this->setListSetting($event, 'PerPage', $per_page);
}
else {
// per-page not found in request -> get from pesistent session (or session)
$per_page = $this->getListSetting($event, 'PerPage');
}
}
if (!$per_page) {
// per page wan't found in request/session/persistent session
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
// allow to override default per-page value from tag
$default_per_page = $event->getEventParam('default_per_page');
if (!is_numeric($default_per_page)) {
$default_per_page = 10;
}
$per_page = $list_helper->getDefaultPerPage($event->Prefix, $default_per_page);
}
return $per_page;
}
/**
* Set's correct sorting for list
* based on data provided with event
*
* @param kEvent $event
* @access private
* @see OnListBuild
*/
function SetSorting(&$event)
{
$event->setPseudoClass('_List');
$object =& $event->getObject();
/* @var $object kDBList */
if ($object->isMainList()) {
$sort_by = $this->Application->GetVar('sort_by');
$cur_sort1 = $cur_sort1_dir = $cur_sort2 = $cur_sort2_dir = false;
if ($sort_by) {
list ($cur_sort1, $cur_sort1_dir) = explode(',', $sort_by);
}
}
else {
$cur_sort1 = $this->getListSetting($event, 'Sort1');
$cur_sort1_dir = $this->getListSetting($event, 'Sort1_Dir');
$cur_sort2 = $this->getListSetting($event, 'Sort2');
$cur_sort2_dir = $this->getListSetting($event, 'Sort2_Dir');
}
$tag_sort_by = $event->getEventParam('sort_by');
if ($tag_sort_by) {
if ($tag_sort_by == 'random') {
$object->AddOrderField('RAND()', '');
}
else {
// multiple sortings could be specified at once
$tag_sort_by = explode('|', $tag_sort_by);
foreach ($tag_sort_by as $sorting_element) {
list ($by, $dir) = explode(',', $sorting_element);
$object->AddOrderField($by, $dir);
}
}
}
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings', Array ());
$sorting_prefix = array_key_exists($event->Special, $list_sortings) ? $event->Special : '';
$sorting_configs = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
if ($sorting_configs && array_key_exists('DefaultSorting1Field', $sorting_configs)) {
// sorting defined in configuration variables overrides one from unit config
$list_sortings[$sorting_prefix]['Sorting'] = Array (
$this->Application->ConfigValue($sorting_configs['DefaultSorting1Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting1Dir']),
$this->Application->ConfigValue($sorting_configs['DefaultSorting2Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting2Dir']),
);
}
// use default if not specified in session
if (!$cur_sort1 || !$cur_sort1_dir) {
$sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting');
if ($sorting) {
reset($sorting);
$cur_sort1 = key($sorting);
$cur_sort1_dir = current($sorting);
if (next($sorting)) {
$cur_sort2 = key($sorting);
$cur_sort2_dir = current($sorting);
}
}
}
- // always add forced sorting before any user sortings
+ // always add forced sorting before any user sorting fields
$forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting');
-
+ /* @var $forced_sorting Array */
+
if ($forced_sorting) {
foreach ($forced_sorting as $field => $dir) {
$object->AddOrderField($field, $dir);
}
}
- // add user sortings
+ // add user sorting fields
if ($cur_sort1 != '' && $cur_sort1_dir != '') {
$object->AddOrderField($cur_sort1, $cur_sort1_dir);
}
if ($cur_sort2 != '' && $cur_sort2_dir != '') {
$object->AddOrderField($cur_sort2, $cur_sort2_dir);
}
}
/**
* Gets list setting by name (persistent or real session)
*
* @param kEvent $event
* @param string $variable_name
* @return string
*/
function getListSetting(&$event, $variable_name)
{
$view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
$storage_prefix = $event->getEventParam('same_special') ? $event->Prefix : $event->getPrefixSpecial();
// get sorting from pesistent session
$variable_value = $this->Application->RecallPersistentVar($storage_prefix . '_' . $variable_name . '.' . $view_name, ALLOW_DEFAULT_SETTINGS);
/*if (!$variable_value) {
// get sorting from session
$variable_value = $this->Application->RecallVar($storage_prefix . '_' . $variable_name);
}*/
return $variable_value;
}
/**
* Sets list setting by name (persistent and real session)
*
* @param kEvent $event
* @param string $variable_name
* @param string $variable_value
*/
function setListSetting(&$event, $variable_name, $variable_value = null)
{
$view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
// $this->Application->StoreVar($event->getPrefixSpecial() . '_' . $variable_name, $variable_value, true); //true for optional
if ( isset($variable_value) ) {
$this->Application->StorePersistentVar($event->getPrefixSpecial() . '_' . $variable_name . '.' . $view_name, $variable_value, true); //true for optional
}
else {
$this->Application->RemovePersistentVar($event->getPrefixSpecial() . '_' . $variable_name . '.' . $view_name);
}
}
/**
* Add filters found in session
*
* @param kEvent $event
*/
function AddFilters(&$event)
{
$object =& $event->getObject();
+ /* @var $object kDBList */
- $edit_mark = rtrim($this->Application->GetSID().'_'.$this->Application->GetTopmostWid($event->Prefix), '_');
+ $edit_mark = rtrim($this->Application->GetSID() . '_' . $this->Application->GetTopmostWid($event->Prefix), '_');
// add search filter
- $filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter');
- if ($filter_data) {
+ $filter_data = $this->Application->RecallVar($event->getPrefixSpecial() . '_search_filter');
+
+ if ( $filter_data ) {
$filter_data = unserialize($filter_data);
+
foreach ($filter_data as $filter_field => $filter_params) {
$filter_type = ($filter_params['type'] == 'having') ? kDBList::HAVING_FILTER : kDBList::WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $filter_params['value']);
$object->addFilter($filter_field, $filter_value, $filter_type, kDBList::FLT_SEARCH);
}
}
// add custom filter
- $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
- $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name);
- if ($custom_filters) {
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
+ $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial() . '_custom_filter.' . $view_name);
+
+ if ( $custom_filters ) {
$grid_name = $event->getEventParam('grid');
$custom_filters = unserialize($custom_filters);
- if (isset($custom_filters[$grid_name])) {
+
+ if ( isset($custom_filters[$grid_name]) ) {
foreach ($custom_filters[$grid_name] as $field_name => $field_options) {
list ($filter_type, $field_options) = each($field_options);
- if (isset($field_options['value']) && $field_options['value']) {
+
+ if ( isset($field_options['value']) && $field_options['value'] ) {
$filter_type = ($field_options['sql_filter_type'] == 'having') ? kDBList::HAVING_FILTER : kDBList::WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $field_options['value']);
$object->addFilter($field_name, $filter_value, $filter_type, kDBList::FLT_CUSTOM);
}
}
}
}
- $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
- if($view_filter)
- {
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial() . '_view_filter');
+
+ if ( $view_filter ) {
$view_filter = unserialize($view_filter);
+
$temp_filter =& $this->Application->makeClass('kMultipleFilter');
- $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
+ /* @var $temp_filter kMultipleFilter */
+
+ $filter_menu = $this->Application->getUnitOption($event->Prefix, 'FilterMenu');
- $group_key = 0; $group_count = count($filter_menu['Groups']);
- while($group_key < $group_count)
- {
+ $group_key = 0;
+ $group_count = count($filter_menu['Groups']);
+
+ while ( $group_key < $group_count ) {
$group_info = $filter_menu['Groups'][$group_key];
- $temp_filter->setType( constant('kDBList::FLT_TYPE_'.$group_info['mode']) );
+ $temp_filter->setType(constant('kDBList::FLT_TYPE_' . $group_info['mode']));
$temp_filter->clearFilters();
- foreach ($group_info['filters'] as $flt_id)
- {
- $sql_key = getArrayValue($view_filter,$flt_id) ? 'on_sql' : 'off_sql';
- if ($filter_menu['Filters'][$flt_id][$sql_key] != '')
- {
- $temp_filter->addFilter('view_filter_'.$flt_id, $filter_menu['Filters'][$flt_id][$sql_key]);
+
+ foreach ($group_info['filters'] as $flt_id) {
+ $sql_key = getArrayValue($view_filter, $flt_id) ? 'on_sql' : 'off_sql';
+
+ if ( $filter_menu['Filters'][$flt_id][$sql_key] != '' ) {
+ $temp_filter->addFilter('view_filter_' . $flt_id, $filter_menu['Filters'][$flt_id][$sql_key]);
}
}
- $object->addFilter('view_group_'.$group_key, $temp_filter, $group_info['type'] , kDBList::FLT_VIEW);
+
+ $object->addFilter('view_group_' . $group_key, $temp_filter, $group_info['type'], kDBList::FLT_VIEW);
$group_key++;
}
}
}
/**
* Set's new sorting for list
*
* @param kEvent $event
* @access protected
*/
function OnSetSorting(&$event)
{
$cur_sort1 = $this->getListSetting($event, 'Sort1');
$cur_sort1_dir = $this->getListSetting($event, 'Sort1_Dir');
$use_double_sorting = $this->Application->ConfigValue('UseDoubleSorting');
if ($use_double_sorting) {
$cur_sort2 = $this->getListSetting($event, 'Sort2');
$cur_sort2_dir = $this->getListSetting($event, 'Sort2_Dir');
}
$passed_sort1 = $this->Application->GetVar($event->getPrefixSpecial(true) . '_Sort1');
if ($cur_sort1 == $passed_sort1) {
$cur_sort1_dir = $cur_sort1_dir == 'asc' ? 'desc' : 'asc';
}
else {
if ($use_double_sorting) {
$cur_sort2 = $cur_sort1;
$cur_sort2_dir = $cur_sort1_dir;
}
$cur_sort1 = $passed_sort1;
$cur_sort1_dir = 'asc';
}
$this->setListSetting($event, 'Sort1', $cur_sort1);
$this->setListSetting($event, 'Sort1_Dir', $cur_sort1_dir);
if ($use_double_sorting) {
$this->setListSetting($event, 'Sort2', $cur_sort2);
$this->setListSetting($event, 'Sort2_Dir', $cur_sort2_dir);
}
}
/**
* Set sorting directly to session (used for category item sorting (front-end), grid sorting (admin, view menu)
*
* @param kEvent $event
*/
function OnSetSortingDirect(&$event)
{
// used on Front-End in category item lists
$prefix_special = $event->getPrefixSpecial();
$combined = $this->Application->GetVar($event->getPrefixSpecial(true) . '_CombinedSorting');
if ($combined) {
list ($field, $dir) = explode('|', $combined);
if ($this->Application->isAdmin || !$this->Application->GetVar('main_list')) {
$this->setListSetting($event, 'Sort1', $field);
$this->setListSetting($event, 'Sort1_Dir', $dir);
}
else {
$event->setPseudoClass('_List');
$this->Application->SetVar('sort_by', $field . ',' . $dir);
$object =& $event->getObject( Array ('main_list' => 1) );
/* @var $object kDBList */
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$this->_passListParams($event, 'sort_by');
if ($list_helper->hasUserSorting($object)) {
$event->SetRedirectParam('sort_by', $field . ',' . strtolower($dir));
}
$event->SetRedirectParam('pass', 'm');
}
return ;
}
// used in "View Menu -> Sort" menu in administrative console
$field_pos = $this->Application->GetVar($event->getPrefixSpecial(true) . '_SortPos');
$this->Application->LinkVar($event->getPrefixSpecial(true) . '_Sort' . $field_pos, $prefix_special . '_Sort' . $field_pos);
$this->Application->LinkVar($event->getPrefixSpecial(true) . '_Sort' . $field_pos . '_Dir', $prefix_special . '_Sort' . $field_pos . '_Dir');
}
/**
* Reset grid sorting to default (from config)
*
* @param kEvent $event
*/
function OnResetSorting(&$event)
{
$this->setListSetting($event, 'Sort1');
$this->setListSetting($event, 'Sort1_Dir');
$this->setListSetting($event, 'Sort2');
$this->setListSetting($event, 'Sort2_Dir');
}
/**
* Sets grid refresh interval
*
* @param kEvent $event
*/
function OnSetAutoRefreshInterval(&$event)
{
$refresh_interval = $this->Application->GetVar('refresh_interval');
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_interval);
}
/**
* Changes auto-refresh state for grid
*
* @param kEvent $event
*/
function OnAutoRefreshToggle(&$event)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
if (!$refresh_intervals) {
return ;
}
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$auto_refresh = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name);
if ($auto_refresh === false) {
$refresh_intervals = explode(',', $refresh_intervals);
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_intervals[0]);
}
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name, $auto_refresh ? 0 : 1);
}
/**
* Creates needed sql query to load item,
* if no query is defined in config for
* special requested, then use default
* query
*
* @param kEvent $event
* @access protected
*/
function ItemPrepareQuery(&$event)
{
- $sqls = $this->Application->getUnitOption($event->Prefix, 'ItemSQLs', Array ());
- $special = array_key_exists($event->Special, $sqls) ? $event->Special : '';
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
- if (!array_key_exists($special, $sqls)) {
- // preferred special not found in ItemSQLs -> use analog from ListSQLs
- return $this->ListPrepareQuery($event);
- }
+ $sqls = $object->getFormOption('ItemSQLs', Array ());
+ $special = isset($sqls[$event->Special]) ? $event->Special : '';
- return $sqls[$special];
+ // preferred special not found in ItemSQLs -> use analog from ListSQLs
+
+ return isset($sqls[$special]) ? $sqls[$special] : $this->ListPrepareQuery($event);
}
/**
* Creates needed sql query to load list,
* if no query is defined in config for
* special requested, then use default
* query
*
* @param kEvent $event
* @access protected
*/
function ListPrepareQuery(&$event)
{
- $sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs', Array ());
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $sqls = $object->getFormOption('ListSQLs', Array ());
+
return $sqls[ array_key_exists($event->Special, $sqls) ? $event->Special : '' ];
}
/**
* Apply custom processing to item
*
* @param kEvent $event
+ * @param string $type
+ * @return void
+ * @access protected
*/
- function customProcessing(&$event, $type)
+ protected function customProcessing(&$event, $type)
{
}
/* Edit Events mostly used in Admin */
/**
* Creates new kDBItem
*
* @param kEvent $event
* @access protected
*/
function OnCreate(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
list($id,$field_values) = each($items_info);
$object->SetFieldsFromHash($field_values);
}
$this->customProcessing($event,'before');
//look at kDBItem' Create for ForceCreateId description, it's rarely used and is NOT set by default
if ( $object->Create($event->getEventParam('ForceCreateId')) ) {
$this->customProcessing($event,'after');
$event->status=kEvent::erSUCCESS;
$event->setRedirectParams(Array('opener'=>'u'), true);
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
$this->Application->SetVar($event->getPrefixSpecial().'_SaveEvent','OnCreate');
$object->setID($id);
}
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @access protected
*/
function OnUpdate(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
+
+ if ( $items_info ) {
foreach ($items_info as $id => $field_values) {
$object->Load($id);
- $object->SetFieldsFromHash($field_values);
- $this->customProcessing($event, 'before');
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
if ( $object->Update($id) ) {
$this->customProcessing($event, 'after');
$event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Delete's kDBItem object
*
* @param kEvent $event
* @access protected
*/
function OnDelete(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
$temp->DeleteItems($event->Prefix, $event->Special, Array($this->getPassedID($event)));
}
/**
* Deletes all records from table
*
* @param kEvent $event
*/
function OnDeleteAll(&$event)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName');
$ids = $this->Conn->GetCol($sql);
if ($ids) {
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
}
}
/**
* Prepares new kDBItem object
*
* @param kEvent $event
* @access protected
*/
function OnNew(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$object->Clear(0);
$this->Application->SetVar($event->getPrefixSpecial().'_SaveEvent', 'OnCreate');
if ($event->getEventParam('top_prefix') != $event->Prefix) {
// this is subitem prefix, so use main item special
$table_info = $object->getLinkedInfo( $this->getMainSpecial($event) );
}
else {
$table_info = $object->getLinkedInfo();
}
$object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']);
$event->redirect = false;
}
/**
- * Cancel's kDBItem Editing/Creation
+ * Cancels kDBItem Editing/Creation
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnCancel(&$event)
+ protected function OnCancel(&$event)
{
- $object =& $event->getObject(Array('skip_autoload' => true));
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- if ($items_info) {
- $delete_ids = Array();
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ if ( $items_info ) {
+ $delete_ids = Array ();
+
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
foreach ($items_info as $id => $field_values) {
$object->Load($id);
// record created for using with selector (e.g. Reviews->Select User), and not validated => Delete it
- if ($object->isLoaded() && !$object->Validate() && ($id <= 0) ) {
+ if ( $object->isLoaded() && !$object->Validate() && ($id <= 0) ) {
$delete_ids[] = $id;
}
}
- if ($delete_ids) {
- $temp->DeleteItems($event->Prefix, $event->Special, $delete_ids);
+ if ( $delete_ids ) {
+ $temp_handler->DeleteItems($event->Prefix, $event->Special, $delete_ids);
}
}
- $event->setRedirectParams(Array('opener'=>'u'), true);
+ $event->SetRedirectParam('opener', 'u');
}
-
/**
* Deletes all selected items.
* Automatically recurse into sub-items using temp handler, and deletes sub-items
* by calling its Delete method if sub-item has AutoDelete set to true in its config file
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnMassDelete(&$event)
+ protected function OnMassDelete(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $event->status=kEvent::erSUCCESS;
-
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
$ids = $this->StoreSelectedIDs($event);
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('ids');
- if($ids)
- {
- $temp->DeleteItems($event->Prefix, $event->Special, $ids);
+ if ( $ids ) {
+ $temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
}
+
$this->clearSelectedIDs($event);
}
/**
* Sets window id (of first opened edit window) to temp mark in uls
*
* @param kEvent $event
*/
function setTempWindowID(&$event)
{
$prefixes = Array ($event->Prefix, $event->getPrefixSpecial(true));
foreach ($prefixes as $prefix) {
$mode = $this->Application->GetVar($prefix . '_mode');
if ($mode == 't') {
$wid = $this->Application->GetVar('m_wid');
$this->Application->SetVar(str_replace('_', '.', $prefix) . '_mode', 't' . $wid);
break;
}
}
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
*/
function OnEdit(&$event)
{
$this->setTempWindowID($event);
$ids = $this->StoreSelectedIDs($event);
$this->Application->RemoveVar( $this->_getPendingActionVariableName($event) );
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$this->Application->RemoveVar($changes_var_name);
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
$temp->PrepareEdit();
$event->SetRedirectParam('m_lang', $this->Application->GetDefaultLanguageId());
$event->SetRedirectParam($event->getPrefixSpecial() . '_id', array_shift($ids));
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
}
/**
* Saves content of temp table into live and
* redirects to event' default redirect (normally grid template)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnSave(&$event)
+ protected function OnSave(&$event)
{
$event->CallSubEvent('OnPreSave');
- if ($event->status == kEvent::erSUCCESS) {
- $skip_master = false;
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $changes_var_name = $this->Prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix);
+ if ($event->status != kEvent::erSUCCESS) {
+ return ;
+ }
- if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
- $live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array());
- if ($live_ids === false) {
- // coping from table failed, because we have another coping process to same table, that wasn't finished
- $event->status = kEvent::erFAIL;
- return ;
- }
+ $skip_master = false;
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
- if ($live_ids) {
- // ensure, that newly created item ids are avalable as if they were selected from grid
- // NOTE: only works if main item has subitems !!!
- $this->StoreSelectedIDs($event, $live_ids);
- }
+ $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
- $object =& $event->getObject();
- /* @var $object kDBItem */
+ if ( !$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
+ $live_ids = $temp_handler->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array ());
- $this->SaveLoggedChanges($changes_var_name, $object->ShouldLogChanges());
- }
- else {
+ if ( $live_ids === false ) {
+ // coping from table failed, because we have another coping process to same table, that wasn't finished
$event->status = kEvent::erFAIL;
+ return ;
}
- $this->clearSelectedIDs($event);
+ if ( $live_ids ) {
+ // ensure, that newly created item ids are available as if they were selected from grid
+ // NOTE: only works if main item has sub-items !!!
+ $this->StoreSelectedIDs($event, $live_ids);
+ }
- $event->setRedirectParams(Array('opener' => 'u'), true);
- $this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
- // all temp tables are deleted here => all after hooks should think, that it's live mode now
- $this->Application->SetVar($event->Prefix.'_mode', '');
+ $this->SaveLoggedChanges($changes_var_name, $object->ShouldLogChanges());
}
+ else {
+ $event->status = kEvent::erFAIL;
+ }
+
+ $this->clearSelectedIDs($event);
+
+ $event->setRedirectParams(Array ('opener' => 'u'), true);
+ $this->Application->RemoveVar($event->getPrefixSpecial() . '_modified');
+
+ // all temp tables are deleted here => all after hooks should think, that it's live mode now
+ $this->Application->SetVar($event->Prefix . '_mode', '');
}
function SaveLoggedChanges($changes_var_name, $save = true)
{
// 1. get changes, that were made
$changes = $this->Application->RecallVar($changes_var_name);
$changes = $changes ? unserialize($changes) : Array ();
$this->Application->RemoveVar($changes_var_name);
if (!$changes) {
// no changes, skip processing
return ;
}
// TODO: 2. optimize change log records (replace multiple changes to same record with one change record)
$to_increment = Array ();
// 3. collect serials to reset based on foreign keys
foreach ($changes as $index => $rec) {
if (array_key_exists('DependentFields', $rec)) {
foreach ($rec['DependentFields'] as $field_name => $field_value) {
// will be "ci|ItemResourceId:345"
$to_increment[] = $rec['Prefix'] . '|' . $field_name . ':' . $field_value;
// also reset sub-item prefix general serial
$to_increment[] = $rec['Prefix'];
}
unset($changes[$index]['DependentFields']);
}
unset($changes[$index]['ParentId'], $changes[$index]['ParentPrefix']);
}
// 4. collect serials to reset based on changed ids
foreach ($changes as $change) {
$to_increment[] = $change['MasterPrefix'] . '|' . $change['MasterId'];
if ($change['MasterPrefix'] != $change['Prefix']) {
// also reset sub-item prefix general serial
$to_increment[] = $change['Prefix'];
// will be "ci|ItemResourceId"
$to_increment[] = $change['Prefix'] . '|' . $change['ItemId'];
}
}
// 5. reset serials collected before
$to_increment = array_unique($to_increment);
$this->Application->incrementCacheSerial($this->Prefix);
foreach ($to_increment as $to_increment_mixed) {
if (strpos($to_increment_mixed, '|') !== false) {
list ($to_increment_prefix, $to_increment_id) = explode('|', $to_increment_mixed, 2);
$this->Application->incrementCacheSerial($to_increment_prefix, $to_increment_id);
}
else {
$this->Application->incrementCacheSerial($to_increment_mixed);
}
}
// save changes to database
$sesion_log_id = $this->Application->RecallVar('_SessionLogId_');
if (!$save || !$sesion_log_id) {
// saving changes to database disabled OR related session log missing
return ;
}
$add_fields = Array (
'PortalUserId' => $this->Application->RecallVar('user_id'),
'SessionLogId' => $sesion_log_id,
);
$change_log_table = $this->Application->getUnitOption('change-log', 'TableName');
foreach ($changes as $rec) {
$this->Conn->doInsert(array_merge($rec, $add_fields), $change_log_table);
}
$this->Application->incrementCacheSerial('change-log');
$sql = 'UPDATE ' . $this->Application->getUnitOption('session-log', 'TableName') . '
SET AffectedItems = AffectedItems + ' . count($changes) . '
WHERE SessionLogId = ' . $sesion_log_id;
$this->Conn->Query($sql);
$this->Application->incrementCacheSerial('session-log');
}
/**
* Cancels edit
* Removes all temp tables and clears selected ids
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCancelEdit(&$event)
+ protected function OnCancelEdit(&$event)
{
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp->CancelEdit();
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->CancelEdit();
$this->clearSelectedIDs($event);
- $event->setRedirectParams(Array('opener'=>'u'), true);
- $this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
+ $event->setRedirectParams(Array ('opener' => 'u'), true);
+ $this->Application->RemoveVar($event->getPrefixSpecial() . '_modified');
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$this->Application->RemoveVar($changes_var_name);
}
-
/**
* Allows to determine if we are creating new item or editing already created item
*
* @param kEvent $event
* @return bool
*/
function isNewItemCreate(&$event)
{
$object =& $event->getObject( Array ('raise_warnings' => 0) );
- return !$object->IsLoaded();
+ /* @var $object kDBItem */
-// $item_id = $this->getPassedID($event);
-// return ($item_id == '') ? true : false;
+ return !$object->isLoaded();
}
/**
* Saves edited item into temp table
* If there is no id, new item is created in temp table
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSave(&$event)
+ protected function OnPreSave(&$event)
{
- //$event->redirect = false;
// if there is no id - it means we need to create an item
- if (is_object($event->MasterEvent)) {
- $event->MasterEvent->setEventParam('IsNew',false);
+ if ( is_object($event->MasterEvent) ) {
+ $event->MasterEvent->setEventParam('IsNew', false);
}
- if ($this->isNewItemCreate($event)) {
+ if ( $this->isNewItemCreate($event) ) {
$event->CallSubEvent('OnPreSaveCreated');
- if (is_object($event->MasterEvent)) {
- $event->MasterEvent->setEventParam('IsNew',true);
+
+ if ( is_object($event->MasterEvent) ) {
+ $event->MasterEvent->setEventParam('IsNew', true);
}
- return;
+
+ return ;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
+ if ( $items_info ) {
foreach ($items_info as $id => $field_values) {
$object->Load($id);
- $object->SetFieldsFromHash($field_values);
- $this->customProcessing($event, 'before');
- if( $object->Update($id) )
- {
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
+
+ if ( $object->Update($id) ) {
$this->customProcessing($event, 'after');
- $event->status=kEvent::erSUCCESS;
+ $event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
}
/**
- * [HOOK] Saves subitem
+ * [HOOK] Saves sub-item
*
* @param kEvent $event
*/
function OnPreSaveSubItem(&$event)
{
$not_created = $this->isNewItemCreate($event);
$event->CallSubEvent($not_created ? 'OnCreate' : 'OnUpdate');
if ($event->status == kEvent::erSUCCESS) {
$object =& $event->getObject();
/* @var $object kDBItem */
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$event->MasterEvent->status = $event->status;
}
$event->SetRedirectParam('opener', 's');
}
/**
* Saves edited item in temp table and loads
* item with passed id in current template
* Used in Prev/Next buttons
*
* @param kEvent $event
*/
function OnPreSaveAndGo(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status == kEvent::erSUCCESS) {
$id = $this->Application->GetVar($event->getPrefixSpecial(true) . '_GoId');
$event->SetRedirectParam($event->getPrefixSpecial() . '_id', $id);
}
}
/**
* Saves edited item in temp table and goes
* to passed tabs, by redirecting to it with OnPreSave event
*
* @param kEvent $event
*/
function OnPreSaveAndGoToTab(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status==kEvent::erSUCCESS) {
$event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
}
}
/**
* Saves editable list and goes to passed tab,
* by redirecting to it with empty event
*
* @param kEvent $event
*/
function OnUpdateAndGoToTab(&$event)
{
$event->setPseudoClass('_List');
$event->CallSubEvent('OnUpdate');
if ($event->status==kEvent::erSUCCESS) {
$event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
}
}
/**
* Prepare temp tables for creating new item
* but does not create it. Actual create is
* done in OnPreSaveCreated
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreCreate(&$event)
+ protected function OnPreCreate(&$event)
{
$this->setTempWindowID($event);
$this->clearSelectedIDs($event);
$this->Application->SetVar('m_lang', $this->Application->GetDefaultLanguageId());
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
- $temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
- $temp->PrepareEdit();
+ $temp_handler =& $this->Application->recallObject($event->Prefix . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->PrepareEdit();
$object->setID(0);
- $this->Application->SetVar($event->getPrefixSpecial().'_id', 0);
- $this->Application->SetVar($event->getPrefixSpecial().'_PreCreate', 1);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_PreCreate', 1);
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$this->Application->RemoveVar($changes_var_name);
$event->redirect = false;
}
/**
* Creates a new item in temp table and
- * stores item id in App vars and Session on succsess
+ * stores item id in App vars and Session on success
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveCreated(&$event)
+ protected function OnPreSaveCreated(&$event)
{
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if($items_info) $field_values = array_shift($items_info);
-
$object =& $event->getObject( Array('skip_autoload' => true) );
- $object->SetFieldsFromHash($field_values);
+ /* @var $object kDBItem */
+
+ $object->SetFieldsFromHash( $this->getSubmittedFields($event) );
$this->customProcessing($event, 'before');
- if( $object->Create() )
- {
+ if ( $object->Create() ) {
$this->customProcessing($event, 'after');
- $event->SetRedirectParam($event->getPrefixSpecial(true).'_id', $object->GetId());
- $event->status=kEvent::erSUCCESS;
+ $event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $object->GetID());
}
- else
- {
- $event->status=kEvent::erFAIL;
- $event->redirect=false;
+ else {
+ $event->status = kEvent::erFAIL;
+ $event->redirect = false;
$object->setID(0);
}
-
}
- function OnReset(&$event)
+ /**
+ * Reloads form to loose all changes made during item editing
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnReset(&$event)
{
//do nothing - should reset :)
- if ($this->isNewItemCreate($event)) {
+ if ( $this->isNewItemCreate($event) ) {
// just reset id to 0 in case it was create
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
$object->setID(0);
- $this->Application->SetVar($event->getPrefixSpecial().'_id',0);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0);
}
}
/**
- * Apply same processing to each item beeing selected in grid
+ * Apply same processing to each item being selected in grid
*
* @param kEvent $event
- * @access private
+ * @return void
+ * @access protected
*/
- function iterateItems(&$event)
+ protected function iterateItems(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
+
$ids = $this->StoreSelectedIDs($event);
- if ($ids) {
- $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') );
- $order_field = $this->Application->getUnitOption($event->Prefix,'OrderField');
+ if ( $ids ) {
+ $status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
+ $order_field = $this->Application->getUnitOption($event->Prefix, 'OrderField');
- if (!$order_field) {
+ if ( !$order_field ) {
$order_field = 'Priority';
}
foreach ($ids as $id) {
$object->Load($id);
- switch ($event->Name) {
+ switch ( $event->Name ) {
case 'OnMassApprove':
$object->SetDBField($status_field, 1);
break;
case 'OnMassDecline':
$object->SetDBField($status_field, 0);
break;
case 'OnMassMoveUp':
$object->SetDBField($order_field, $object->GetDBField($order_field) + 1);
break;
case 'OnMassMoveDown':
$object->SetDBField($order_field, $object->GetDBField($order_field) - 1);
break;
}
- if ($object->Update()) {
+ if ( $object->Update() ) {
$event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$this->clearSelectedIDs($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnMassClone(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $event->status = kEvent::erSUCCESS;
-
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
$ids = $this->StoreSelectedIDs($event);
- if ($ids) {
- $temp->CloneItems($event->Prefix, $event->Special, $ids);
+ if ( $ids ) {
+ $temp_handler->CloneItems($event->Prefix, $event->Special, $ids);
}
$this->clearSelectedIDs($event);
}
function check_array($records, $field, $value)
{
foreach ($records as $record) {
if ($record[$field] == $value) {
return true;
}
}
return false;
}
- function OnPreSavePopup(&$event)
+ /**
+ * Saves data from editing form to database without checking required fields
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnPreSavePopup(&$event)
{
$object =& $event->getObject();
+ /* @var $object kDBItem */
+
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
- $this->finalizePopup($event);
+ $event->SetRedirectParam('opener', 'u');
}
/* End of Edit events */
// III. Events that allow to put some code before and after Update,Load,Create and Delete methods of item
/**
* Occurse before loading item, 'id' parameter
* allows to get id of item beeing loaded
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemLoad(&$event)
{
}
/**
- * Occurse after loading item, 'id' parameter
+ * Occurs after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(&$event)
{
}
/**
- * Occurse before creating item
+ * Occurs before creating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
}
/**
- * Occurse after creating item
+ * Occurs after creating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->IsTempTable() ) {
$this->_proccessPendingActions($event);
}
}
/**
- * Occurse before updating item
+ * Occurs before updating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(&$event)
{
}
/**
- * Occurse after updating item
+ * Occurs after updating item
*
* @param kEvent $event
* @access public
*/
function OnAfterItemUpdate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->IsTempTable() ) {
$this->_proccessPendingActions($event);
}
}
/**
* Occurse before deleting item, id of item beeing
* deleted is stored as 'id' event param
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemDelete(&$event)
{
}
/**
* Occurse after deleting item, id of deleted item
* is stored as 'id' param of event
*
* @param kEvent $event
* @access public
*/
function OnAfterItemDelete(&$event)
{
}
/**
* Occurs before validation attempt
*
* @param kEvent $event
*/
function OnBeforeItemValidate(&$event)
{
}
/**
* Occurs after successful item validation
*
* @param kEvent $event
*/
function OnAfterItemValidate(&$event)
{
}
/**
* Occures after an item has been copied to temp
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterCopyToTemp(&$event)
{
}
/**
- * Occures before an item is deleted from live table when copying from temp
+ * Occurs before an item is deleted from live table when copying from temp
* (temp handler deleted all items from live and then copy over all items from temp)
* Id of item being deleted is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(&$event)
{
}
/**
* Occures before an item is copied to live table (after all foreign keys have been updated)
* Id of item being copied is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnBeforeCopyToLive(&$event)
{
}
/**
* Occures after an item has been copied to live table
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterCopyToLive(&$event)
{
$this->_proccessPendingActions($event);
}
/**
* Processing file pending actions (e.g. delete scheduled files)
*
* @param kEvent $event
*/
function _proccessPendingActions(&$event)
{
$var_name = $this->_getPendingActionVariableName($event);
$schedule = $this->Application->RecallVar($var_name);
if ( $schedule ) {
$schedule = unserialize($schedule);
foreach ($schedule as $data) {
if ( $data['action'] == 'delete' ) {
unlink( $data['file'] );
}
}
$this->Application->RemoveVar($var_name);
}
}
/**
* Returns variable name, used to store pending file actions
*
* @param kEvent $event
* @return string
*/
function _getPendingActionVariableName(&$event)
{
$window_id = $this->Application->GetTopmostWid($event->Prefix);
return $event->Prefix . '_file_pending_actions' . $window_id;
}
/**
- * Occures before an item is cloneded
- * Id of ORIGINAL item is passed as event' 'id' param
- * Do not call object' Update method in this event, just set needed fields!
+ * Occurs before an item has been cloned
+ * Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeClone(&$event)
+ protected function OnBeforeClone(&$event)
{
}
/**
* Occures after an item has been cloned
* Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterClone(&$event)
{
}
/**
* Occures after list is queried
*
* @param kEvent $event
*/
function OnAfterListQuery(&$event)
{
}
/**
* Ensures that popup will be closed automatically
* and parent window will be refreshed with template
* passed
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
+ * @deprecated
*/
- function finalizePopup(&$event)
+ protected function finalizePopup(&$event)
{
$event->SetRedirectParam('opener', 'u');
}
/**
* Create search filters based on search query
*
* @param kEvent $event
* @access protected
*/
function OnSearch(&$event)
{
$event->setPseudoClass('_List');
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->performSearch($event);
}
/**
* Clear search keywords
*
* @param kEvent $event
* @access protected
*/
function OnSearchReset(&$event)
{
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->resetSearch($event);
}
/**
* Set's new filter value (filter_id meaning from config)
*
* @param kEvent $event
*/
function OnSetFilter(&$event)
{
$filter_id = $this->Application->GetVar('filter_id');
$filter_value = $this->Application->GetVar('filter_value');
$view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
$view_filter = $view_filter ? unserialize($view_filter) : Array();
$view_filter[$filter_id] = $filter_value;
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
}
- function OnSetFilterPattern(&$event)
+ /**
+ * Sets view filter based on request
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnSetFilterPattern(&$event)
{
- $filters = $this->Application->GetVar($event->getPrefixSpecial(true).'_filters');
- if (!$filters) return ;
+ $filters = $this->Application->GetVar($event->getPrefixSpecial(true) . '_filters');
+ if ( !$filters ) {
+ return;
+ }
- $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
- $view_filter = $view_filter ? unserialize($view_filter) : Array();
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial() . '_view_filter');
+ $view_filter = $view_filter ? unserialize($view_filter) : Array ();
$filters = explode(',', $filters);
+
foreach ($filters as $a_filter) {
list($id, $value) = explode('=', $a_filter);
$view_filter[$id] = $value;
}
- $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_view_filter', serialize($view_filter));
$event->redirect = false;
}
/**
* Add/Remove all filters applied to list from "View" menu
*
* @param kEvent $event
*/
function FilterAction(&$event)
{
$view_filter = Array();
$filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
switch ($event->Name)
{
case 'OnRemoveFilters':
$filter_value = 1;
break;
case 'OnApplyFilters':
$filter_value = 0;
break;
}
foreach($filter_menu['Filters'] as $filter_key => $filter_params)
{
if(!$filter_params) continue;
$view_filter[$filter_key] = $filter_value;
}
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
}
/**
* Enter description here...
*
* @param kEvent $event
+ * @access protected
*/
- function OnPreSaveAndOpenTranslator(&$event)
+ protected function OnPreSaveAndOpenTranslator(&$event)
{
$this->Application->SetVar('allow_translation', true);
+
$object =& $event->getObject();
+ /* @var $object kDBItem */
+
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
- if ($event->status == kEvent::erSUCCESS) {
-
+ if ( $event->status == kEvent::erSUCCESS ) {
$resource_id = $this->Application->GetVar('translator_resource_id');
- if ($resource_id) {
+
+ if ( $resource_id ) {
$t_prefixes = explode(',', $this->Application->GetVar('translator_prefixes'));
- $cdata =& $this->Application->recallObject($t_prefixes[1], null, Array('skip_autoload' => true));
+ $cdata =& $this->Application->recallObject($t_prefixes[1], null, Array ('skip_autoload' => true));
+ /* @var $cdata kDBItem */
+
$cdata->Load($resource_id, 'ResourceId');
- if (!$cdata->isLoaded()) {
+
+ if ( !$cdata->isLoaded() ) {
$cdata->SetDBField('ResourceId', $resource_id);
$cdata->Create();
}
- $this->Application->SetVar($cdata->getPrefixSpecial().'_id', $cdata->GetID());
+
+ $this->Application->SetVar($cdata->getPrefixSpecial() . '_id', $cdata->GetID());
}
$event->redirect = $this->Application->GetVar('translator_t');
- $event->setRedirectParams(Array (
+
+ $redirect_params = Array (
'pass' => 'all,trans,' . $this->Application->GetVar('translator_prefixes'),
'opener' => 's',
$event->getPrefixSpecial(true) . '_id' => $object->GetID(),
'trans_event' => 'OnLoad',
'trans_prefix' => $this->Application->GetVar('translator_prefixes'),
'trans_field' => $this->Application->GetVar('translator_field'),
'trans_multi_line' => $this->Application->GetVar('translator_multi_line'),
- ), true);
+ );
+
+ $event->setRedirectParams($redirect_params, true);
// 1. SAVE LAST TEMPLATE TO SESSION (really needed here, because of tweaky redirect)
$last_template = $this->Application->RecallVar('last_template');
- preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets);
+ preg_match('/index4\.php\|' . $this->Application->GetSID() . '-(.*):/U', $last_template, $rets);
$this->Application->StoreVar('return_template', $this->Application->GetVar('t'));
}
}
/**
* Makes all fields non-required
*
* @param kDBItem $object
*/
function RemoveRequiredFields(&$object)
{
// making all field non-required to achieve successful presave
- $fields = $object->getFields();
+ $fields = array_keys( $object->getFields() );
- foreach ($fields as $field => $options) {
+ foreach ($fields as $field) {
if ( $object->isRequired($field) ) {
$object->setRequired($field, false);
}
}
}
/**
* Saves selected user in needed field
*
* @param kEvent $event
*/
function OnSelectUser(&$event)
{
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
$items_info = $this->Application->GetVar('u');
- if ($items_info) {
+
+ if ( $items_info ) {
$user_id = array_shift( array_keys($items_info) );
- $object =& $event->getObject();
$this->RemoveRequiredFields($object);
$is_new = !$object->isLoaded();
- $is_main = substr($this->Application->GetVar($event->Prefix.'_mode'), 0, 1) == 't';
+ $is_main = substr($this->Application->GetVar($event->Prefix . '_mode'), 0, 1) == 't';
- if ($is_new) {
+ if ( $is_new ) {
$new_event = $is_main ? 'OnPreCreate' : 'OnNew';
$event->CallSubEvent($new_event);
$event->redirect = true;
}
$object->SetDBField($this->Application->RecallVar('dst_field'), $user_id);
- if ($is_new) {
+ if ( $is_new ) {
$object->Create();
}
else {
$object->Update();
}
}
- $event->SetRedirectParam($event->getPrefixSpecial().'_id', $object->GetID());
- $this->finalizePopup($event);
+ $event->SetRedirectParam($event->getPrefixSpecial() . '_id', $object->GetID());
+ $event->SetRedirectParam('opener', 'u');
}
/** EXPORT RELATED **/
/**
* Shows export dialog
*
* @param kEvent $event
*/
function OnExport(&$event)
{
$selected_ids = $this->StoreSelectedIDs($event);
if (implode(',', $selected_ids) == '') {
// K4 fix when no ids found bad selected ids array is formed
$selected_ids = false;
}
$this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
$this->Application->LinkVar('export_finish_t');
$this->Application->LinkVar('export_progress_t');
$this->Application->StoreVar('export_oroginal_special', $event->Special);
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/*list ($index_file, $env) = explode('|', $this->Application->RecallVar('last_template'));
$finish_url = $this->Application->BaseURL('/admin').$index_file.'?'.ENV_VAR_NAME.'='.$env;
$this->Application->StoreVar('export_finish_url', $finish_url);*/
$redirect_params = Array (
$this->Prefix . '.export_event' => 'OnNew',
'pass' => 'all,' . $this->Prefix . '.export'
);
$event->setRedirectParams($redirect_params);
}
/**
- * Apply some special processing to
- * object beeing recalled before using
- * it in other events that call prepareObject
+ * Apply some special processing to object being
+ * recalled before using it in other events that
+ * call prepareObject
*
- * @param Object $object
+ * @param kDBItem|kDBList $object
* @param kEvent $event
+ * @return void
* @access protected
*/
- function prepareObject(&$object, &$event)
+ protected function prepareObject(&$object, &$event)
{
- if ($event->Special == 'export' || $event->Special == 'import')
- {
+ if ( $event->Special == 'export' || $event->Special == 'import' ) {
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->prepareExportColumns($event);
}
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
*/
function getCustomExportColumns(&$event)
{
return Array();
}
/**
* Export form validation & processing
*
* @param kEvent $event
*/
function OnExportBegin(&$event)
{
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->OnExportBegin($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnExportCancel(&$event)
{
$this->OnGoBack($event);
}
/**
* Allows configuring export options
*
* @param kEvent $event
*/
function OnBeforeExportBegin(&$event)
{
}
- function OnDeleteExportPreset(&$event)
+ /**
+ * Deletes export preset
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnDeleteExportPreset(&$event)
{
- $object =& $event->GetObject();
+ $field_values = $this->getSubmittedFields($event);
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if($items_info)
- {
- list($id,$field_values) = each($items_info);
- $preset_key = $field_values['ExportPresets'];
+ if ( !$field_values ) {
+ return ;
+ }
- $export_settings = $this->Application->RecallPersistentVar('export_settings');
- if (!$export_settings) return ;
- $export_settings = unserialize($export_settings);
- if (!isset($export_settings[$event->Prefix])) return ;
-
- $to_delete = '';
- $export_presets = array(''=>'');
- foreach ($export_settings[$event->Prefix] as $key => $val) {
- if (implode('|', $val['ExportColumns']) == $preset_key) {
- $to_delete = $key;
- break;
- }
- }
- if ($to_delete) {
- unset($export_settings[$event->Prefix][$to_delete]);
- $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
+ $preset_key = $field_values['ExportPresets'];
+ $export_settings = $this->Application->RecallPersistentVar('export_settings');
+
+ if ( !$export_settings ) {
+ return ;
+ }
+
+ $export_settings = unserialize($export_settings);
+
+ if ( !isset($export_settings[$event->Prefix]) ) {
+ return ;
+ }
+
+ $to_delete = '';
+
+ foreach ($export_settings[$event->Prefix] as $key => $val) {
+ if ( implode('|', $val['ExportColumns']) == $preset_key ) {
+ $to_delete = $key;
+ break;
}
}
+
+ if ( $to_delete ) {
+ unset($export_settings[$event->Prefix][$to_delete]);
+ $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
+ }
}
/**
* Saves changes & changes language
*
* @param kEvent $event
*/
function OnPreSaveAndChangeLanguage(&$event)
{
if ($this->UseTempTables($event)) {
$event->CallSubEvent('OnPreSave');
}
if ($event->status == kEvent::erSUCCESS) {
$this->Application->SetVar('m_lang', $this->Application->GetVar('language'));
$data = $this->Application->GetVar('st_id');
if ($data) {
$event->SetRedirectParam('st_id', $data);
}
}
}
/**
* Used to save files uploaded via swfuploader
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnUploadFile(&$event)
+ protected function OnUploadFile(&$event)
{
$event->status = kEvent::erSTOP;
// define('DBG_SKIP_REPORTING', 0);
$default_msg = "Flash requires that we output something or it won't fire the uploadSuccess event";
if (!$this->Application->HttpQuery->Post) {
// Variables {field, id, flashsid} are always submitted through POST!
// When file size is larger, then "upload_max_filesize" (in php.ini),
- // then theese variables also are not submitted -> handle such case.
+ // then these variables also are not submitted -> handle such case.
header('HTTP/1.0 413 File size exceeds allowed limit');
echo $default_msg;
return ;
}
if (!$this->_checkFlashUploaderPermission($event)) {
// 403 Forbidden
header('HTTP/1.0 403 You don\'t have permissions to upload');
echo $default_msg;
return ;
}
$value = $this->Application->GetVar('Filedata');
if (!$value || ($value['error'] != UPLOAD_ERR_OK)) {
// 413 Request Entity Too Large (file uploads disabled OR uploaded file was
// to large for web server to accept, see "upload_max_filesize" in php.ini)
header('HTTP/1.0 413 File size exceeds allowed limit');
echo $default_msg;
return ;
}
$tmp_path = WRITEABLE . '/tmp/';
$fname = $value['name'];
$id = $this->Application->GetVar('id');
if ($id) {
$fname = $id . '_' . $fname;
}
$field_name = $this->Application->GetVar('field');
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
if (array_key_exists($field_name, $fields)) {
$upload_dir = $fields[$field_name]['upload_dir'];
}
else {
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$upload_dir = $virtual_fields[$field_name]['upload_dir'];
}
if (!is_writable($tmp_path)) {
// 500 Internal Server Error
// check both temp and live upload directory
header('HTTP/1.0 500 Write permissions not set on the server');
echo $default_msg;
return ;
}
$upload_formatter =& $this->Application->recallObject('kUploadFormatter');
/* @var $upload_formatter kUploadFormatter */
$fname = $upload_formatter->_ensureUniqueFilename($tmp_path, $fname);
move_uploaded_file($value['tmp_name'], $tmp_path.$fname);
echo preg_replace('/^' . preg_quote($id, '/') . '_/', '', $fname);
$this->deleteTempFiles($tmp_path);
}
/**
* Delete temporary files, that won't be used for sure
*
* @param string $path
*/
function deleteTempFiles($path)
{
$files = glob($path . '*.*');
$max_file_date = strtotime('-1 day');
foreach ($files as $file) {
if (filemtime($file) < $max_file_date) {
unlink($file);
}
}
}
/**
* Checks, that flash uploader is allowed to perform upload
*
* @param kEvent $event
* @return bool
*/
function _checkFlashUploaderPermission(&$event)
{
// Flash uploader does NOT send correct cookies, so we need to make our own check
$cookie_name = 'adm_' . $this->Application->ConfigValue('SessionCookieName');
$this->Application->HttpQuery->Cookie['cookies_on'] = 1;
$this->Application->HttpQuery->Cookie[$cookie_name] = $this->Application->GetVar('flashsid');
// this prevents session from auto-expiring when KeepSessionOnBrowserClose & FireFox is used
$this->Application->HttpQuery->Cookie[$cookie_name . '_live'] = $this->Application->GetVar('flashsid');
$admin_ses =& $this->Application->recallObject('Session.admin');
/* @var $admin_ses Session */
if ($admin_ses->RecallVar('user_id') == USER_ROOT) {
return true;
}
// copy some data from given session to current session
$backup_user_id = $this->Application->RecallVar('user_id');
$this->Application->StoreVar('user_id', $admin_ses->RecallVar('user_id'));
$backup_user_groups = $this->Application->RecallVar('UserGroups');
$this->Application->StoreVar('UserGroups', $admin_ses->RecallVar('UserGroups'));
// check permissions using event, that have "add|edit" rule
$check_event = new kEvent($event->getPrefixSpecial() . ':OnProcessSelected');
$check_event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
$allowed_to_upload = $this->CheckPermission($check_event);
// restore changed data, so nothing gets saved to database
$this->Application->StoreVar('user_id', $backup_user_id);
$this->Application->StoreVar('UserGroups', $backup_user_groups);
return $allowed_to_upload;
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnDeleteFile(&$event)
{
$event->status = kEvent::erSTOP;
if (strpos($this->Application->GetVar('file'), '../') !== false) {
return ;
}
$object =& $event->getObject( Array ('skip_autoload' => true) );
$options = $object->GetFieldOptions( $this->Application->GetVar('field') );
$var_name = $this->_getPendingActionVariableName($event);
$schedule = $this->Application->RecallVar($var_name);
$schedule = $schedule ? unserialize($schedule) : Array ();
$schedule[] = Array ('action' => 'delete', 'file' => FULL_PATH . $options['upload_dir'] . $this->Application->GetVar('file'));
$this->Application->StoreVar($var_name, serialize($schedule));
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnViewFile(&$event)
{
$event->status = kEvent::erSTOP;
$file = $this->Application->GetVar('file');
if ((strpos($file, '../') !== false) || (trim($file) !== $file)) {
// when relative paths or special chars are found template names from url, then it's hacking attempt
return ;
}
$object =& $event->getObject( Array ('skip_autoload' => true));
/* @var $object kDBItem */
$field = $this->Application->GetVar('field');
$options = $object->GetFieldOptions($field);
// set current uploaded file
if ($this->Application->GetVar('tmp')) {
$options['upload_dir'] = WRITEBALE_BASE . '/tmp/';
unset($options['include_path']);
$object->SetFieldOptions($field, $options);
$object->SetDBField($field, $this->Application->GetVar('id') . '_' . $file);
}
else {
$object->SetDBField($field, $file);
}
// get url to uploaded file
if ($this->Application->GetVar('thumb')) {
$url = $object->GetField($field, $options['thumb_format']);
}
else {
$url = $object->GetField($field, 'full_url'); // don't use "file_urls" format to prevent recursion
}
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$path = $file_helper->urlToPath($url);
if (!file_exists($path)) {
exit;
}
$type = mime_content_type($path);
header('Content-Length: ' . filesize($path));
header('Content-Type: ' . $type);
header('Content-Disposition: inline; filename="' . $file . '"');
readfile($path);
}
/**
* Validates MInput control fields
*
* @param kEvent $event
*/
function OnValidateMInputFields(&$event)
{
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$minput_helper->OnValidateMInputFields($event);
}
/**
* Returns auto-complete values for ajax-dropdown
*
* @param kEvent $event
*/
function OnSuggestValues(&$event)
{
if (!$this->Application->isAdminUser) {
// very careful here, because this event allows to
// view every object field -> limit only to logged-in admins
return ;
}
$event->status = kEvent::erSTOP;
$field = $this->Application->GetVar('field');
$cur_value = $this->Application->GetVar('cur_value');
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$object =& $event->getObject();
if (!$field || !$cur_value || !$object->isField($field)) {
return ;
}
$limit = $this->Application->GetVar('limit');
if (!$limit) {
$limit = 20;
}
$sql = 'SELECT DISTINCT '.$field.'
FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
WHERE '.$field.' LIKE '.$this->Conn->qstr($cur_value.'%').'
ORDER BY '.$field.'
LIMIT 0,' . $limit;
$data = $this->Conn->GetCol($sql);
$this->Application->XMLHeader();
echo '<suggestions>';
foreach ($data as $item) {
echo '<item>' . htmlspecialchars($item) . '</item>';
}
echo '</suggestions>';
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnSaveWidths(&$event)
{
$event->status = kEvent::erSTOP;
- $lang =& $this->Application->recallObject('lang.current');
-// header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
+ /*$lang =& $this->Application->recallObject('lang.current');
+ header('Content-type: text/xml; charset=' . $lang->GetDBField('Charset'));*/
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
- $picker_helper->PreparePicker($event->getPrefixSpecial(), $this->Application->GetVar('grid_name'));
+ $picker_helper->PreparePicker($event->getPrefixSpecial(), $this->Application->GetVar('grid_name'));
$picker_helper->SaveWidths($event->getPrefixSpecial(), $this->Application->GetVar('widths'));
echo 'OK';
}
/**
* Called from CSV import script after item fields
* are set and validated, but before actual item create/update.
* If event status is kEvent::erSUCCESS, line will be imported,
* else it will not be imported but added to skipped lines
* and displayed in the end of import.
* Event status is preset from import script.
*
* @param kEvent $event
*/
function OnBeforeCSVLineImport(&$event)
{
// abstract, for hooking
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
*/
function OnCloneSubItem(&$event)
{
$clones = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'Clones');
$subitem_prefix = $event->Prefix . '-' . preg_replace('/^#/', '', $event->MasterEvent->Prefix);
$clones[$subitem_prefix] = Array ('ParentPrefix' => $event->Prefix);
$this->Application->setUnitOption($event->MasterEvent->Prefix, 'Clones', $clones);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/db/dbitem.php
===================================================================
--- branches/5.2.x/core/kernel/db/dbitem.php (revision 14595)
+++ branches/5.2.x/core/kernel/db/dbitem.php (revision 14596)
@@ -1,1643 +1,1413 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
/**
* DBItem
*
*/
class kDBItem extends kDBBase {
/**
* Description
*
* @var array Associative array of current item' field values
* @access protected
*/
protected $FieldValues = Array ();
/**
* Unformatted field values, before parse
*
* @var Array
* @access protected
*/
protected $DirtyFieldValues = Array ();
/**
* Holds item values after loading (not affected by submit)
*
* @var Array
* @access protected
*/
protected $OriginalFieldValues = Array ();
/**
- * Holds field errors
- *
- * @var Array
- * @access protected
- */
- protected $FieldErrors = Array ();
-
- /**
- * Phrases for each error pseudo
- *
- * @var Array
- * @access protected
- */
- protected $ErrorMsgs = Array ();
-
- /**
* If set to true, Update will skip Validation before running
*
* @var array Associative array of current item' field values
* @access public
*/
public $IgnoreValidation = false;
/**
* Remembers if object was loaded
*
* @var bool
* @access protected
*/
protected $Loaded = false;
/**
* Holds item' primary key value
*
* @var int Value of primary key field for current item
* @access protected
*/
protected $ID;
/**
* This object is used in cloning operations
*
* @var bool
* @access public
*/
public $inCloning = false;
- public function __construct()
+ /**
+ * Validator object reference
+ *
+ * @var kValidator
+ */
+ protected $validator = null;
+
+ /**
+ * Creates validator object, only when required
+ *
+ */
+ public function initValidator()
{
- parent::__construct();
+ if ( !is_object($this->validator) ) {
+ $validator_class = $this->Application->getUnitOption($this->Prefix, 'ValidatorClass', 'kValidator');
+
+ $this->validator =& $this->Application->makeClass($validator_class);
+ }
- $this->ErrorMsgs['required'] = '!la_err_required!'; //'Field is required';
- $this->ErrorMsgs['unique'] = '!la_err_unique!'; //'Field value must be unique';
- $this->ErrorMsgs['value_out_of_range'] = '!la_err_value_out_of_range!'; //'Field is out of range, possible values from %s to %s';
- $this->ErrorMsgs['length_out_of_range'] = '!la_err_length_out_of_range!'; //'Field is out of range';
- $this->ErrorMsgs['bad_type'] = '!la_err_bad_type!'; //'Incorrect data format, please use %s';
- $this->ErrorMsgs['invalid_format'] = '!la_err_invalid_format!'; //'Incorrect data format, please use %s';
- $this->ErrorMsgs['bad_date_format'] = '!la_err_bad_date_format!'; //'Incorrect date format, please use (%s) ex. (%s)';
- $this->ErrorMsgs['primary_lang_required'] = '!la_err_primary_lang_required!';
+ $this->validator->setDataSource($this);
}
public function SetDirtyField($field_name, $field_value)
{
$this->DirtyFieldValues[$field_name] = $field_value;
}
public function GetDirtyField($field_name)
{
return $this->DirtyFieldValues[$field_name];
}
public function GetOriginalField($field_name, $formatted = false, $format=null)
{
if (array_key_exists($field_name, $this->OriginalFieldValues)) {
// item was loaded before
$value = $this->OriginalFieldValues[$field_name];
}
else {
// no original fields -> use default field value
$value = $this->Fields[$field_name]['default'];
}
if (!$formatted) {
return $value;
}
- $options = $this->GetFieldOptions($field_name);
$res = $value;
- if (array_key_exists('formatter', $options)) {
- $formatter =& $this->Application->recallObject($options['formatter']);
+ $formatter = $this->GetFieldOption($field_name, 'formatter');
+
+ if ( $formatter ) {
+ $formatter =& $this->Application->recallObject($formatter);
/* @var $formatter kFormatter */
$res = $formatter->Format($value, $field_name, $this, $format);
}
+
return $res;
}
/**
* Sets original field value (useful for custom virtual fields)
*
* @param string $field_name
*/
public function SetOriginalField($field_name, $field_value)
{
$this->OriginalFieldValues[$field_name] = $field_value;
}
/**
* Set's default values for all fields
*
* @access public
*/
public function SetDefaultValues()
{
parent::SetDefaultValues();
if ($this->populateMultiLangFields) {
$this->PopulateMultiLangFields();
}
foreach ($this->Fields as $field => $field_options) {
$default_value = isset($field_options['default']) ? $field_options['default'] : NULL;
$this->SetDBField($field, $default_value);
}
}
/**
* Sets current item field value
* (applies formatting)
*
* @access public
* @param string $name Name of the field
* @param mixed $value Value to set the field to
* @return void
*/
public function SetField($name,$value)
{
$options = $this->GetFieldOptions($name);
$parsed = $value;
if ($value == '') {
$parsed = NULL;
}
// kFormatter is always used, to make sure, that numeric value is converted to normal representation
// according to regional format, even when formatter is not set (try seting format to 1.234,56 to understand why)
$formatter =& $this->Application->recallObject(isset($options['formatter']) ? $options['formatter'] : 'kFormatter');
+ /* @var $formatter kFormatter */
+
$parsed = $formatter->Parse($value, $name, $this);
$this->SetDBField($name,$parsed);
}
/**
* Sets current item field value
* (doesn't apply formatting)
*
* @access public
* @param string $name Name of the field
* @param mixed $value Value to set the field to
* @return void
*/
public function SetDBField($name,$value)
{
$this->FieldValues[$name] = $value;
- /*if (isset($this->Fields[$name]['formatter'])) {
- $formatter =& $this->Application->recallObject($this->Fields[$name]['formatter']);
- $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.
+ * 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 = isset($this->Fields[$field]['error_field']) ? $this->Fields[$field]['error_field'] : $field;
- if (isset($this->FieldErrors[$error_field]['pseudo'])) {
- // 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.'!';
- }
+ $this->initValidator();
- return true;
+ return $this->validator->SetError($field, $pseudo, $error_label, $error_params);
}
/**
* Removes error on field
*
* @param string $field
* @access public
*/
public function RemoveError($field)
{
- unset( $this->FieldErrors[$field] );
+ if ( !is_object($this->validator) ) {
+ return ;
+ }
+
+ $this->validator->RemoveError($field);
}
/**
* Returns error pseudo
*
* @param string $field
* @return string
*/
public function GetErrorPseudo($field)
{
- if ( !array_key_exists($field, $this->FieldErrors) ) {
+ if ( !is_object($this->validator) ) {
return '';
}
- return array_key_exists('pseudo', $this->FieldErrors[$field]) ? $this->FieldErrors[$field]['pseudo'] : '';
+ return $this->validator->GetErrorPseudo($field);
}
/**
* Return current item' field value by field name
* (doesn't apply formatter)
*
* @param string $name field name to return
* @return mixed
* @access public
*/
public function GetDBField($name)
{
/*if (!array_key_exists($name, $this->FieldValues) && defined('DEBUG_MODE') && DEBUG_MODE) {
$this->Application->Debugger->appendTrace();
}*/
return $this->FieldValues[$name];
}
public function HasField($name)
{
return array_key_exists($name, $this->FieldValues);
}
public function GetFieldValues()
{
return $this->FieldValues;
}
/**
- * 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
- *
- * @param Array $hash
- * @param Array $set_fields Optional param, field names in target object to set, other fields will be skipped
- * @access public
- */
- public function SetFieldsFromHash($hash, $set_fields = null)
+ * 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 actually setting the fields
+ *
+ * @param Array $hash
+ * @param Array $set_fields Optional param, field names in target object to set, other fields will be skipped
+ * @return void
+ * @access public
+ */
+ public function SetFieldsFromHash($hash, $set_fields = Array ())
{
- // used in formatter which work with multiple fields together
- foreach($hash as $field_name => $field_value) {
- if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) {
- continue;
- }
+ if ( !$set_fields ) {
+ $set_fields = array_keys($hash);
+ }
- if (is_array($set_fields) && !in_array($field_name, $set_fields)) {
- continue;
- }
+ $set_fields = array_intersect($set_fields, array_keys($this->Fields));
- $this->SetDirtyField($field_name, $field_value);
+ // used in formatter which work with multiple fields together
+ foreach ($set_fields as $field_name) {
+ $this->SetDirtyField($field_name, $hash[$field_name]);
}
// formats all fields using associated formatters
- foreach ($hash as $field_name => $field_value)
- {
- if (is_numeric($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);
+ foreach ($set_fields as $field_name) {
+ $this->SetField($field_name, $hash[$field_name]);
}
}
- public function SetDBFieldsFromHash($hash, $set_fields = null)
+ /**
+ * Sets object fields from $hash arrat
+ * @param Array $hash
+ * @param Array|null $set_fields
+ * @return void
+ * @access public
+ */
+ public function SetDBFieldsFromHash($hash, $set_fields = Array ())
{
- foreach ($hash as $field_name => $field_value) {
- if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) {
- continue;
- }
+ if ( !$set_fields ) {
+ $set_fields = array_keys($hash);
+ }
- if (is_array($set_fields) && !in_array($field_name, $set_fields)) {
- continue;
- }
+ $set_fields = array_intersect($set_fields, array_keys($this->Fields));
- $this->SetDBField($field_name, $field_value);
+ foreach ($set_fields as $field_name) {
+ $this->SetDBField($field_name, $hash[$field_name]);
}
}
/**
- * Returns part of SQL WHERE clause identifing the record, ex. id = 25
- *
- * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
- * @param Array $keys_hash alternative, then item id, keys hash to load item by
- * @return void
- * @see kDBItem::Load()
- * @see kDBItem::Update()
- * @see kDBItem::Delete()
- * @access protected
- */
- protected function GetKeyClause($method=null, $keys_hash = null)
+ * Returns part of SQL WHERE clause identifying the record, ex. id = 25
+ *
+ * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
+ * @param Array $keys_hash alternative, then item id, keys hash to load item by
+ * @see kDBItem::Load()
+ * @see kDBItem::Update()
+ * @see kDBItem::Delete()
+ * @return string
+ * @access protected
+ */
+ protected function GetKeyClause($method = null, $keys_hash = null)
{
- if (!isset($keys_hash)) {
+ if ( !isset($keys_hash) ) {
$keys_hash = Array ($this->IDField => $this->ID);
}
$ret = '';
foreach ($keys_hash as $field => $value) {
- if (!preg_match('/\./', $field)) {
+ if ( !preg_match('/\./', $field) ) {
$ret .= '(`' . $this->TableName . '`.' . $field . ' = ' . $this->Conn->qstr($value) . ') AND ';
}
else {
$ret .= '(' . $field . ' = ' . $this->Conn->qstr($value) . ') AND ';
}
}
return substr($ret, 0, -5);
}
/**
* Loads item from the database by given id
*
* @access public
* @param mixed $id item id of keys->values hash to load item by
* @param string $id_field_name Optional parameter to load item by given Id field
* @param bool $cachable cache this query result based on it's prefix serial
* @return bool True if item has been loaded, false otherwise
*/
public function Load($id, $id_field_name = null, $cachable = false)
{
if ( isset($id_field_name) ) {
$this->IDField = $id_field_name; // set new IDField
}
$keys_sql = '';
if (is_array($id)) {
$keys_sql = $this->GetKeyClause('load', $id);
}
else {
$this->setID($id);
$keys_sql = $this->GetKeyClause('load');
}
if ( isset($id_field_name) ) {
// restore original IDField from unit config
$this->IDField = $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;
if ($cachable && $this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
$serial_name = $this->Application->incrementCacheSerial($this->Prefix == 'st' ? 'c' : $this->Prefix, isset($id_field_name) ? null : $id, false);
$cache_key = 'kDBItem::Load_' . crc32(serialize($id) . '-' . $this->IDField) . '[%' . $serial_name . '%]';
$field_values = $this->Application->getCache($cache_key, false);
if ($field_values === false) {
$field_values = $this->Conn->GetRow($q);
if ($field_values !== false) {
// only cache, when data was retrieved
$this->Application->setCache($cache_key, $field_values);
}
}
}
else {
$field_values = $this->Conn->GetRow($q);
}
if ($field_values) {
$this->FieldValues = array_merge($this->FieldValues, $field_values);
$this->OriginalFieldValues = $this->FieldValues;
}
else {
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;
}
/**
* Loads object from hash (not db)
*
* @param Array $fields_hash
* @param string $id_field
*/
public function LoadFromHash($fields_hash, $id_field = null)
{
if (!isset($id_field)) {
$id_field = $this->IDField;
}
$this->Clear();
if (!$fields_hash || !array_key_exists($id_field, $fields_hash)) {
// no data OR id field missing
return false;
}
$id = $fields_hash[$id_field];
if ( !$this->raiseEvent('OnBeforeItemLoad', $id) ) {
return false;
}
$this->FieldValues = array_merge($this->FieldValues, $fields_hash);
$this->OriginalFieldValues = $this->FieldValues;
$this->setID($id);
$this->UpdateFormattersSubFields(); // used for updating separate virtual date/time fields from DB timestamp (for example)
$this->raiseEvent('OnAfterItemLoad', $id);
$this->Loaded = true;
return true;
}
/**
* Builds select sql, SELECT ... FROM parts only
*
* @access public
* @return string
*/
/**
* Returns SELECT part of list' query
*
* @param string $base_query
* @param bool $replace_table
* @return string
* @access public
*/
public function GetSelectSQL($base_query = null, $replace_table = true)
{
if (!isset($base_query)) {
$base_query = $this->SelectClause;
}
$base_query = $this->addCalculatedFields($base_query);
return parent::GetSelectSQL($base_query, $replace_table);
}
public function UpdateFormattersMasterFields()
{
+ $this->initValidator(); // used, when called not from kValidator::Validate method
+
foreach ($this->Fields as $field => $options) {
- if (isset($options['formatter'])) {
+ if ( isset($options['formatter']) ) {
$formatter =& $this->Application->recallObject($options['formatter']);
+ /* @var $formatter kFormatter */
+
$formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this);
}
}
}
/**
* Allows to skip certain fields from getting into sql queries
*
* @param string $field_name
* @param mixed $force_id
* @return bool
*/
public function skipField($field_name, $force_id = false)
{
$skip = false;
// 1. skipping 'virtual' field
$skip = $skip || array_key_exists($field_name, $this->VirtualFields);
// 2. don't write empty field value to db, when "skip_empty" option is set
$field_value = array_key_exists($field_name, $this->FieldValues) ? $this->FieldValues[$field_name] : false;
if (array_key_exists($field_name, $this->Fields)) {
$skip_empty = array_key_exists('skip_empty', $this->Fields[$field_name]) ? $this->Fields[$field_name]['skip_empty'] : false;
}
else {
// field found in database, but not declared in unit config
$skip_empty = false;
}
$skip = $skip || (!$field_value && $skip_empty);
// 3. skipping field not in Fields (nor virtual, nor real)
$skip = $skip || !array_key_exists($field_name, $this->Fields);
return $skip;
}
/**
- * Updates previously loaded record with current item' values
- *
- * @access public
- * @param int Primery Key Id to update
- * @return bool
- */
+ * Updates previously loaded record with current item' values
+ *
+ * @access public
+ * @param int $id Primary Key Id to update
+ * @param bool $system_update
+ * @return bool
+ * @access public
+ */
public function Update($id = null, $system_update = false)
{
- if (isset($id)) {
+ if ( isset($id) ) {
$this->setID($id);
}
- if (!$this->raiseEvent('OnBeforeItemUpdate')) {
+ if ( !$this->raiseEvent('OnBeforeItemUpdate') ) {
return false;
}
- if (!isset($this->ID)) {
+ if ( !isset($this->ID) ) {
// ID could be set inside OnBeforeItemUpdate event, so don't combine this check with previous one
return false;
}
// validate before updating
- if (!$this->Validate()) {
+ if ( !$this->Validate() ) {
return false;
}
- if (!$this->FieldValues) {
- // nothing to update
- return true;
- }
-
- $sql = '';
-
- foreach ($this->FieldValues as $field_name => $field_value) {
- if ($this->skipField($field_name)) {
- continue;
- }
-
- if ( is_null($field_value) ) {
- if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) {
- // "kFormatter::Parse" methods converts empty values to NULL and for
- // not-null fields they are replaced with default value here
- $field_value = $this->Fields[$field_name]['default'];
- }
- }
-
- $sql .= '`' . $field_name . '` = ' . $this->Conn->qstr($field_value) . ', ';
- }
-
- $sql = 'UPDATE ' . $this->TableName . '
- SET ' . substr($sql, 0, -2) . '
- WHERE ' . $this->GetKeyClause('update');
-
- if ($this->Conn->ChangeQuery($sql) === false) {
- // there was and sql error
- return false;
- }
+ if ( !$this->FieldValues ) {
+ // nothing to update
+ return true;
+ }
+
+ $sql = '';
+
+ foreach ($this->FieldValues as $field_name => $field_value) {
+ if ( $this->skipField($field_name) ) {
+ continue;
+ }
+
+ if ( is_null($field_value) ) {
+ if ( array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null'] ) {
+ // "kFormatter::Parse" methods converts empty values to NULL and for
+ // not-null fields they are replaced with default value here
+ $field_value = $this->Fields[$field_name]['default'];
+ }
+ }
+
+ $sql .= '`' . $field_name . '` = ' . $this->Conn->qstr($field_value) . ', ';
+ }
+
+ $sql = 'UPDATE ' . $this->TableName . '
+ SET ' . substr($sql, 0, -2) . '
+ WHERE ' . $this->GetKeyClause('update');
+
+ if ( $this->Conn->ChangeQuery($sql) === false ) {
+ // there was and sql error
+ return false;
+ }
$affected_rows = $this->Conn->getAffectedRows();
- if (!$system_update && ($affected_rows > 0)) {
+ if ( !$system_update && ($affected_rows > 0) ) {
$this->setModifiedFlag(ChangeLog::UPDATE);
}
$this->saveCustomFields();
- $this->raiseEvent('OnAfterItemUpdate');
- $this->OriginalFieldValues = $this->FieldValues;
- $this->Loaded = true;
+ $this->raiseEvent('OnAfterItemUpdate');
+ $this->OriginalFieldValues = $this->FieldValues;
+ $this->Loaded = true;
- if (!$this->IsTempTable()) {
+ if ( !$this->IsTempTable() ) {
$this->Application->resetCounters($this->TableName);
}
return true;
}
+ /**
+ * Validates given field
+ *
+ * @param string $field
+ * @return bool
+ * @access public
+ */
public function ValidateField($field)
{
- $options = $this->Fields[$field];
+ $this->initValidator();
- /*if (isset($options['formatter'])) {
- $formatter =& $this->Application->recallObject($options['formatter']);
- $formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this);
- }*/
-
- $error_field = isset($options['error_field']) ? $options['error_field'] : $field;
- $res = !isset($this->FieldErrors[$error_field]['pseudo']) || !$this->FieldErrors[$error_field]['pseudo'];
-
- $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;
+ return $this->validator->ValidateField($field);
}
/**
* Validate all item fields based on
* constraints set in each field options
* in config
*
* @return bool
* @access private
*/
public function Validate()
{
- $this->UpdateFormattersMasterFields(); //order is critical - should be called BEFORE checking errors
-
- if ($this->IgnoreValidation) {
+ if ( $this->IgnoreValidation ) {
return true;
}
+ $this->initValidator();
+
// will apply any custom validation to the item
$this->raiseEvent('OnBeforeItemValidate');
- $global_res = true;
- foreach ($this->Fields as $field => $params) {
- $res = $this->ValidateField($field);
-
-
- $global_res = $global_res && $res;
- }
-
- if (!$global_res && $this->Application->isDebugMode()) {
- $error_msg = ' Validation failed in prefix <strong>'.$this->Prefix.'</strong>,
- 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);
- }
-
- if ($global_res) {
+ if ( $this->validator->Validate() ) {
// no validation errors
$this->raiseEvent('OnAfterItemValidate');
- }
- return $global_res;
- }
+ 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;
+ return false;
}
/**
* Check if item has errors
*
* @param Array $skip_fields fields to skip during error checking
* @return bool
*/
public function HasErrors($skip_fields = Array ())
{
- $global_res = false;
-
- foreach ($this->Fields as $field => $field_params) {
- // 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;
- }
+ if ( !is_object($this->validator) ) {
+ return false;
}
- return $global_res;
- }
- /**
- * 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)
- {
- $res = true;
- $val = $this->FieldValues[$field];
- if ( $val != '' &&
- isset($params['type']) &&
- preg_match("#int|integer|double|float|real|numeric|string#", $params['type'])
- ) {
- 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->FieldValues[$field]);
- }
- if (!$res) {
- $this->SetError($field, 'bad_type', null, Array ($params['type']));
- }
- }
- return $res;
+ return $this->validator->HasErrors($skip_fields);
}
/**
* Check if value is set for required field
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access public
+ * @todo Find a way to get rid of direct call from kMultiLanguage::UpdateMasterFields method
*/
public function ValidateRequired($field, $params)
{
- $res = true;
- if (isset($params['required']) && $params['required']) {
- $check_value = $this->FieldValues[$field];
- if ($this->Application->ConfigValue('TrimRequiredFields')) {
- $check_value = trim($check_value);
- }
- $res = ((string)$check_value != '');
- }
-
- if (!$res) {
- $this->SetError($field, 'required');
- }
-
- return $res;
- }
-
- /**
- * 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)
- {
- $res = true;
- $unique_fields = getArrayValue($params,'unique');
- if($unique_fields !== false)
- {
- $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
- if ((string)$this->GetDBField($unique_field) != '' || (isset($this->Fields[$unique_field]['required']) && $this->Fields[$unique_field]['required'])) {
- $where[] = '`'.$unique_field.'` = '.$this->Conn->qstr( $this->GetDBField($unique_field) );
- }
- 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->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', $this->Application->GetLiveName($this->TableName), $sql) );
-
- $res = ($res_temp == 0) && ($res_live == 0);
-
- if (!$res) {
- $this->SetError($field, 'unique');
- }
- }
- return $res;
- }
-
- /**
- * 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->FieldValues[$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'];
- $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_val, $max_val));
- return $res;
- }
- 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 (!$res) {
- $error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len'), mb_strlen($val));
- $this->SetError($field, 'length_out_of_range', null, $error_params);
- return $res;
- }
- return $res;
+ return $this->validator->ValidateRequired($field, $params);
}
/**
* Return error message for field
*
* @param string $field
* @return string
* @access public
*/
public function GetErrorMsg($field, $force_escape = null)
{
- $err = $this->GetErrorPseudo($field);
-
- if (!$err) {
+ if ( !is_object($this->validator) ) {
return '';
}
- // if special error msg defined in config
- if( isset($this->Fields[$field]['error_msgs'][$err]) )
- {
- $msg = $this->Fields[$field]['error_msgs'][$err];
- }
- else //fall back to defaults
- {
- if( !isset($this->ErrorMsgs[$err]) ) {
- trigger_error('No user message is defined for pseudo error <b>'.$err.'</b><br>', E_USER_WARNING);
- return $err; //return the pseudo itself
- }
- $msg = $this->ErrorMsgs[$err];
- }
- $msg = $this->Application->ReplaceLanguageTags($msg, $force_escape);
-
- if ( isset($this->FieldErrors[$field]['params']) )
- {
- return vsprintf($msg, $this->FieldErrors[$field]['params']);
- }
-
- return $msg;
+ return $this->validator->GetErrorMsg($field, $force_escape);
}
/**
* Returns field errors
*
* @return Array
* @access public
*/
public function GetFieldErrors()
{
- return $this->FieldErrors;
+ if ( !is_object($this->validator) ) {
+ return Array ();
+ }
+
+ return $this->validator->GetFieldErrors();
}
/**
- * Creates a record in the database table with current item' values
- *
- * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
- * @access public
- * @return bool
- */
+ * Creates a record in the database table with current item' values
+ *
+ * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
+ * @param bool $system_create
+ * @return bool
+ * @access public
+ */
public function Create($force_id = false, $system_create = false)
{
if (!$this->raiseEvent('OnBeforeItemCreate')) {
return false;
}
// Validating fields before attempting to create record
if (!$this->Validate()) {
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) {
if ($this->skipField($field_name, $force_id)) {
continue;
}
if (is_null($field_value)) {
if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) {
// "kFormatter::Parse" methods converts empty values to NULL and for
- // not-null fields they are replaced with default value here
+ // not-null fields they are replaced with default value here
$values_sql .= $this->Conn->qstr($this->Fields[$field_name]['default']);
}
else {
$values_sql .= $this->Conn->qstr($field_value);
}
}
else {
if (($field_name == $this->IDField) && ($field_value == 0) && !is_int($force_id)) {
// don't skip IDField in INSERT statement, just use DEFAULT keyword as it's value
$values_sql .= 'DEFAULT';
}
else {
$values_sql .= $this->Conn->qstr($field_value);
}
}
$fields_sql .= '`' . $field_name . '`, '; //Adding field name to fields block of Insert statement
$values_sql .= ', ';
}
$sql = 'INSERT INTO ' . $this->TableName . ' (' . substr($fields_sql, 0, -2) . ')
VALUES (' . substr($values_sql, 0, -2) . ')';
//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 into temp table (id is not auto-increment field)
$insert_id = $this->FieldValues[$this->IDField];
}
$this->setID($insert_id);
$this->OriginalFieldValues = $this->FieldValues;
if (!$system_create){
$this->setModifiedFlag(ChangeLog::CREATE);
}
$this->saveCustomFields();
if (!$this->IsTempTable()) {
$this->Application->resetCounters($this->TableName);
}
if ($this->IsTempTable() && ($this->Application->GetTopmostPrefix($this->Prefix) != $this->Prefix) && !is_int($force_id)) {
// temp table + subitem = set negative id
$this->setTempID();
}
$this->raiseEvent('OnAfterItemCreate');
$this->Loaded = true;
return true;
}
/**
- * Deletes the record from databse
- *
- * @access public
- * @return bool
- */
+ * Deletes the record from database
+ *
+ * @param int $id
+ * @return bool
+ * @access public
+ */
public function Delete($id = null)
{
- if (isset($id)) {
+ if ( isset($id) ) {
$this->setID($id);
}
- if (!$this->raiseEvent('OnBeforeItemDelete')) {
+ if ( !$this->raiseEvent('OnBeforeItemDelete') ) {
return false;
}
$sql = 'DELETE FROM ' . $this->TableName . '
WHERE ' . $this->GetKeyClause('Delete');
$ret = $this->Conn->ChangeQuery($sql);
$affected_rows = $this->Conn->getAffectedRows();
- if ($affected_rows > 0) {
+ if ( $affected_rows > 0 ) {
$this->setModifiedFlag(ChangeLog::DELETE); // will change affected rows, so get it before this line
// something was actually deleted
$this->raiseEvent('OnAfterItemDelete');
}
- if (!$this->IsTempTable()) {
+ if ( !$this->IsTempTable() ) {
$this->Application->resetCounters($this->TableName);
}
return $ret;
}
public function PopulateMultiLangFields()
{
foreach ($this->Fields as $field => $options) {
// master field is set only for CURRENT language
$formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false;
- if (($formatter == 'kMultiLanguage') && array_key_exists('master_field', $options) && array_key_exists('error_field', $options)) {
+ if ( ($formatter == 'kMultiLanguage') && isset($options['master_field']) && isset($options['error_field']) ) {
// MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode,
- // we display ML fields directly so we set it back to itself, otherwise error will not be displayed
- unset($this->Fields[$field]['error_field']);
+ // we display ML fields directly so we set it back to itself, otherwise error won't be displayed
+ unset( $this->Fields[$field]['error_field'] );
}
}
}
/**
* Sets new name for item in case if it is beeing copied
* in same table
*
* @param array $master Table data from TempHandler
* @param int $foreign_key ForeignKey value to filter name check query by
* @param string $title_field FieldName to alter, by default - TitleField of the prefix
* @param string $format sprintf-style format of renaming pattern, by default Copy %1$s of %2$s which makes it Copy [Number] of Original Name
* @access public
*/
public function NameCopy($master=null, $foreign_key=null, $title_field=null, $format='Copy %1$s of %2$s')
{
if (!isset($title_field)) {
$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 {
if ( preg_match('/'.sprintf($format, '([0-9]*) *', '(.*)').'/', $new_name, $regs) ) {
$new_name = sprintf($format, ($regs[1]+1), $regs[2]);
}
elseif ($original_checked) {
$new_name = sprintf($format, '', $new_name);
}
// 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);
}
protected function raiseEvent($name, $id = null, $additional_params = Array())
{
if( !isset($id) ) $id = $this->GetID();
$event = new kEvent( Array('name'=>$name,'prefix'=>$this->Prefix,'special'=>$this->Special) );
$event->setEventParam('id', $id);
if ($additional_params) {
foreach ($additional_params as $ap_name => $ap_value) {
$event->setEventParam($ap_name, $ap_value);
}
}
$this->Application->HandleEvent($event);
return $event->status == kEvent::erSUCCESS ? true : false;
}
/**
* Set's new ID for item
*
* @param int $new_id
* @access public
*/
public function setID($new_id)
{
$this->ID = $new_id;
$this->SetDBField($this->IDField, $new_id);
}
/**
* Generate and set new temporary id
*
* @access private
*/
public function setTempID()
{
$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());
if ($this->ShouldLogChanges(true)) {
// Updating TempId in ChangesLog, if changes are disabled
$ses_var_name = $this->Application->GetTopmostPrefix($this->Prefix) . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$changes = $this->Application->RecallVar($ses_var_name);
$changes = $changes ? unserialize($changes) : Array ();
if ($changes) {
foreach ($changes as $key => $rec) {
if ($rec['Prefix'] == $this->Prefix && $rec['ItemId'] == $this->GetID()) {
// change log for record, that's ID was just updated -> update in change log record too
$changes[$key]['ItemId'] = $new_id;
}
if ($rec['MasterPrefix'] == $this->Prefix && $rec['MasterId'] == $this->GetID()) {
// master item id was changed
$changes[$key]['MasterId'] = $new_id;
}
if (in_array($this->Prefix, $rec['ParentPrefix']) && $rec['ParentId'][$this->Prefix] == $this->GetID()) {
// change log record of given item's sub item -> update changed id's in dependent fields
$changes[$key]['ParentId'][$this->Prefix] = $new_id;
if (array_key_exists('DependentFields', $rec)) {
// these are fields from table of $rec['Prefix'] table!
// when one of dependent fields goes into idfield of it's parent item, that was changed
$parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey');
$parent_table_key = is_array($parent_table_key) ? $parent_table_key[$this->Prefix] : $parent_table_key;
if ($parent_table_key == $this->IDField) {
$foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey');
$foreign_key = is_array($foreign_key) ? $foreign_key[$this->Prefix] : $foreign_key;
$changes[$key]['DependentFields'][$foreign_key] = $new_id;
}
}
}
}
}
$this->Application->StoreVar($ses_var_name, serialize($changes));
}
$this->SetID($new_id);
}
/**
* Set's modification flag for main prefix of current prefix to true
*
* @access private
* @author Alexey
*/
public function setModifiedFlag($mode = null)
{
$main_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
$this->Application->StoreVar($main_prefix . '_modified', '1', true); // true for optional
if ($this->ShouldLogChanges(true)) {
$this->LogChanges($main_prefix, $mode);
if (!$this->IsTempTable()) {
$handler =& $this->Application->recallObject($this->Prefix . '_EventHandler');
/* @var $handler kDBEventHandler */
$ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$handler->SaveLoggedChanges($ses_var_name, $this->ShouldLogChanges());
}
}
}
/**
* Determines, that changes made to this item should be written to change log
*
* @param bool $log_changes
* @return bool
*/
public function ShouldLogChanges($log_changes = null)
{
if (!isset($log_changes)) {
// specific logging mode no forced -> use global logging settings
$log_changes = $this->Application->getUnitOption($this->Prefix, 'LogChanges') || $this->Application->ConfigValue('UseChangeLog');
}
return $log_changes && !$this->Application->getUnitOption($this->Prefix, 'ForceDontLogChanges');
}
protected function LogChanges($main_prefix, $mode)
{
- if (!$mode) {
+ if ( !$mode ) {
return ;
}
$ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$changes = $this->Application->RecallVar($ses_var_name);
$changes = $changes ? unserialize($changes) : Array ();
$fields_hash = Array (
'Prefix' => $this->Prefix,
'ItemId' => $this->GetID(),
'OccuredOn' => adodb_mktime(),
'MasterPrefix' => $main_prefix,
'Action' => $mode,
);
- if ($this->Prefix == $main_prefix) {
+ if ( $this->Prefix == $main_prefix ) {
// main item
$fields_hash['MasterId'] = $this->GetID();
$fields_hash['ParentPrefix'] = Array ($main_prefix);
$fields_hash['ParentId'] = Array ($main_prefix => $this->GetID());
}
else {
// sub item
// collect foreign key values (for serial reset)
- $foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey');
+ $foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey', Array ());
$dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array ();
+ /* @var $foreign_keys Array */
- if (is_array($foreign_keys)) {
+ if ( is_array($foreign_keys) ) {
foreach ($foreign_keys as $prefix => $field_name) {
$dependent_fields[$field_name] = $this->GetDBField($field_name);
$fields_hash['ParentPrefix'][] = $prefix;
$fields_hash['ParentId'][$prefix] = $this->getParentId($prefix);
}
}
else {
$dependent_fields[$foreign_keys] = $this->GetDBField($foreign_keys);
$fields_hash['ParentPrefix'] = Array ( $this->Application->getUnitOption($this->Prefix, 'ParentPrefix') );
$fields_hash['ParentId'][ $fields_hash['ParentPrefix'][0] ] = $this->getParentId('auto');
}
$fields_hash['DependentFields'] = $dependent_fields;
- // works only, when main item is present in url, when subitem is changed
+ // works only, when main item is present in url, when sub-item is changed
$master_id = $this->Application->GetVar($main_prefix . '_id');
- if ($master_id === false) {
- // works in case of we are not editing topmost item, when subitem is created/updated/deleted
+ if ( $master_id === false ) {
+ // works in case of we are not editing topmost item, when sub-item is created/updated/deleted
$master_id = $this->getParentId('auto', true);
}
$fields_hash['MasterId'] = $master_id;
}
- switch ($mode) {
+ switch ( $mode ) {
case ChangeLog::UPDATE:
$to_save = array_merge($this->GetTitleField(), $this->GetChangedFields());
break;
case ChangeLog::CREATE:
$to_save = $this->GetTitleField();
break;
case ChangeLog::DELETE:
$to_save = array_merge($this->GetTitleField(), $this->GetRealFields());
break;
+
+ default:
+ $to_save = Array ();
+ break;
}
$fields_hash['Changes'] = serialize($to_save);
$changes[] = $fields_hash;
$this->Application->StoreVar($ses_var_name, serialize($changes));
}
/**
* Returns current item parent's ID
*
* @param bool $top_most return topmost parent, when used
* @return int
*/
protected function getParentId($parent_prefix, $top_most = false)
{
$current_id = $this->GetID();
$current_prefix = $this->Prefix;
if ($parent_prefix == 'auto') {
$parent_prefix = $this->Application->getUnitOption($current_prefix, 'ParentPrefix');
}
if (!$parent_prefix) {
return $current_id;
}
do {
// field in this table
$foreign_key = $this->Application->getUnitOption($current_prefix, 'ForeignKey');
$foreign_key = is_array($foreign_key) ? $foreign_key[$parent_prefix] : $foreign_key;
// get foreign key value for $current_prefix
if ($current_prefix == $this->Prefix) {
$foreign_key_value = $this->GetDBField($foreign_key);
}
else {
$id_field = $this->Application->getUnitOption($current_prefix, 'IDField');
$table_name = $this->Application->getUnitOption($current_prefix, 'TableName');
if ($this->IsTempTable()) {
$table_name = $this->Application->GetTempName($table_name, 'prefix:' . $current_prefix);
}
$sql = 'SELECT ' . $foreign_key . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' = ' . $current_id;
$foreign_key_value = $this->Conn->GetOne($sql);
}
// field in parent table
$parent_table_key = $this->Application->getUnitOption($current_prefix, 'ParentTableKey');
$parent_table_key = is_array($parent_table_key) ? $parent_table_key[$parent_prefix] : $parent_table_key;
$parent_id_field = $this->Application->getUnitOption($parent_prefix, 'IDField');
$parent_table_name = $this->Application->getUnitOption($parent_prefix, 'TableName');
if ($this->IsTempTable()) {
$parent_table_name = $this->Application->GetTempName($parent_table_name, 'prefix:' . $current_prefix);
}
if ($parent_id_field == $parent_table_key) {
// sub-item is related by parent item idfield
$current_id = $foreign_key_value;
}
else {
// sub-item is related by other parent item field
$sql = 'SELECT ' . $parent_id_field . '
FROM ' . $parent_table_name . '
WHERE ' . $parent_table_key . ' = ' . $foreign_key_value;
$current_id = $this->Conn->GetOne($sql);
}
$current_prefix = $parent_prefix;
if (!$top_most) {
break;
}
} while ( $parent_prefix = $this->Application->getUnitOption($current_prefix, 'ParentPrefix') );
return $current_id;
}
/**
* Returns title field (if any)
*
* @return Array
*/
public function GetTitleField()
{
$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
if ($title_field) {
$value = $this->GetField($title_field);
return $value ? Array ($title_field => $value) : Array ();
}
return Array ();
}
/**
* Returns only fields, that are present in database (no virtual and no calculated fields)
*
* @return Array
*/
public function GetRealFields()
{
- if (function_exists('array_diff_key')) {
- $db_fields = array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields);
- }
- else {
- $db_fields = Array();
-
- foreach ($this->FieldValues as $key => $value) {
- if (array_key_exists($key, $this->VirtualFields) || array_key_exists($key, $this->CalculatedFields)) {
- continue;
- }
-
- $db_fields[$key] = $value;
- }
- }
-
- return $db_fields;
+ return array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields);
}
/**
* Returns only changed database field
*
* @param bool $include_virtual_fields
* @return Array
*/
public function GetChangedFields($include_virtual_fields = false)
{
$changes = Array ();
$fields = $include_virtual_fields ? $this->FieldValues : $this->GetRealFields();
$diff = array_diff_assoc($fields, $this->OriginalFieldValues);
foreach ($diff as $field => $new_value) {
$old_value = $this->GetOriginalField($field, true);
$new_value = $this->GetField($field);
if ($old_value != $new_value) {
// "0.00" and "0.0000" are stored as strings and will differ. Double check to prevent that.
$changes[$field] = Array ('old' => $old_value, 'new' => $new_value);
}
}
return $changes;
}
/**
* Returns ID of currently processed record
*
* @return int
* @access public
*/
public function GetID()
{
return $this->ID;
}
/**
* Generates ID for new items before inserting into database
*
* @return int
* @access private
*/
protected function generateID()
{
return 0;
}
/**
* Returns true if item was loaded successfully by Load method
*
* @return bool
*/
public function isLoaded()
{
return $this->Loaded;
}
/**
* Checks if field is required
*
* @param string $field
* @return bool
*/
public function isRequired($field)
{
return isset($this->Fields[$field]['required']) && $this->Fields[$field]['required'];
}
/**
* Sets new required flag to field
*
- * @param string $field
+ * @param mixed $fields
* @param bool $is_required
*/
- public function setRequired($field, $is_required = true)
+ public function setRequired($fields, $is_required = true)
{
- $this->Fields[$field]['required'] = $is_required;
+ if ( !is_array($fields) ) {
+ $fields = explode(',', $fields);
+ }
+
+ foreach ($fields as $field) {
+ $this->Fields[$field]['required'] = $is_required;
+ }
}
+ /**
+ * Removes all data from an object
+ *
+ * @param int $new_id
+ * @return bool
+ * @access public
+ */
public function Clear($new_id = null)
{
$this->Loaded = false;
- $this->FieldValues = Array();
- $this->OriginalFieldValues = Array ();
+ $this->FieldValues = $this->OriginalFieldValues = Array ();
$this->SetDefaultValues(); // will wear off kDBItem::setID effect, so set it later
- $this->FieldErrors = Array();
+
+ if ( is_object($this->validator) ) {
+ $this->validator->reset();
+ }
$this->setID($new_id);
return $this->Loaded;
}
public function Query($force = false)
{
throw new Exception('<b>Query</b> method is called in class <strong>' . get_class($this) . '</strong> for prefix <strong>' . $this->getPrefixSpecial() . '</strong>');
}
protected function saveCustomFields()
{
- if (!$this->customFields || $this->inCloning) {
+ if ( !$this->customFields || $this->inCloning ) {
return true;
}
$cdata_key = rtrim($this->Prefix . '-cdata.' . $this->Special, '.');
- $cdata =& $this->Application->recallObject($cdata_key, null, Array('skip_autoload' => true));
+ $cdata =& $this->Application->recallObject($cdata_key, null, Array ('skip_autoload' => true, 'populate_ml_fields' => true));
/* @var $cdata kDBItem */
$resource_id = $this->GetDBField('ResourceId');
$cdata->Load($resource_id, 'ResourceId');
$cdata->SetDBField('ResourceId', $resource_id);
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
/* @var $ml_formatter kMultiLanguage */
- $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
- /* @var $ml_helper kMultiLanguageHelper */
-
foreach ($this->customFields as $custom_id => $custom_name) {
- $field_options = $cdata->GetFieldOptions('cust_' . $custom_id);
- $force_primary = isset($field_options['force_primary']) && $field_options['force_primary'];
-
- if ($force_primary) {
- $cdata->SetDBField($ml_formatter->LangFieldName('cust_' . $custom_id, true), $this->GetDBField('cust_' . $custom_name));
- }
- else {
- for ($language_id = 1; $language_id <= $ml_helper->languageCount; $language_id++) {
- if (!$ml_helper->LanguageFound($language_id)) {
- continue;
- }
-
- $cdata->SetDBField('l' . $language_id . '_cust_' . $custom_id, $this->GetDBField('l' . $language_id . '_cust_' . $custom_name));
- }
- }
+ $force_primary = $cdata->GetFieldOption('cust_' . $custom_id, 'force_primary');
+ $cdata->SetDBField($ml_formatter->LangFieldName('cust_' . $custom_id, $force_primary), $this->GetDBField('cust_' . $custom_name));
}
return $cdata->isLoaded() ? $cdata->Update() : $cdata->Create();
}
/**
* Returns specified field value from all selected rows.
* Don't affect current record index
*
* @param string $field
* @param bool $formatted
* @param string $format
* @return Array
*/
public function GetCol($field, $formatted = false, $format = null)
{
if ($formatted) {
return Array (0 => $this->GetField($field, $format));
}
return Array (0 => $this->GetDBField($field));
}
/**
* Set's loaded status of object
*
* @param bool $is_loaded
* @access public
* @todo remove this method, since item can't be marked as loaded externally
*/
public function setLoaded($is_loaded = true)
{
$this->Loaded = $is_loaded;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/application.php
===================================================================
--- branches/5.2.x/core/kernel/application.php (revision 14595)
+++ branches/5.2.x/core/kernel/application.php (revision 14596)
@@ -1,2662 +1,2714 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
/**
* Basic class for Kernel4-based Application
*
* This class is a Facade for any other class which needs to deal with Kernel4 framework.<br>
* The class incapsulates the main run-cycle of the script, provide access to all other objects in the framework.<br>
* <br>
* The class is a singleton, which means that there could be only one instance of kApplication in the script.<br>
-* This could be guranteed by NOT calling the class constuctor directly, but rather calling kApplication::Instance() method,
-* which returns an instance of the application. The method gurantees that it will return exactly the same instance for any call.<br>
+* This could be guaranteed by NOT calling the class constructor directly, but rather calling kApplication::Instance() method,
+* which returns an instance of the application. The method guarantees that it will return exactly the same instance for any call.<br>
* See singleton pattern by GOF.
*/
class kApplication implements kiCacheable {
/**
* Is true, when Init method was called already, prevents double initialization
*
* @var bool
*/
var $InitDone = false;
/**
* Holds internal NParser object
* @access private
* @var NParser
*/
var $Parser;
/**
* Holds parser output buffer
* @access private
* @var string
*/
var $HTML;
/**
* Prevents request from beeing proceeded twice in case if application init is called mere then one time
*
* @var bool
* @todo This is not good anyway (by Alex)
*/
var $RequestProcessed = false;
/**
* The main Factory used to create
* almost any class of kernel and
* modules
*
* @access private
* @var kFactory
*/
var $Factory;
/**
* Template names, that will be used instead of regular templates
*
* @var Array
*/
var $ReplacementTemplates = Array ();
/**
* Mod-Rewrite listeners used during url building and parsing
*
* @var Array
*/
var $RewriteListeners = Array ();
/**
* Reference to debugger
*
* @var Debugger
*/
var $Debugger = null;
/**
* Holds all phrases used
* in code and template
*
* @var PhrasesCache
*/
var $Phrases;
/**
* Modules table content, key - module name
*
* @var Array
*/
var $ModuleInfo = Array();
/**
* Holds DBConnection
*
* @var kDBConnection
*/
var $Conn = null;
/**
* Maintains list of user-defined error handlers
*
* @var Array
*/
var $errorHandlers = Array();
/**
* Maintains list of user-defined exception handlers
*
* @var Array
*/
var $exceptionHandlers = Array();
// performance needs:
/**
* Holds a refererence to httpquery
*
* @var kHttpQuery
*/
var $HttpQuery = null;
/**
* Holds a reference to UnitConfigReader
*
* @var kUnitConfigReader
*/
var $UnitConfigReader = null;
/**
* Holds a reference to Session
*
* @var Session
*/
var $Session = null;
/**
* Holds a ref to kEventManager
*
* @var kEventManager
*/
var $EventManager = null;
/**
* Holds a ref to kUrlManager
*
* @var kUrlManager
* @access protected
*/
protected $UrlManager = null;
/**
* Ref for TemplatesChache
*
* @var TemplatesCache
*/
var $TemplatesCache = null;
var $CompilationCache = array(); //used when compiling templates
var $CachedProcessors = array(); //used when running compiled templates
var $LambdaElements = 1; // for autonumbering unnamed RenderElements [any better place for this prop? KT]
/**
* Holds current NParser tag while parsing, can be used in error messages to display template file and line
*
* @var _BlockTag
*/
var $CurrentNTag = null;
/**
* Object of unit caching class
*
* @var kCacheManager
*/
var $cacheManager = null;
/**
- * Tells, that administrator has authentificated in administrative console
- * Should be used to manipulate data change OR data restrictioning!
+ * Tells, that administrator has authenticated in administrative console
+ * Should be used to manipulate data change OR data restrictions!
*
* @var bool
*/
var $isAdminUser = false;
/**
* Tells, that admin version of "index.php" was used, nothing more!
* Should be used to manipulate data display!
*
* @var bool
*/
var $isAdmin = false;
/**
* Instance of site domain object
*
* @var kDBItem
*/
var $siteDomain = null;
/**
* Prevent kApplication class to be created directly, only via Instance method
*
*/
protected function __construct()
{
}
/**
* Returns kApplication instance anywhere in the script.
*
* This method should be used to get single kApplication object instance anywhere in the
- * Kernel-based application. The method is guranteed to return the SAME instance of kApplication.
+ * Kernel-based application. The method is guaranteed to return the SAME instance of kApplication.
* Anywhere in the script you could write:
* <code>
* $application =& kApplication::Instance();
* </code>
* or in an object:
* <code>
* $this->Application =& kApplication::Instance();
* </code>
* to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class.
- * To use descendand of standard kApplication class in your project you would need to define APPLICATION_CLASS constant
+ * To use descendant of standard kApplication class in your project you would need to define APPLICATION_CLASS constant
* BEFORE calling kApplication::Instance() for the first time. If APPLICATION_CLASS is not defined the method would
* create and return default KernelApplication instance.
*
* Pattern: Singleton
*
* @static
* @access public
* @return kApplication
*/
public static function &Instance()
{
static $instance = false;
if (!$instance) {
$class = defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication';
$instance = new $class();
$instance->Application =& $instance;
}
return $instance;
}
/**
* Initializes the Application
*
* @access public
* @see kHTTPQuery
* @see Session
* @see TemplatesCache
* @return bool Was Init actually made now or before
*/
public function Init()
{
- if($this->InitDone) {
+ if ( $this->InitDone ) {
return false;
}
$this->isAdmin = kUtil::constOn('ADMIN');
if ( !kUtil::constOn('SKIP_OUT_COMPRESSION') ) {
ob_start(); // collect any output from method (other then tags) into buffer
}
- if (defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY')) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Init:');
}
- if (!$this->isDebugMode() && !kUtil::constOn('DBG_ZEND_PRESENT')) {
+ if ( !$this->isDebugMode() && !kUtil::constOn('DBG_ZEND_PRESENT') ) {
error_reporting(0);
ini_set('display_errors', 0);
}
- if (!kUtil::constOn('DBG_ZEND_PRESENT')) {
- $error_handler = set_error_handler( Array (&$this, 'handleError') );
- if ($error_handler) {
+ if ( !kUtil::constOn('DBG_ZEND_PRESENT') ) {
+ $error_handler = set_error_handler(Array (&$this, 'handleError'));
+ if ( $error_handler ) {
// wrap around previous error handler, if any was set
$this->errorHandlers[] = $error_handler;
}
- $exception_handler = set_exception_handler( Array (&$this, 'handleException') );
- if ($exception_handler) {
+ $exception_handler = set_exception_handler(Array (&$this, 'handleException'));
+ if ( $exception_handler ) {
// wrap around previous exception handler, if any was set
$this->exceptionHandlers[] = $exception_handler;
}
}
$this->Factory = new kFactory();
$this->registerDefaultClasses();
- $this->Conn =& $this->Factory->makeClass( 'kDBConnection', Array (SQL_TYPE, Array (&$this, 'handleSQLError')) );
+ $this->Conn =& $this->Factory->makeClass('kDBConnection', Array (SQL_TYPE, Array (&$this, 'handleSQLError')));
$this->Conn->debugMode = $this->isDebugMode();
$this->Conn->Connect(SQL_SERVER, SQL_USER, SQL_PASS, SQL_DB);
$this->cacheManager =& $this->makeClass('kCacheManager');
$this->cacheManager->InitCache();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Before UnitConfigReader');
}
$this->UnitConfigReader =& $this->makeClass('kUnitConfigReader');
$this->UnitConfigReader->scanModules(MODULES_PATH);
$this->registerModuleConstants();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('After UnitConfigReader');
}
define('MOD_REWRITE', $this->ConfigValue('UseModRewrite') && !$this->isAdmin ? 1 : 0);
$this->HttpQuery =& $this->recallObject('HTTPQuery');
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery initial');
}
$this->Session =& $this->recallObject('Session');
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed Session');
}
- if (!$this->RecallVar('UserGroups')) {
+ if ( !$this->RecallVar('UserGroups') ) {
$user_groups = trim($this->Session->GetField('GroupList'), ',');
- if (!$user_groups) {
+ if ( !$user_groups ) {
$user_groups = $this->ConfigValue('User_GuestGroup');
}
$this->Session->SetField('GroupList', $user_groups);
$this->StoreVar('UserGroups', $user_groups, true); // true for optional
}
$this->UrlManager->LoadStructureTemplateMapping();
$this->HttpQuery->AfterInit();
$this->Session->ValidateExpired();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit');
}
$this->cacheManager->LoadApplicationCache();
$site_timezone = $this->ConfigValue('Config_Site_Time');
- if ($site_timezone) {
+ if ( $site_timezone ) {
putenv('TZ=' . $site_timezone);
}
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Loaded cache and phrases');
}
$this->ValidateLogin(); // must be called before AfterConfigRead, because current user should be available there
$this->UnitConfigReader->AfterConfigRead();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed AfterConfigRead');
}
- if ($this->GetVar('m_cat_id') === false) {
+ if ( $this->GetVar('m_cat_id') === false ) {
$this->SetVar('m_cat_id', 0);
}
- if (!$this->RecallVar('curr_iso')) {
+ if ( !$this->RecallVar('curr_iso') ) {
$this->StoreVar('curr_iso', $this->GetPrimaryCurrency(), true); // true for optional
}
$visit_id = $this->RecallVar('visit_id');
- if ($visit_id !== false) {
+ if ( $visit_id !== false ) {
$this->SetVar('visits_id', $visit_id);
}
- $language =& $this->recallObject( 'lang.current', null, Array('live_table' => true) );
- if (preg_match('/utf-8/', $language->GetDBField('Charset'))) {
+ $language =& $this->recallObject('lang.current', null, Array ('live_table' => true));
+ /* @var $language LanguagesItem */
+
+ if ( preg_match('/utf-8/', $language->GetDBField('Charset')) ) {
setlocale(LC_ALL, 'en_US.UTF-8');
mb_internal_encoding('UTF-8');
}
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->profileFinish('kernel4_startup');
}
$this->InitDone = true;
- $this->HandleEvent( new kEvent('adm:OnStartup') );
+ $this->HandleEvent(new kEvent('adm:OnStartup'));
return true;
}
function InitManagers()
{
if ($this->InitDone) {
throw new Exception('Duplicate call of ' . __METHOD__, E_USER_ERROR);
return ;
}
$this->UrlManager =& $this->makeClass('kUrlManager');
$this->EventManager =& $this->makeClass('EventManager');
$this->Phrases =& $this->makeClass('kPhraseCache');
$this->RegisterDefaultBuildEvents();
}
/**
* Returns module information. Searches module by requested field
*
* @param string $field
* @param mixed $value
* @param string field value to returns, if not specified, then return all fields
* @param string field to return
* @return Array
*/
function findModule($field, $value, $return_field = null)
{
$found = false;
foreach ($this->ModuleInfo as $module_name => $module_info) {
if (strtolower($module_info[$field]) == strtolower($value)) {
$found = true;
break;
}
}
if ($found) {
return isset($return_field) ? $module_info[$return_field] : $module_info;
}
return false;
}
- function refreshModuleInfo()
+ /**
+ * Refreshes information about loaded modules
+ *
+ * @return void
+ * @access public
+ */
+ public function refreshModuleInfo()
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules')) {
$this->registerModuleConstants();
- return false;
+ return ;
}
$modules_helper =& $this->makeClass('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Modules
WHERE ' . $modules_helper->getWhereClause() . '
ORDER BY LoadOrder';
$this->ModuleInfo = $this->Conn->Query($sql, 'Name');
$this->registerModuleConstants();
}
/**
* Checks if passed language id if valid and sets it to primary otherwise
*
*/
function VerifyLanguageId()
{
$language_id = $this->GetVar('m_lang');
if (!$language_id) {
$language_id = 'default';
}
$this->SetVar('lang.current_id', $language_id);
$this->SetVar('m_lang', $language_id);
$lang_mode = $this->GetVar('lang_mode');
$this->SetVar('lang_mode', '');
$lang =& $this->recallObject('lang.current');
/* @var $lang kDBItem */
if (!$lang->isLoaded() || (!$this->isAdmin && !$lang->GetDBField('Enabled'))) {
if (!defined('IS_INSTALL')) {
$this->ApplicationDie('Unknown or disabled language');
}
}
$this->SetVar('lang_mode',$lang_mode);
}
/**
* Checks if passed theme id if valid and sets it to primary otherwise
*
*/
function VerifyThemeId()
{
if ($this->isAdmin) {
kUtil::safeDefine('THEMES_PATH', '/core/admin_templates');
return;
}
$path = $this->GetFrontThemePath();
if ($path === false) {
$this->ApplicationDie('No Primary Theme Selected or Current Theme is Unknown or Disabled');
}
kUtil::safeDefine('THEMES_PATH', $path);
}
function GetFrontThemePath($force=0)
{
- static $path=null;
- if (!$force && isset($path)) return $path;
+ static $path = null;
+
+ if ( !$force && isset($path) ) {
+ return $path;
+ }
$theme_id = $this->GetVar('m_theme');
- if (!$theme_id) {
+ if ( !$theme_id ) {
// $theme_id = $this->GetDefaultThemeId(1); //1 to force front-end mode!
$theme_id = 'default';
}
+
$this->SetVar('m_theme', $theme_id);
- $this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId
+ $this->SetVar('theme.current_id', $theme_id); // KOSTJA: this is to fool theme' getPassedId
$theme =& $this->recallObject('theme.current');
- if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) {
+ /* @var $theme ThemeItem */
+
+ if ( !$theme->isLoaded() || !$theme->GetDBField('Enabled') ) {
return false;
}
- $path = '/themes/'.$theme->GetDBField('Name');
+
+ // assign & then return, since it's static variable
+ $path = '/themes/' . $theme->GetDBField('Name');
+
return $path;
}
function GetDefaultLanguageId($init = false)
{
$cache_key = 'primary_language_info[%LangSerial%]';
$language_info = $this->getCache($cache_key);
if ($language_info === false) {
// cache primary language info first
$table = $this->getUnitOption('lang', 'TableName');
$id_field = $this->getUnitOption('lang', 'IDField');
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT ' . $id_field . ', IF(AdminInterfaceLang, "Admin", "Front") AS LanguageKey
FROM ' . $table . '
WHERE (AdminInterfaceLang = 1 OR PrimaryLang = 1) AND (Enabled = 1)';
$language_info = $this->Conn->GetCol($sql, 'LanguageKey');
if ($language_info !== false) {
$this->setCache($cache_key, $language_info);
}
}
$language_key = ($this->isAdmin && $init) || count($language_info) == 1 ? 'Admin' : 'Front';
if (array_key_exists($language_key, $language_info) && $language_info[$language_key] > 0) {
// get from cache
return $language_info[$language_key];
}
$language_id = $language_info && array_key_exists($language_key, $language_info) ? $language_info[$language_key] : false;
if (!$language_id && defined('IS_INSTALL') && IS_INSTALL) {
$language_id = 1;
}
return $language_id;
}
function GetDefaultThemeId($force_front=0)
{
static $theme_id = 0;
if ($theme_id > 0) {
return $theme_id;
}
if (kUtil::constOn('DBG_FORCE_THEME')) {
$theme_id = DBG_FORCE_THEME;
}
elseif (!$force_front && $this->isAdmin) {
$theme_id = 999;
}
else {
$cache_key = 'primary_theme[%ThemeSerial%]';
$theme_id = $this->getCache($cache_key);
if ($theme_id === false) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT ' . $this->getUnitOption('theme', 'IDField') . '
FROM ' . $this->getUnitOption('theme', 'TableName') . '
WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
$theme_id = $this->Conn->GetOne($sql);
if ($theme_id !== false) {
$this->setCache($cache_key, $theme_id);
}
}
}
return $theme_id;
}
/**
* Returns site primary currency ISO code
*
* @return string
*/
function GetPrimaryCurrency()
{
$cache_key = 'primary_currency[%CurrSerial%][%SiteDomainSerial%]:' . $this->siteDomainField('DomainId');
$currency_iso = $this->getCache($cache_key);
if ($currency_iso === false) {
if ($this->isModuleEnabled('In-Commerce')) {
$this->Conn->nextQueryCachable = true;
$currency_id = $this->siteDomainField('PrimaryCurrencyId');
$sql = 'SELECT ISO
FROM ' . $this->getUnitOption('curr', 'TableName') . '
WHERE ' . ($currency_id > 0 ? 'CurrencyId = ' . $currency_id : 'IsPrimary = 1');
$currency_iso = $this->Conn->GetOne($sql);
}
else {
$currency_iso = 'USD';
}
$this->setCache($cache_key, $currency_iso);
}
return $currency_iso;
}
/**
* Returns site domain field. When none of site domains are found false is returned.
*
* @param string $field
* @param bool $formatted
* @param string $format
*/
function siteDomainField($field, $formatted = false, $format = null)
{
if ($this->isAdmin) {
// don't apply any filtering in administrative console
return false;
}
if (!$this->siteDomain) {
$this->siteDomain =& $this->recallObject('site-domain.current');
/* @var $site_domain kDBItem */
}
if ($this->siteDomain->isLoaded()) {
return $formatted ? $this->siteDomain->GetField($field, $format) : $this->siteDomain->GetDBField($field);
}
return false;
}
/**
* Registers default classes such as ItemController, GridController and LoginController
*
* Called automatically while initializing Application
* @access private
* @return void
*/
function RegisterDefaultClasses()
{
$this->registerClass('kHelper', KERNEL_PATH . '/kbase.php');
$this->registerClass('kMultipleFilter', KERNEL_PATH . '/utility/filters.php');
$this->registerClass('kiCacheable', KERNEL_PATH . '/interfaces/cacheable.php', 'kiCacheable');
$this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager', 'kiCacheable');
$this->registerClass('kHookManager', KERNEL_PATH . '/managers/hook_manager.php', null, 'kiCacheable');
$this->registerClass('kAgentManager', KERNEL_PATH . '/managers/agent_manager.php', null, 'kiCacheable');
$this->registerClass('kRequestManager', KERNEL_PATH . '/managers/request_manager.php');
$this->registerClass('kUrlManager', KERNEL_PATH . '/managers/url_manager.php');
$this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php', null, 'kiCacheable');
$this->registerClass('PhrasesCache', KERNEL_PATH . '/languages/phrases_cache.php', 'kPhraseCache');
$this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php');
+ $this->registerClass('kValidator', KERNEL_PATH . '/utility/validator.php');
$this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php');
// Params class descendants
$this->registerClass('kArray', KERNEL_PATH . '/utility/params.php');
$this->registerClass('Params', KERNEL_PATH . '/utility/params.php');
$this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions');
$this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'kCache', 'Params');
$this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery', 'Params');
// session
$this->registerClass('Session', KERNEL_PATH . '/session/session.php');
$this->registerClass('SessionStorage', KERNEL_PATH . '/session/session_storage.php');
$this->registerClass('InpSession', KERNEL_PATH . '/session/inp_session.php', 'Session');
$this->registerClass('InpSessionStorage', KERNEL_PATH . '/session/inp_session_storage.php', 'SessionStorage');
// template parser
$this->registerClass('kTagProcessor', KERNEL_PATH . '/processors/tag_processor.php');
$this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php', 'm_TagProcessor', 'kTagProcessor');
$this->registerClass('kDBTagProcessor', KERNEL_PATH . '/db/db_tag_processor.php', null, 'kTagProcessor');
$this->registerClass('kCatDBTagProcessor', KERNEL_PATH . '/db/cat_tag_processor.php', null, 'kDBTagProcessor');
$this->registerClass('NParser', KERNEL_PATH . '/nparser/nparser.php');
$this->registerClass('TemplatesCache', KERNEL_PATH . '/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor'));
// database
$this->registerClass('kDBConnection', KERNEL_PATH . '/db/db_connection.php');
$this->registerClass('kDBItem', KERNEL_PATH . '/db/dbitem.php');
$this->registerClass('kCatDBItem', KERNEL_PATH . '/db/cat_dbitem.php', null, 'kDBItem');
$this->registerClass('kDBList', KERNEL_PATH . '/db/dblist.php');
$this->registerClass('kCatDBList', KERNEL_PATH . '/db/cat_dblist.php', null, 'kDBList');
$this->registerClass('kDBEventHandler', KERNEL_PATH . '/db/db_event_handler.php');
$this->registerClass('kCatDBEventHandler', KERNEL_PATH . '/db/cat_event_handler.php', null, 'kDBEventHandler');
// email sending
$this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender', 'kHelper');
$this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket');
// do not move to config - this helper is used before configs are read
$this->registerClass('kModulesHelper', KERNEL_PATH . '/../units/helpers/modules_helper.php', 'ModulesHelper');
}
function RegisterDefaultBuildEvents()
{
$this->EventManager->registerBuildEvent('kTempTablesHandler', 'OnTempHandlerBuild');
}
/**
* Returns cached category informaton by given cache name. All given category
* information is recached, when at least one of 4 caches is missing.
*
* @param int $category_id
* @param string $name cache name = {filenames, category_designs, category_tree}
* @return string
* @access public
*/
public function getCategoryCache($category_id, $name)
{
return $this->cacheManager->getCategoryCache($category_id, $name);
}
/**
* Returns caching type (none, memory, temporary)
*
* @return int
* @access public
*/
public function isCachingType($caching_type)
{
return $this->cacheManager->isCachingType($caching_type);
}
/**
* Increments serial based on prefix and it's ID (optional)
*
* @param string $prefix
* @param int $id ID (value of IDField) or ForeignKeyField:ID
* @param bool $increment
* @access public
*/
public function incrementCacheSerial($prefix, $id = null, $increment = true)
{
return $this->cacheManager->incrementCacheSerial($prefix, $id, $increment);
}
/**
* Returns cached $key value from cache named $cache_name
*
* @param int $key key name from cache
* @param bool $store_locally store data locally after retrieved
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getCache($key, $store_locally = true, $max_rebuild_seconds = 0)
{
return $this->cacheManager->getCache($key, $store_locally, $max_rebuild_seconds);
}
/**
* Adds new value to cache $cache_name and identified by key $key
*
* @param int $key key name to add to cache
* @param mixed $value value of chached record
* @param int $expiration when value expires (0 - doesn't expire)
* @access public
*/
public function setCache($key, $value, $expiration = 0)
{
return $this->cacheManager->setCache($key, $value, $expiration);
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
*/
public function rebuildCache($name, $mode = null, $max_rebuilding_time = 0)
{
$this->cacheManager->rebuildCache($name, $mode, $max_rebuilding_time);
}
/**
* Deletes key from cache
*
* @param string $key
* @access public
*/
public function deleteCache($key)
{
$this->cacheManager->deleteCache($key);
}
/**
* Reset's all memory cache at once
*
* @access public
*/
public function resetCache()
{
$this->cacheManager->resetCache();
}
/**
* Returns value from database cache
*
* @param string $name key name
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getDBCache($name, $max_rebuild_seconds = 0)
{
return $this->cacheManager->getDBCache($name, $max_rebuild_seconds);
}
/**
* Sets value to database cache
*
* @param string $name
* @param mixed $value
* @param int|bool $expiration
* @access public
*/
public function setDBCache($name, $value, $expiration = false)
{
$this->cacheManager->setDBCache($name, $value, $expiration);
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
*/
public function rebuildDBCache($name, $mode = null, $max_rebuilding_time = 0)
{
$this->cacheManager->rebuildDBCache($name, $mode, $max_rebuilding_time);
}
/**
* Deletes key from database cache
*
* @param string $name
* @access public
*/
public function deleteDBCache($name)
{
$this->cacheManager->deleteDBCache($name);
}
/**
* Registers each module specific constants if any found
*
*/
function registerModuleConstants()
{
if (file_exists(KERNEL_PATH.'/constants.php')) {
kUtil::includeOnce(KERNEL_PATH.'/constants.php');
}
if (!$this->ModuleInfo) {
return false;
}
foreach ($this->ModuleInfo as $module_name => $module_info) {
$contants_file = FULL_PATH . '/' . $module_info['Path'] . 'constants.php';
if (file_exists($contants_file)) {
kUtil::includeOnce($contants_file);
}
}
return true;
}
function ProcessRequest()
{
if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_SHOW_HTTPQUERY') ) {
$this->Debugger->appendHTML('HTTPQuery:');
$this->Debugger->dumpVars($this->HttpQuery->_Params);
}
$this->EventManager->ProcessRequest();
$this->EventManager->runAgents(reBEFORE);
$this->RequestProcessed = true;
}
/**
* Actually runs the parser against current template and stores parsing result
*
* This method gets t variable passed to the script, loads the template given in t variable and
* parses it. The result is store in {@link $this->HTML} property.
* @access public
* @return void
*/
function Run()
{
if (defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Run:');
}
if ($this->isAdminUser) {
// for permission checking in events & templates
$this->LinkVar('module'); // for common configuration templates
$this->LinkVar('module_key'); // for common search templates
$this->LinkVar('section'); // for common configuration templates
if ($this->GetVar('m_opener') == 'p') {
$this->LinkVar('main_prefix'); // window prefix, that opened selector
$this->LinkVar('dst_field'); // field to set value choosed in selector
}
if ($this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax')) {
// hide debug output from ajax requests automatically
kUtil::safeDefine('DBG_SKIP_REPORTING', 1); // safeDefine, because debugger also defines it
}
}
elseif ($this->GetVar('admin')) {
// viewing front-end through admin's frame
$admin_session =& $this->recallObject('Session.admin');
+ /* @var $admin_session Session */
+
$user = (int)$admin_session->RecallVar('user_id'); // in case, when no valid admin session found
+
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
if ($perm_helper->CheckUserPermission($user, 'CATEGORY.MODIFY', 0, $this->getBaseCategory())) {
// user can edit cms blocks
$editing_mode = $this->GetVar('editing_mode');
define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_BROWSE);
}
}
kUtil::safeDefine('EDITING_MODE', ''); // user can't edit anything
$this->Phrases->setPhraseEditing();
if (!$this->RequestProcessed) $this->ProcessRequest();
$this->InitParser();
$t = $this->GetVar('t');
if (!$this->TemplatesCache->TemplateExists($t) && !$this->isAdmin) {
$cms_handler =& $this->recallObject('st_EventHandler');
/* @var $cms_handler CategoriesEventHandler */
$t = ltrim($cms_handler->GetDesignTemplate(), '/');
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendHTML('<strong>Design Template</strong>: ' . $t . '; <strong>CategoryID</strong>: ' . $this->GetVar('m_cat_id'));
}
}
/*else {
$cms_handler->SetCatByTemplate();
}*/
if (defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Parsing:');
}
$this->HTML = $this->Parser->Run($t);
if (defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application after Parsing:');
}
}
function InitParser($theme_name = false)
{
if( !is_object($this->Parser) ) {
$this->Parser =& $this->recallObject('NParser');
$this->TemplatesCache =& $this->recallObject('TemplatesCache');
}
$this->TemplatesCache->forceThemeName = $theme_name;
}
/**
* Send the parser results to browser
*
* Actually send everything stored in {@link $this->HTML}, to the browser by echoing it.
* @access public
* @return void
*/
function Done()
{
$this->HandleEvent( new kEvent('adm:OnBeforeShutdown') );
$debug_mode = defined('DEBUG_MODE') && $this->isDebugMode();
if ($debug_mode && kUtil::constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Done:');
}
if ($debug_mode) {
$this->EventManager->runAgents(reAFTER);
$this->Session->SaveData();
if (kUtil::constOn('DBG_CACHE')) {
$this->cacheManager->printStatistics();
}
$this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true);
}
else {
// send "Set-Cookie" header before any output is made
$this->Session->SetSession();
$this->HTML = ob_get_clean() . $this->HTML;
}
if ($this->UseOutputCompression()) {
$compression_level = $this->ConfigValue('OutputCompressionLevel');
if (!$compression_level || $compression_level < 0 || $compression_level > 9) {
$compression_level = 7;
}
header('Content-Encoding: gzip');
echo gzencode($this->HTML, $compression_level);
}
else {
echo $this->HTML;
}
$this->cacheManager->UpdateApplicationCache();
flush();
if (!$debug_mode) {
$this->EventManager->runAgents(reAFTER);
$this->Session->SaveData();
}
if (defined('DBG_CAPTURE_STATISTICS') && DBG_CAPTURE_STATISTICS && !$this->isAdmin) {
$this->_storeStatistics();
}
}
/**
* Stores script execution statistics to database
*
*/
function _storeStatistics()
{
global $start;
$script_time = microtime(true) - $start;
$query_statistics = $this->Conn->getQueryStatistics(); // time & count
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'StatisticsCapture
WHERE TemplateName = ' . $this->Conn->qstr( $this->GetVar('t') );
$data = $this->Conn->GetRow($sql);
if ($data) {
$this->_updateAverageStatistics($data, 'ScriptTime', $script_time);
$this->_updateAverageStatistics($data, 'SqlTime', $query_statistics['time']);
$this->_updateAverageStatistics($data, 'SqlCount', $query_statistics['count']);
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'StatisticsCapture', 'StatisticsId = ' . $data['StatisticsId']);
}
else {
$data['ScriptTimeMin'] = $data['ScriptTimeAvg'] = $data['ScriptTimeMax'] = $script_time;
$data['SqlTimeMin'] = $data['SqlTimeAvg'] = $data['SqlTimeMax'] = $query_statistics['time'];
$data['SqlCountMin'] = $data['SqlCountAvg'] = $data['SqlCountMax'] = $query_statistics['count'];
$data['TemplateName'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'StatisticsCapture');
}
}
/**
* Calculates average time for statistics
*
* @param Array $data
* @param string $field_prefix
* @param float $current_value
*/
function _updateAverageStatistics(&$data, $field_prefix, $current_value)
{
$data[$field_prefix . 'Avg'] = (($data['Hits'] * $data[$field_prefix . 'Avg']) + $current_value) / ($data['Hits'] + 1);
if ($current_value < $data[$field_prefix . 'Min']) {
$data[$field_prefix . 'Min'] = $current_value;
}
if ($current_value > $data[$field_prefix . 'Max']) {
$data[$field_prefix . 'Max'] = $current_value;
}
}
function logSlowQuery($slow_sql, $time)
{
$query_crc = crc32($slow_sql);
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'SlowSqlCapture
WHERE QueryCrc = ' . $query_crc;
$data = $this->Conn->Query($sql, null, true);
if ($data) {
$this->_updateAverageStatistics($data, 'Time', $time);
$template_names = explode(',', $data['TemplateNames']);
array_push($template_names, $this->GetVar('t'));
$data['TemplateNames'] = implode(',', array_unique($template_names));
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'SlowSqlCapture', 'CaptureId = ' . $data['CaptureId']);
}
else {
$data['TimeMin'] = $data['TimeAvg'] = $data['TimeMax'] = $time;
$data['SqlQuery'] = $slow_sql;
$data['QueryCrc'] = $query_crc;
$data['TemplateNames'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'SlowSqlCapture');
}
}
/**
* Checks if output compression options is available
*
* @return string
*/
function UseOutputCompression()
{
if (kUtil::constOn('IS_INSTALL') || kUtil::constOn('DBG_ZEND_PRESENT') || kUtil::constOn('SKIP_OUT_COMPRESSION')) {
return false;
}
return $this->ConfigValue('UseOutputCompression') && function_exists('gzencode') && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
}
// Facade
/**
* Returns current session id (SID)
* @access public
- * @return longint
+ * @return int
*/
function GetSID()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
return $session->GetID();
}
function DestroySession()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$session->Destroy();
}
/**
- * Returns variable passed to the script as GET/POST/COOKIE
- *
- * @access public
- * @param string $name Name of variable to retrieve
- * @param int $default default value returned in case if varible not present
- * @return mixed
- */
- function GetVar($name, $default = false)
+ * Returns variable passed to the script as GET/POST/COOKIE
+ *
+ * @param string $name Name of variable to retrieve
+ * @param mixed $default default value returned in case if variable not present
+ *
+ * @return mixed
+ * @access public
+ */
+ public function GetVar($name, $default = false)
{
return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default;
}
/**
* Returns ALL variables passed to the script as GET/POST/COOKIE
*
* @access public
* @return array
*/
function GetVars()
{
return $this->HttpQuery->GetParams();
}
/**
* Set the variable 'as it was passed to the script through GET/POST/COOKIE'
*
* This could be useful to set the variable when you know that
* other objects would relay on variable passed from GET/POST/COOKIE
* or you could use SetVar() / GetVar() pairs to pass the values between different objects.<br>
*
* This method is formerly known as $this->Session->SetProperty.
* @param string $var Variable name to set
* @param mixed $val Variable value
* @access public
* @return void
*/
- function SetVar($var,$val)
+ public function SetVar($var,$val)
{
- return $this->HttpQuery->Set($var, $val);
+ $this->HttpQuery->Set($var, $val);
}
/**
* Deletes kHTTPQuery variable
*
* @param string $var
* @todo think about method name
*/
function DeleteVar($var)
{
return $this->HttpQuery->Remove($var);
}
/**
* Deletes Session variable
*
* @param string $var
*/
function RemoveVar($var)
{
return $this->Session->RemoveVar($var);
}
function RemovePersistentVar($var)
{
return $this->Session->RemovePersistentVar($var);
}
/**
* Restores Session variable to it's db version
*
* @param string $var
*/
function RestoreVar($var)
{
return $this->Session->RestoreVar($var);
}
/**
* Returns session variable value
*
* Return value of $var variable stored in Session. An optional default value could be passed as second parameter.
*
* @see SimpleSession
* @access public
* @param string $var Variable name
* @param mixed $default Default value to return if no $var variable found in session
* @return mixed
*/
function RecallVar($var,$default=false)
{
return $this->Session->RecallVar($var,$default);
}
function RecallPersistentVar($var, $default = false)
{
return $this->Session->RecallPersistentVar($var, $default);
}
/**
* Stores variable $val in session under name $var
*
* Use this method to store variable in session. Later this variable could be recalled.
* @see RecallVar
* @access public
* @param string $var Variable name
* @param mixed $val Variable value
*/
function StoreVar($var, $val, $optional = false)
{
$session =& $this->recallObject('Session');
$this->Session->StoreVar($var, $val, $optional);
}
function StorePersistentVar($var, $val, $optional = false)
{
$this->Session->StorePersistentVar($var, $val, $optional);
}
function StoreVarDefault($var, $val, $optional=false)
{
$session =& $this->recallObject('Session');
$this->Session->StoreVarDefault($var, $val, $optional);
}
/**
* Links HTTP Query variable with session variable
*
* If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session.
* This method could be used for making sure that GetVar will return query or session value for given
* variable, when query variable should overwrite session (and be stored there for later use).<br>
* This could be used for passing item's ID into popup with multiple tab -
* in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id').
* After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session
* @access public
* @param string $var HTTP Query (GPC) variable name
* @param mixed $ses_var Session variable name
* @param mixed $default Default variable value
*/
function LinkVar($var, $ses_var = null, $default = '', $optional = false)
{
if (!isset($ses_var)) $ses_var = $var;
if ($this->GetVar($var) !== false) {
$this->StoreVar($ses_var, $this->GetVar($var), $optional);
}
else {
$this->SetVar($var, $this->RecallVar($ses_var, $default));
}
}
/**
* Returns variable from HTTP Query, or from session if not passed in HTTP Query
*
* The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed.
* Returns the default value if variable does not exist in session and was not passed in HTTP Query
*
* @see LinkVar
* @access public
* @param string $var HTTP Query (GPC) variable name
* @param mixed $ses_var Session variable name
* @param mixed $default Default variable value
* @return mixed
*/
function GetLinkedVar($var, $ses_var = null, $default = '')
{
$this->LinkVar($var, $ses_var, $default);
return $this->GetVar($var);
}
- function AddBlock($name, $tpl)
- {
- $this->cache[$name] = $tpl;
- }
-
function ProcessParsedTag($prefix, $tag, $params)
{
$processor = $this->Parser->GetProcessor($prefix);
+ /* @var $processor kDBTagProcessor */
return $processor->ProcessParsedTag($tag, $params, $prefix);
}
/**
* Return ADODB Connection object
*
* Returns ADODB Connection object already connected to the project database, configurable in config.php
* @access public
* @return kDBConnection
*/
function &GetADODBConnection()
{
return $this->Conn;
}
/**
* Allows to parse given block name or include template
*
* @param Array $params Parameters to pass to block. Reserved parameter "name" used to specify block name.
* @param Array $pass_params Forces to pass current parser params to this block/template. Use with cauntion, because you can accidently pass "block_no_data" parameter.
* @param bool $as_template
* @return string
*/
function ParseBlock($params, $pass_params = 0, $as_template = false)
{
if (substr($params['name'], 0, 5) == 'html:') {
return substr($params['name'], 5);
}
return $this->Parser->ParseBlock($params, $pass_params, $as_template);
}
/**
* Checks, that we have given block defined
*
* @param string $name
* @return bool
*/
function ParserBlockFound($name)
{
return $this->Parser->blockFound($name);
}
/**
* Allows to include template with a given name and given parameters
*
* @param Array $params Parameters to pass to template. Reserved parameter "name" used to specify template name.
* @return string
*/
function IncludeTemplate($params)
{
return $this->Parser->IncludeTemplate($params, isset($params['is_silent']) ? 1 : 0);
}
/**
* Return href for template
*
* @access public
* @param string $t Template path
* @var string $prefix index.php prefix - could be blank, 'admin'
*/
public function HREF($t, $prefix = '', $params = null, $index_file = null)
{
return $this->UrlManager->HREF($t, $prefix, $params, $index_file);
}
function getPhysicalTemplate($template)
{
return $this->UrlManager->getPhysicalTemplate($template);
}
/**
* Returns variables with values that should be passed throught with this link + variable list
*
* @param Array $params
* @return Array
*/
function getPassThroughVariables(&$params)
{
return $this->UrlManager->getPassThroughVariables($params);
}
- function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true)
+ function BuildEnv($t, $params, $pass = 'all', $pass_events = false, $env_var = true)
{
return $this->UrlManager->BuildEnv($t, $params, $pass, $pass_events, $env_var);
}
function BaseURL($prefix = '', $ssl = null, $add_port = true)
{
if ($ssl === null) {
// stay on same encryption level
return PROTOCOL . SERVER_NAME . ($add_port && defined('PORT') ? ':' . PORT : '') . rtrim(BASE_PATH, '/') . $prefix . '/';
}
if ($ssl) {
// going from http:// to https://
$base_url = $this->isAdmin ? $this->ConfigValue('AdminSSL_URL') : false;
if (!$base_url) {
$ssl_url = $this->siteDomainField('SSLUrl');
$base_url = $ssl_url !== false ? $ssl_url : $this->ConfigValue('SSL_URL');
}
return rtrim($base_url, '/') . $prefix . '/';
}
// going from https:// to http://
$domain = $this->siteDomainField('DomainName');
if ($domain === false) {
$domain = DOMAIN;
}
return 'http://' . $domain . ($add_port && defined('PORT') ? ':' . PORT : '') . rtrim($this->ConfigValue('Site_Path'), '/') . $prefix . '/';
}
function Redirect($t = '', $params = Array(), $prefix = '', $index_file = null)
{
$js_redirect = getArrayValue($params, 'js_redirect');
if ($t == '' || $t === true) {
$t = $this->GetVar('t');
}
// pass prefixes and special from previous url
if (array_key_exists('js_redirect', $params)) {
unset($params['js_redirect']);
}
// allows to send custom responce code along with redirect header
if (array_key_exists('response_code', $params)) {
$response_code = (int)$params['response_code'];
unset($params['response_code']);
}
else {
$response_code = 302; // Found
}
if (!array_key_exists('pass', $params)) {
$params['pass'] = 'all';
}
if ($this->GetVar('ajax') == 'yes' && $t == $this->GetVar('t')) {
// redirects to the same template as current
$params['ajax'] = 'yes';
}
$params['__URLENCODE__'] = 1;
$location = $this->HREF($t, $prefix, $params, $index_file);
if ($this->isDebugMode() && (kUtil::constOn('DBG_REDIRECT') || (kUtil::constOn('DBG_RAISE_ON_WARNINGS') && $this->Debugger->WarningCount))) {
$this->Debugger->appendTrace();
echo '<strong>Debug output above !!!</strong><br/>' . "\n";
if ( array_key_exists('HTTP_REFERER', $_SERVER) ) {
echo 'Referer: <strong>' . $_SERVER['HTTP_REFERER'] . '</strong><br/>' . "\n";
}
echo "Proceed to redirect: <a href=\"{$location}\">{$location}</a><br/>\n";
}
else {
if ($js_redirect) {
// show "redirect" template instead of redirecting,
// because "Set-Cookie" header won't work, when "Location"
// header is used later
$this->SetVar('t', 'redirect');
$this->SetVar('redirect_to', $location);
// make all additional parameters available on "redirect" template too
foreach ($params as $name => $value) {
$this->SetVar($name, $value);
}
return true;
}
else {
if ($this->GetVar('ajax') == 'yes' && $t != $this->GetVar('t')) {
// redirection to other then current template during ajax request
kUtil::safeDefine('DBG_SKIP_REPORTING', 1);
echo '#redirect#' . $location;
}
elseif (headers_sent() != '') {
// some output occured -> redirect using javascript
echo '<script type="text/javascript">window.location.href = \'' . $location . '\';</script>';
}
else {
// no output before -> redirect using HTTP header
// header('HTTP/1.1 302 Found');
header('Location: ' . $location, true, $response_code);
}
}
}
// session expiration is called from session initialization,
// that's why $this->Session may be not defined here
$session =& $this->recallObject('Session');
/* @var $session Session */
$this->HandleEvent( new kEvent('adm:OnBeforeShutdown') );
$session->SaveData();
ob_end_flush();
exit;
}
function Phrase($label, $allow_editing = true, $use_admin = false)
{
return $this->Phrases->GetPhrase($label, $allow_editing, $use_admin);
}
/**
* Replace language tags in exclamation marks found in text
*
* @param string $text
* @param bool $force_escape force escaping, not escaping of resulting string
* @return string
* @access public
*/
function ReplaceLanguageTags($text, $force_escape = null)
{
return $this->Phrases->ReplaceLanguageTags($text, $force_escape);
}
/**
* Checks if user is logged in, and creates
* user object if so. User object can be recalled
* later using "u.current" prefix_special. Also you may
* get user id by getting "u.current_id" variable.
*
* @access private
*/
function ValidateLogin()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$user_id = $session->GetField('PortalUserId');
- if (!$user_id && $user_id != USER_ROOT) {
+ if ( !$user_id && $user_id != USER_ROOT ) {
$user_id = USER_GUEST;
}
$this->SetVar('u.current_id', $user_id);
- if (!$this->isAdmin) {
+ if ( !$this->isAdmin ) {
// needed for "profile edit", "registration" forms ON FRONT ONLY
$this->SetVar('u_id', $user_id);
}
$this->StoreVar('user_id', $user_id, $user_id == USER_GUEST); // storing Guest user_id (-2) is optional
$this->isAdminUser = $this->isAdmin && $this->LoggedIn();
- if ($this->GetVar('expired') == 1) {
+ if ( $this->GetVar('expired') == 1 ) {
// this parameter is set only from admin
$user =& $this->recallObject('u.current');
+ /* @var $user UsersItem */
+
$user->SetError('ValidateLogin', 'session_expired', 'la_text_sess_expired');
}
- if (($user_id != USER_GUEST) && kUtil::constOn('DBG_REQUREST_LOG') ) {
- $http_query =& $this->recallObject('HTTPQuery');
- $http_query->writeRequestLog(DBG_REQUREST_LOG);
+ if ( ($user_id != USER_GUEST) && defined('DBG_REQUREST_LOG') && DBG_REQUREST_LOG ) {
+ $this->HttpQuery->writeRequestLog(DBG_REQUREST_LOG);
}
- if ($user_id != USER_GUEST) {
+ if ( $user_id != USER_GUEST ) {
// normal users + root
$this->LoadPersistentVars();
}
}
/**
* Loads current user persistent session data
*
*/
function LoadPersistentVars()
{
$this->Session->LoadPersistentVars();
}
/**
* Returns configuration option value by name
*
* @param string $name
* @return string
*/
function ConfigValue($name)
{
return $this->cacheManager->ConfigValue($name);
}
function SetConfigValue($name, $value)
{
return $this->cacheManager->SetConfigValue($name, $value);
}
/**
* Allows to process any type of event
*
* @param kEvent $event
* @param Array $params
* @param Array $specific_params
* @access public
* @author Alex
*/
function HandleEvent(&$event, $params = null, $specific_params = null)
{
if ( isset($params) ) {
$event = new kEvent($params, $specific_params);
}
$this->EventManager->HandleEvent($event);
}
/**
* Registers new class in the factory
*
* @param string $real_class Real name of class as in class declaration
* @param string $file Filename in what $real_class is declared
* @param string $pseudo_class Name under this class object will be accessed using getObject method
* @param Array $dependecies List of classes required for this class functioning
* @access public
* @author Alex
*/
function registerClass($real_class, $file, $pseudo_class = null, $dependecies = Array() )
{
$this->Factory->registerClass($real_class, $file, $pseudo_class, $dependecies);
}
/**
* Unregisters existing class from factory
*
* @param string $real_class Real name of class as in class declaration
* @param string $pseudo_class Name under this class object is accessed using getObject method
*/
function unregisterClass($real_class, $pseudo_class = null)
{
$this->Factory->unregisterClass($real_class, $pseudo_class);
}
/**
* Add $class_name to required classes list for $depended_class class.
* All required class files are included before $depended_class file is included
*
* @param string $depended_class
* @param string $class_name
* @author Alex
*/
function registerDependency($depended_class, $class_name)
{
$this->Factory->registerDependency($depended_class, $class_name);
}
/**
* Add new agent
*
* @param string $short_name name to be used to store last maintenace run info
* @param string $event_name
* @param int $run_interval run interval in seconds
* @param int $type before or after agent
* @param int $status
* @access public
*/
public function registerAgent($short_name, $event_name, $run_interval, $type = reBEFORE, $status = STATUS_ACTIVE)
{
$this->EventManager->registerAgent($short_name, $event_name, $run_interval, $type, $status);
}
/**
* Registers Hook from subprefix event to master prefix event
*
* Pattern: Observer
*
* @param string $hook_event
* @param string $do_event
* @param int $mode
* @param bool $conditional
* @access public
*/
public function registerHook($hook_event, $do_event, $mode = hAFTER, $conditional = false)
{
$this->EventManager->registerHook($hook_event, $do_event, $mode, $conditional);
}
/**
* Registers build event for given pseudo class
*
* @param string $pseudo_class
* @param string $event_name
* @access public
*/
public function registerBuildEvent($pseudo_class, $event_name)
{
$this->EventManager->registerBuildEvent($pseudo_class, $event_name);
}
/**
* Allows one TagProcessor tag act as other TagProcessor tag
*
* @param Array $tag_info
* @author Kostja
*/
function registerAggregateTag($tag_info)
{
$aggregator =& $this->recallObject('TagsAggregator', 'kArray');
/* @var $aggregator kArray */
$tag_data = Array(
$tag_info['LocalPrefix'],
$tag_info['LocalTagName'],
getArrayValue($tag_info, 'LocalSpecial')
);
$aggregator->SetArrayValue($tag_info['AggregateTo'], $tag_info['AggregatedTagName'], $tag_data);
}
/**
* Returns object using params specified, creates it if is required
*
* @param string $name
* @param string $pseudo_class
* @param Array $event_params
* @param Array $arguments
* @return kBase
*/
public function &recallObject($name, $pseudo_class = null, $event_params = Array(), $arguments = Array ())
{
$result =& $this->Factory->getObject($name, $pseudo_class, $event_params, $arguments);
return $result;
}
/**
* Returns tag processor for prefix specified
*
* @param string $prefix
* @return kDBTagProcessor
*/
function &recallTagProcessor($prefix)
{
$this->InitParser(); // because kDBTagProcesor is in NParser dependencies
$result =& $this->recallObject($prefix . '_TagProcessor');
return $result;
}
/**
* Checks if object with prefix passes was already created in factory
*
* @param string $name object presudo_class, prefix
* @return bool
* @author Kostja
*/
function hasObject($name)
{
return isset($this->Factory->Storage[$name]);
}
/**
* Removes object from storage by given name
*
* @param string $name Object's name in the Storage
* @author Kostja
*/
public function removeObject($name)
{
$this->Factory->DestroyObject($name);
}
/**
* Get's real class name for pseudo class, includes class file and creates class instance
*
* Pattern: Factory Method
*
* @param string $pseudo_class
* @param Array $arguments
* @return kBase
* @access public
*/
public function &makeClass($pseudo_class, $arguments = Array ())
{
$result =& $this->Factory->makeClass($pseudo_class, $arguments);
return $result;
}
/**
* Checks if application is in debug mode
*
* @param bool $check_debugger check if kApplication debugger is initialized too, not only for defined DEBUG_MODE constant
* @return bool
* @author Alex
* @access public
*/
public function isDebugMode($check_debugger = true)
{
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
if ($check_debugger) {
$debug_mode = $debug_mode && is_object($this->Debugger);
}
return $debug_mode;
}
/**
* Apply url rewriting used by mod_rewrite or not
*
* @param bool $ssl Force ssl link to be build
* @return bool
*/
function RewriteURLs($ssl = false)
{
// case #1,#4:
// we want to create https link from http mode
// we want to create https link from https mode
// conditions: ($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')
// case #2,#3:
// we want to create http link from https mode
// we want to create http link from http mode
// conditions: !$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')
$allow_rewriting =
(!$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')) // always allow mod_rewrite for http
|| // or allow rewriting for redirect TO httpS or when already in httpS
(($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')); // but only if it's allowed in config!
return kUtil::constOn('MOD_REWRITE') && $allow_rewriting;
}
/**
* Reads unit (specified by $prefix)
* option specified by $option
*
* @param string $prefix
* @param string $option
* @param mixed $default
* @return string
* @access public
*/
public function getUnitOption($prefix, $option, $default = false)
{
return $this->UnitConfigReader->getUnitOption($prefix, $option, $default);
}
/**
* Set's new unit option value
*
* @param string $prefix
* @param string $name
* @param string $value
* @access public
*/
public function setUnitOption($prefix, $option, $value)
{
return $this->UnitConfigReader->setUnitOption($prefix,$option,$value);
}
/**
* Read all unit with $prefix options
*
* @param string $prefix
* @return Array
* @access public
*/
public function getUnitOptions($prefix)
{
return $this->UnitConfigReader->getUnitOptions($prefix);
}
/**
* Returns true if config exists and is allowed for reading
*
* @param string $prefix
* @return bool
*/
public function prefixRegistred($prefix)
{
return $this->UnitConfigReader->prefixRegistred($prefix);
}
/**
* Splits any mixing of prefix and
* special into correct ones
*
* @param string $prefix_special
* @return Array
* @access public
*/
public function processPrefix($prefix_special)
{
return $this->Factory->processPrefix($prefix_special);
}
/**
* Set's new event for $prefix_special
* passed
*
* @param string $prefix_special
* @param string $event_name
* @access public
*/
function setEvent($prefix_special, $event_name)
{
$this->EventManager->setEvent($prefix_special,$event_name);
}
/**
* SQL Error Handler
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
* @author Alex
*/
function handleSQLError($code, $msg, $sql)
{
if ( isset($this->Debugger) ) {
$long_error_msg = '<span class="debug_error">' . $msg . ' (' . $code . ')</span><br/><a href="javascript:$Debugger.SetClipboard(\'' . htmlspecialchars($sql) . '\');"><strong>SQL</strong></a>: ' . $this->Debugger->formatSQL($sql);
$long_id = $this->Debugger->mapLongError($long_error_msg);
$error_msg = mb_substr($msg . ' (' . $code . ') [' . $sql . ']', 0, 1000) . ' #' . $long_id;
if ( kUtil::constOn('DBG_SQL_FAILURE') && !defined('IS_INSTALL') ) {
throw new Exception($error_msg);
}
else {
$this->Debugger->appendTrace();
}
}
else {
// when not debug mode, then fatal database query won't break anything
$error_msg = '<strong>SQL Error</strong> in sql: ' . $sql . ', code <strong>' . $code . '</strong> (' . $msg . ')';
}
trigger_error($error_msg, E_USER_WARNING);
return true;
}
/**
* Default error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array $errcontext
+ * @return bool
+ * @access public
*/
- function handleError($errno, $errstr = '', $errfile = '', $errline = '', $errcontext = '')
+ public function handleError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ())
{
$this->errorLogSilent($errno, $errstr, $errfile, $errline);
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
- if (!$this->errorHandlers || ($debug_mode && $skip_reporting)) {
+ if ( !$this->errorHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
- if ($errno == E_USER_ERROR) {
+ if ( $errno == E_USER_ERROR ) {
$this->errorDisplayFatal('<strong>Fatal Error: </strong>' . "{$errstr} in {$errfile} on line {$errline}");
}
- if (!$this->errorHandlers) {
+ if ( !$this->errorHandlers ) {
return true;
}
}
$res = false;
foreach ($this->errorHandlers as $handler) {
if ( is_array($handler) ) {
$object =& $handler[0];
$method = $handler[1];
$res = $object->$method($errno, $errstr, $errfile, $errline, $errcontext);
}
else {
$res = $handler($errno, $errstr, $errfile, $errline, $errcontext);
}
}
return $res;
}
/**
* Handles exception
*
* @param Exception $exception
* @return bool
+ * @access public
*/
- function handleException($exception)
+ public function handleException($exception)
{
// transform exception to regular error (no need to rewrite existing error handlers)
$errno = $exception->getCode();
$errstr = $exception->getMessage();
$errfile = $exception->getFile();
$errline = $exception->getLine();
$this->errorLogSilent($errno, $errstr, $errfile, $errline);
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
- if (!$this->exceptionHandlers || ($debug_mode && $skip_reporting)) {
+ if ( !$this->exceptionHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
$this->errorDisplayFatal('<strong>' . get_class($exception) . ': </strong>' . "{$errstr} in {$errfile} on line {$errline}");
- if (!$this->exceptionHandlers) {
+ if ( !$this->exceptionHandlers ) {
return true;
}
}
$res = false;
foreach ($this->exceptionHandlers as $handler) {
if ( is_array($handler) ) {
$object =& $handler[0];
$method = $handler[1];
$res = $object->$method($exception);
}
else {
$res = $handler($exception);
}
}
return $res;
}
- protected function errorLogSilent($errno, $errstr = '', $errfile = '', $errline = '')
+ /**
+ * Silently saves each given error message to "silent_log.txt" file, when silent log mode is enabled
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param int $errline
+ * @return void
+ * @access protected
+ */
+ protected function errorLogSilent($errno, $errstr = '', $errfile = '', $errline = null)
{
- if (!defined('SILENT_LOG') || !SILENT_LOG) {
- return ;
+ if ( !defined('SILENT_LOG') || !SILENT_LOG ) {
+ return;
}
if ( !(defined('DBG_IGNORE_STRICT_ERRORS') && DBG_IGNORE_STRICT_ERRORS && defined('E_STRICT') && ($errno == E_STRICT)) ) {
$time = adodb_date('d/m/Y H:i:s');
$fp = fopen((defined('RESTRICTED') ? RESTRICTED : FULL_PATH) . '/silent_log.txt', 'a');
fwrite($fp, '[' . $time . '] #' . $errno . ': ' . strip_tags($errstr) . ' in [' . $errfile . '] on line ' . $errline . "\n");
fclose($fp);
}
}
+ /**
+ * Displays div with given error message
+ *
+ * @param string $msg
+ * @return void
+ * @access protected
+ */
protected function errorDisplayFatal($msg)
{
$margin = $this->isAdmin ? '8px' : 'auto';
echo '<div style="background-color: #FEFFBF; margin: ' . $margin . '; padding: 10px; border: 2px solid red; text-align: center">' . $msg . '</div>';
exit;
}
/**
* Prints trace, when debug mode is not available
*
* @param bool $return_result
* @param int $skip_levels
* @return string
+ * @access public
*/
- function printTrace($return_result = false, $skip_levels = 1)
+ public function printTrace($return_result = false, $skip_levels = 1)
{
$ret = Array ();
$trace = debug_backtrace(false);
for ($i = 0; $i < $skip_levels; $i++) {
array_shift($trace);
}
foreach ($trace as $level => $trace_info) {
- if ( isset($trace_info['class']) ) {
+ if ( isset($trace_info['class']) ) {
$object = $trace_info['class'];
}
elseif ( isset($trace_info['object']) ) {
- $object = get_class( $trace_info['object'] );
+ $object = get_class($trace_info['object']);
}
else {
$object = '';
}
$args = '';
$type = isset($trace_info['type']) ? $trace_info['type'] : '';
if ( isset($trace_info['args']) ) {
foreach ($trace_info['args'] as $argument) {
if ( is_object($argument) ) {
$args .= get_class($argument) . ' instance, ';
}
else {
$args .= is_array($argument) ? 'Array' : substr($argument, 0, 10) . ' ..., ';
}
}
$args = substr($args, 0, -2);
}
- $ret[] = '#' . $level . ' ' . $object . $type . $trace_info['function']. '(' . $args . ') called at [' . $trace_info['file'] . ':' . $trace_info['line'] . ']';
+ $ret[] = '#' . $level . ' ' . $object . $type . $trace_info['function'] . '(' . $args . ') called at [' . $trace_info['file'] . ':' . $trace_info['line'] . ']';
}
- if ($return_result) {
+ if ( $return_result ) {
return implode("\n", $ret);
}
echo implode("\n", $ret);
+
+ return '';
}
/**
* Returns & blocks next ResourceId available in system
*
* @return int
* @access public
* @author Alex
*/
function NextResourceId()
{
$table_name = TABLE_PREFIX.'IdGenerator';
$this->Conn->Query('LOCK TABLES '.$table_name.' WRITE');
$this->Conn->Query('UPDATE '.$table_name.' SET lastid = lastid + 1');
$id = $this->Conn->GetOne('SELECT lastid FROM '.$table_name);
if($id === false)
{
$this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)');
$id = 2;
}
$this->Conn->Query('UNLOCK TABLES');
return $id - 1;
}
/**
* Returns genealogical main prefix for subtable prefix passes
* OR prefix, that has been found in REQUEST and some how is parent of passed subtable prefix
*
* @param string $current_prefix
* @param string $real_top if set to true will return real topmost prefix, regardless of its id is passed or not
* @return string
* @access public
* @author Kostja / Alex
*/
function GetTopmostPrefix($current_prefix, $real_top = false)
{
// 1. get genealogical tree of $current_prefix
$prefixes = Array ($current_prefix);
while ( $parent_prefix = $this->getUnitOption($current_prefix, 'ParentPrefix') ) {
if (!$this->prefixRegistred($parent_prefix)) {
// stop searching, when parent prefix is not registered
break;
}
$current_prefix = $parent_prefix;
array_unshift($prefixes, $current_prefix);
}
if ($real_top) {
return $current_prefix;
}
// 2. find what if parent is passed
$passed = explode(',', $this->GetVar('all_passed'));
foreach ($prefixes as $a_prefix) {
if (in_array($a_prefix, $passed)) {
return $a_prefix;
}
}
return $current_prefix;
}
/**
* Triggers email event of type Admin
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEventAdmin($email_event_name, $to_user_id = null, $send_params = Array ())
{
$event =& $this->EmailEvent($email_event_name, EmailEvent::EVENT_TYPE_ADMIN, $to_user_id, $send_params);
return $event;
}
/**
* Triggers email event of type User
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEventUser($email_event_name, $to_user_id = null, $send_params = Array ())
{
$event =& $this->EmailEvent($email_event_name, EmailEvent::EVENT_TYPE_FRONTEND, $to_user_id, $send_params);
return $event;
}
/**
* Triggers general email event
*
* @param string $email_event_name
* @param int $email_event_type (0 for User, 1 for Admin)
* @param int $to_user_id
* @param array $send_params associative array of direct send params,
* possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEvent($email_event_name, $email_event_type, $to_user_id = null, $send_params = Array ())
{
$params = Array (
'EmailEventName' => $email_event_name,
'EmailEventToUserId' => $to_user_id,
'EmailEventType' => $email_event_type,
'DirectSendParams' => $send_params,
);
if (array_key_exists('use_special', $send_params)) {
$event_str = 'emailevents.' . $send_params['use_special'] . ':OnEmailEvent';
}
else {
$event_str = 'emailevents:OnEmailEvent';
}
$this->HandleEvent($event, $event_str, $params);
return $event;
}
/**
* Allows to check if user in this session is logged in or not
*
* @return bool
*/
function LoggedIn()
{
// no session during expiration process
return is_null($this->Session) ? false : $this->Session->LoggedIn();
}
/**
* Check current user permissions based on it's group permissions in specified category
*
* @param string $name permission name
* @param int $cat_id category id, current used if not specified
* @param int $type permission type {1 - system, 0 - per category}
* @return int
*/
function CheckPermission($name, $type = 1, $cat_id = null)
{
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
return $perm_helper->CheckPermission($name, $type, $cat_id);
}
/**
* Set's any field of current visit
*
* @param string $field
* @param mixed $value
*/
function setVisitField($field, $value)
{
if ($this->isAdmin || !$this->ConfigValue('UseVisitorTracking')) {
// admin logins are not registred in visits list
return ;
}
$visit =& $this->recallObject('visits', null, Array ('raise_warnings' => 0));
/* @var $visit kDBItem */
if ($visit->isLoaded()) {
$visit->SetDBField($field, $value);
$visit->Update();
}
}
/**
* Allows to check if in-portal is installed
*
* @return bool
*/
function isInstalled()
{
return $this->InitDone && (count($this->ModuleInfo) > 0);
}
/**
* Allows to determine if module is installed & enabled
*
* @param string $module_name
* @return bool
*/
function isModuleEnabled($module_name)
{
return $this->findModule('Name', $module_name) !== false;
}
/**
* Returns Window ID of passed prefix main prefix (in edit mode)
*
* @param string $prefix
* @return mixed
*/
function GetTopmostWid($prefix)
{
$top_prefix = $this->GetTopmostPrefix($prefix);
$mode = $this->GetVar($top_prefix.'_mode');
return $mode != '' ? substr($mode, 1) : '';
}
/**
* Get temp table name
*
* @param string $table
* @param mixed $wid
* @return string
*/
function GetTempName($table, $wid = '')
{
return $this->GetTempTablePrefix($wid) . $table;
}
function GetTempTablePrefix($wid = '')
{
if (preg_match('/prefix:(.*)/', $wid, $regs)) {
$wid = $this->GetTopmostWid($regs[1]);
}
return TABLE_PREFIX . 'ses_' . $this->GetSID() . ($wid ? '_' . $wid : '') . '_edit_';
}
function IsTempTable($table)
{
static $cache = Array ();
if ( !array_key_exists($table, $cache) ) {
$cache[$table] = preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$table);
}
return (bool)$cache[$table];
}
/**
* Checks, that given prefix is in temp mode
*
* @param string $prefix
* @return bool
*/
function IsTempMode($prefix, $special = '')
{
$top_prefix = $this->GetTopmostPrefix($prefix);
$var_names = Array (
$top_prefix,
rtrim($top_prefix . '_' . $special, '_'), // from post
rtrim($top_prefix . '.' . $special, '.'), // assembled locally
);
$var_names = array_unique($var_names);
$temp_mode = false;
foreach ($var_names as $var_name) {
$value = $this->GetVar($var_name . '_mode');
if ($value && (substr($value, 0, 1) == 't')) {
$temp_mode = true;
break;
}
}
return $temp_mode;
}
/**
* Return live table name based on temp table name
*
* @param string $temp_table
* @return string
*/
function GetLiveName($temp_table)
{
if( preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$temp_table, $rets) )
{
// cut wid from table end if any
return $rets[2];
}
else
{
return $temp_table;
}
}
function CheckProcessors($processors)
{
foreach ($processors as $a_processor)
{
if (!isset($this->CachedProcessors[$a_processor])) {
$this->CachedProcessors[$a_processor] =& $this->recallObject($a_processor.'_TagProcessor');
}
}
}
function ApplicationDie($message = '')
{
$message = ob_get_clean().$message;
if ($this->isDebugMode()) {
$message .= $this->Debugger->printReport(true);
}
echo $this->UseOutputCompression() ? gzencode($message, DBG_COMPRESSION_LEVEL) : $message;
exit;
}
/* moved from MyApplication */
function getUserGroups($user_id)
{
switch ($user_id) {
case USER_ROOT:
$user_groups = $this->ConfigValue('User_LoggedInGroup');
break;
case USER_GUEST:
$user_groups = $this->ConfigValue('User_LoggedInGroup') . ',' . $this->ConfigValue('User_GuestGroup');
break;
default:
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PortalUserId = ' . (int)$user_id;
$res = $this->Conn->GetCol($sql);
$user_groups = Array( $this->ConfigValue('User_LoggedInGroup') );
if ($res) {
$user_groups = array_merge($user_groups, $res);
}
$user_groups = implode(',', $user_groups);
}
return $user_groups;
}
/**
* Allows to detect if page is browsed by spider (293 agents supported)
*
* @return bool
*/
function IsSpider()
{
static $is_spider = null;
if (!isset($is_spider)) {
$user_agent = trim($_SERVER['HTTP_USER_AGENT']);
$robots = file(FULL_PATH.'/core/robots_list.txt');
foreach ($robots as $robot_info) {
$robot_info = explode("\t", $robot_info, 3);
if ($user_agent == trim($robot_info[2])) {
$is_spider = true;
break;
}
}
}
return $is_spider;
}
/**
* Allows to detect table's presense in database
*
* @param string $table_name
* @return bool
*/
function TableFound($table_name)
{
return $this->Conn->TableFound($table_name);
}
/**
* Returns counter value
*
* @param string $name counter name
* @param Array $params counter parameters
* @param string $query_name specify query name directly (don't generate from parmeters)
* @param bool $multiple_results
* @return mixed
*/
function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false)
{
$count_helper =& $this->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
return $count_helper->getCounter($name, $params, $query_name, $multiple_results);
}
/**
- * Resets counter, whitch are affected by one of specified tables
+ * Resets counter, which are affected by one of specified tables
*
* @param string $tables comma separated tables list used in counting sqls
+ * @return void
+ * @access public
*/
- function resetCounters($tables)
+ public function resetCounters($tables)
{
- if (kUtil::constOn('IS_INSTALL')) {
- return ;
+ if ( kUtil::constOn('IS_INSTALL') ) {
+ return;
}
$count_helper =& $this->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
- return $count_helper->resetCounters($tables);
+ $count_helper->resetCounters($tables);
}
/**
* Sends XML header + optionally displays xml heading
*
- * @param string $xml_version
+ * @param string|bool $xml_version
* @return string
+ * @access public
* @author Alex
*/
- function XMLHeader($xml_version = false)
+ public function XMLHeader($xml_version = false)
{
$lang =& $this->recallObject('lang.current');
- header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
+ /* @var $lang LanguagesItem */
+
+ header('Content-type: text/xml; charset=' . $lang->GetDBField('Charset'));
- return $xml_version ? '<?xml version="'.$xml_version.'" encoding="'.$lang->GetDBField('Charset').'"?>' : '';
+ return $xml_version ? '<?xml version="' . $xml_version . '" encoding="' . $lang->GetDBField('Charset') . '"?>' : '';
}
/**
* Returns category tree
*
* @param int $category_id
* @return Array
*/
function getTreeIndex($category_id)
{
$tree_index = $this->getCategoryCache($category_id, 'category_tree');
if ($tree_index) {
$ret = Array ();
list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index);
return $ret;
}
return false;
}
/**
* Base category of all categories
* Usually replaced category, with ID = 0 in category-related operations.
*
* @return int
*/
function getBaseCategory()
{
// same, what $this->findModule('Name', 'Core', 'RootCat') does
// don't cache while IS_INSTALL, because of kInstallToolkit::createModuleCategory and upgrade
return $this->ModuleInfo['Core']['RootCat'];
}
function DeleteUnitCache($include_sections = false)
{
$this->cacheManager->DeleteUnitCache($include_sections);
}
/**
* Sets data from cache to object
*
* @param Array $data
* @access public
*/
public function setFromCache(&$data)
{
$this->ReplacementTemplates = $data['Application.ReplacementTemplates'];
$this->RewriteListeners = $data['Application.RewriteListeners'];
$this->ModuleInfo = $data['Application.ModuleInfo'];
}
/**
* Gets object data for caching
* The following caches should be reset based on admin interaction (adjusting config, enabling modules etc)
*
* @access public
* @return Array
*/
public function getToCache()
{
return Array (
'Application.ReplacementTemplates' => $this->ReplacementTemplates,
'Application.RewriteListeners' => $this->RewriteListeners,
'Application.ModuleInfo' => $this->ModuleInfo,
);
}
public function delayUnitProcessing($method, $params)
{
$this->cacheManager->delayUnitProcessing($method, $params);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/serialized_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/serialized_formatter.php (revision 14595)
+++ branches/5.2.x/core/kernel/utility/formatters/serialized_formatter.php (revision 14596)
@@ -1,33 +1,51 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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.
*/
class kSerializedFormatter extends kFormatter {
- function Parse($value, $field_name, &$object)
+ /**
+ * Performs basic type validation on form field value
+ *
+ * @param mixed $value
+ * @param string $field_name
+ * @param kDBItem $object
+ * @return mixed
+ * @access public
+ */
+ public function Parse($value, $field_name, &$object)
{
$options = $object->GetFieldOptions($field_name);
$value = kUtil::array_merge_recursive(unserialize($options['default']), $value);
return serialize($value);
}
+ /**
+ * Formats value of a given field
+ *
+ * @param string $value
+ * @param string $field_name
+ * @param kDBItem|kDBList $object
+ * @param string $format
+ * @return string
+ */
function Format($value, $field_name, &$object, $format = null)
{
$data = unserialize($value);
$format = explode('.', $format);
$format = '\''.implode('\', \'', $format).'\'';
return eval('return getArrayValue($data, '.$format.');');
}
}
Index: branches/5.2.x/core/kernel/utility/formatters/multilang_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/multilang_formatter.php (revision 14595)
+++ branches/5.2.x/core/kernel/utility/formatters/multilang_formatter.php (revision 14596)
@@ -1,313 +1,320 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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.
*/
class kMultiLanguage extends kFormatter
{
/**
* Multilanguage helper
*
* @var kMultiLanguageHelper
*/
var $helper = null;
public function __construct()
{
parent::__construct();
$this->helper =& $this->Application->recallObject('kMultiLanguageHelper');
}
/**
* Returns ML field equivalent to field name specifed
*
* @param string $field_name
* @param bool $from_primary use primary/current language for name custruction
* @return string
*/
function LangFieldName($field_name, $from_primary = false)
{
static $primary_language = null;
if (preg_match('/^l[0-9]+_/', $field_name)) {
return $field_name;
}
if (!isset($primary_language)) {
$primary_language = $this->Application->GetDefaultLanguageId();
}
$lang = $from_primary ? $primary_language : $this->Application->GetVar('m_lang');
if (!$lang || ($lang == 'default')) {
$lang = $primary_language;
}
return 'l' . $lang . '_' . $field_name;
}
/**
* The method is supposed to alter config options or cofigure object in some way based on its usage of formatters
* The methods is called for every field with formatter defined when configuring item.
* Could be used for adding additional VirtualFields to an object required by some special Formatter
*
* @param string $field_name
* @param array $field_options
* @param kDBBase $object
*/
function PrepareOptions($field_name, &$field_options, &$object)
{
if (getArrayValue($field_options, 'master_field') || getArrayValue($field_options, 'options_processed')) {
return ;
}
$lang_field_name = $this->LangFieldName($field_name);
- //substitude title field
+ //substitute title field
$title_field = $this->Application->getUnitOption($object->Prefix, 'TitleField');
if ($title_field == $field_name) {
$this->Application->setUnitOption($object->Prefix, 'TitleField', $lang_field_name);
}
$languages = $this->helper->getLanguages();
$primary_language_id = $this->Application->GetDefaultLanguageId();
$fields = $this->Application->getUnitOption($object->Prefix, 'Fields', Array ());
$virtual_fields = $this->Application->getUnitOption($object->Prefix, 'VirtualFields', Array ());
- // substitude real field
+ // substitute real field
if (array_key_exists($field_name, $fields)) {
$tmp_field_options = $fields[$field_name];
$tmp_field_options['master_field'] = $field_name;
$tmp_field_options['error_field'] = $field_name;
$field_required = array_key_exists('required', $tmp_field_options) && $tmp_field_options['required'];
foreach ($languages as $language_id) {
// make all non-primary language fields not required
if ($language_id != $primary_language_id) {
unset($tmp_field_options['required']);
}
elseif ($field_required) {
$tmp_field_options['required'] = $field_required;
}
$translated_field = 'l' . $language_id . '_' . $field_name;
$fields[$translated_field] = $tmp_field_options;
$object->SetFieldOptions($translated_field, $tmp_field_options);
}
// makes original field non-required
$object_fields = $object->getFields(); // use kDBBase::getFields, since there are no kDBList::setRequired
unset($fields[$field_name]['required'], $object_fields[$field_name]['required']);
$object->setFields($object_fields);
// prevents real field with formatter set to be saved in db
$virtual_fields[$field_name] = $object_fields[$field_name];
$object->SetFieldOptions($field_name, $object_fields[$field_name], true);
}
elseif (array_key_exists($field_name, $virtual_fields)) {
- // substitude virtual field
- $calculated_fields = $this->Application->getUnitOption($object->Prefix, 'CalculatedFields');
+ // substitute virtual field
+ $calculated_fields = $this->Application->getUnitOption($object->Prefix, 'CalculatedFields', Array ());
$calculated_field_special = array_key_exists($object->Special, $calculated_fields) ? $object->Special : (array_key_exists('', $calculated_fields) ? '' : false);
+ /* @var $calculated_fields Array */
$tmp_field_options = $virtual_fields[$field_name];
$tmp_field_options['master_field'] = $field_name;
$tmp_field_options['error_field'] = $field_name;
$field_required = array_key_exists('required', $tmp_field_options) && $tmp_field_options['required'];
foreach ($languages as $language_id) {
// make all non-primary language fields not required
if ($language_id != $primary_language_id) {
unset($tmp_field_options['required']);
}
elseif ($field_required) {
$tmp_field_options['required'] = $field_required;
}
$translated_field = 'l' . $language_id . '_' . $field_name;
$virtual_fields[$translated_field] = $tmp_field_options;
$object->SetFieldOptions($translated_field, $tmp_field_options, true);
- // substitude calculated fields associated with given virtual field
+ // substitute calculated fields associated with given virtual field
foreach ($calculated_fields as $special => $special_fields) {
if (!array_key_exists($field_name, $special_fields)) {
continue;
}
$calculated_fields[$special][$translated_field] = str_replace('%2$s', $language_id, $special_fields[$field_name]);
if ($special === $calculated_field_special) {
$object->addCalculatedField($translated_field, $calculated_fields[$special][$translated_field]);
}
}
// manually copy virtual field back to fields (see kDBBase::setVirtualFields about that)
$fields[$translated_field] = $tmp_field_options;
$object->SetFieldOptions($translated_field, $tmp_field_options);
}
// remove original calculated field
foreach ($calculated_fields as $special => $special_fields) {
unset($calculated_fields[$special][$field_name]);
}
$object_calculated_fields = $object->getCalculatedFields();
unset($object_calculated_fields[$field_name]);
$object->setCalculatedFields($object_calculated_fields);
// save back calculated fields
$this->Application->setUnitOption($object->Prefix, 'CalculatedFields', $calculated_fields);
// makes original field non-required
$object_fields = $object->getFields(); // use kDBBase::getFields, since there are no kDBList::setRequired
unset($fields[$field_name]['required'], $object_fields[$field_name]['required']);
$object->setFields($object_fields);
$virtual_field_options = $object->GetFieldOptions($field_name, true);
unset($virtual_fields[$field_name]['required'], $virtual_field_options['required']);
$object->SetFieldOptions($field_name, $virtual_field_options, true);
}
- //substitude grid fields
- $grids = $this->Application->getUnitOption($object->Prefix, 'Grids', Array());
+ // substitute grid fields
+ $grids = $this->Application->getUnitOption($object->Prefix, 'Grids', Array ());
+ /* @var $grids Array */
+
foreach ($grids as $name => $grid) {
if ( getArrayValue($grid, 'Fields', $field_name) ) {
// used by column picker to track column position
$grids[$name]['Fields'][$field_name]['formatter_renamed'] = true;
if (!array_key_exists('format', $grids[$name]['Fields'][$field_name])) {
// prevent displaying value from primary language
// instead of missing value in current language
$grids[$name]['Fields'][$field_name]['format'] = 'no_default';
}
if ( !isset($grid['Fields'][$field_name]['title']) ) {
$grids[$name]['Fields'][$field_name]['title'] = 'column:la_fld_' . $field_name;
}
kUtil::array_rename_key($grids[$name]['Fields'], $field_name, $lang_field_name);
}
// update sort fields - used for sorting and filtering in SQLs
foreach ($grid['Fields'] as $grid_fld_name => $fld_options) {
if (isset($fld_options['sort_field']) && $fld_options['sort_field'] == $field_name) {
$grids[$name]['Fields'][$grid_fld_name]['sort_field'] = $lang_field_name;
}
}
}
$this->Application->setUnitOption($object->Prefix, 'Grids', $grids);
- //substitude default sortings
- $sortings = $this->Application->getUnitOption($object->Prefix, 'ListSortings', Array());
+ // substitute default sortings
+ $sortings = $this->Application->getUnitOption($object->Prefix, 'ListSortings', Array ());
+ /* @var $sortings Array */
+
foreach ($sortings as $special => $the_sortings) {
if (isset($the_sortings['ForcedSorting'])) {
kUtil::array_rename_key($sortings[$special]['ForcedSorting'], $field_name, $lang_field_name);
}
if (isset($the_sortings['Sorting'])) {
kUtil::array_rename_key($sortings[$special]['Sorting'], $field_name, $lang_field_name);
}
}
$this->Application->setUnitOption($object->Prefix, 'ListSortings', $sortings);
- //TODO: substitude possible language-fields sortings after changing language
+ // TODO: substitute possible language-fields sortings after changing language
$fields[$field_name]['options_processed'] = $field_options['options_processed'] = true;
$this->Application->setUnitOption($object->Prefix, 'Fields', $fields);
$this->Application->setUnitOption($object->Prefix, 'VirtualFields', $virtual_fields);
}
/*function UpdateSubFields($field, $value, &$options, &$object)
{
}
*/
/**
* Checks, that field value on primary language is set
*
* @param string $field
* @param mixed $value
* @param Array $options
* @param kDBItem $object
*/
function UpdateMasterFields($field, $value, &$options, &$object)
{
$master_field = array_key_exists('master_field', $options) ? $options['master_field'] : false;
if (!$master_field) {
return ;
}
// moved here from Parse, because at Parse time not all of the fields may be set - this is extremly actual, when working with PopulateMlFields mode
$lang = $this->Application->GetVar('m_lang');
$def_lang = $this->Application->GetDefaultLanguageId();
- if (!$this->Application->GetVar('allow_translation') && ($lang != $def_lang) && getArrayValue($options, 'required')) {
+ if ( !$this->Application->GetVar('allow_translation') && ($lang != $def_lang) && $object->isRequired($field) ) {
$def_lang_field = 'l' . $def_lang . '_' . $master_field;
+
if ( !$object->ValidateRequired($def_lang_field, $options) ) {
$object->SetError($master_field, 'primary_lang_required');
if ( $object->isField($def_lang_field) ) {
$object->SetError($def_lang_field, 'primary_lang_required');
}
}
}
}
/**
- * Formats field value
+ * Formats value of a given field
*
* @param string $value
* @param string $field_name
- * @param kDBItem $object
+ * @param kDBItem|kDBList $object
* @param string $format
* @return string
*/
function Format($value, $field_name, &$object, $format=null)
{
$master_field = $object->GetFieldOption($field_name, 'master_field');
if (!$master_field) { // if THIS field is master it does NOT have reference to it's master_field
$lang = $this->Application->GetVar('m_lang');
$value = $object->GetDBField('l'.$lang.'_'.$field_name); //getting value of current language
$master_field = $field_name; // THIS is master_field
}
$options = $object->GetFieldOptions($field_name);
$format = isset($format) ? $format : ( isset($options['format']) ? $options['format'] : null);
// use strpos, becase 2 comma-separated formats could be specified
if ($value == '' && strpos($format, 'no_default') === false) { // try to get default language value
$def_lang_value = $object->GetDBField('l'.$this->Application->GetDefaultLanguageId().'_'.$master_field);
if ($def_lang_value == '') {
return NULL;
}
return $this->_replaceFCKLinks($def_lang_value, $options, $format); //return value from default language
}
return $this->_replaceFCKLinks($value, $options, $format);
}
/**
* Performs required field check on primary language
*
* @param mixed $value
* @param string $field_name
* @param kDBItem $object
- * @return string
+ * @return mixed
+ * @access public
*/
- function Parse($value, $field_name, &$object)
+ public function Parse($value, $field_name, &$object)
{
if ($value == '') return NULL;
return $value;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/date_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/date_formatter.php (revision 14595)
+++ branches/5.2.x/core/kernel/utility/formatters/date_formatter.php (revision 14596)
@@ -1,481 +1,502 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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.
*/
class kDateFormatter extends kFormatter {
/**
* Current Language
*
* @var LanguagesItem
*/
var $language = null;
/**
* Create date formatter
*
* @access public
*/
public function __construct()
{
parent::__construct();
$this->language =& $this->Application->recallObject('lang.current');
}
/**
* Sets mixed format (date + time) for field if not set directly
*
* @param Array $field_options options of field
* @param Array $format separate formats for date & time
* @param string $type destination key in field_options to store mixed format
*/
function SetMixedFormat(&$field_options, &$format, $type)
{
if (!isset($field_options[$type])) {
// default value is date+sepatator+time
$field_options[$type] = '_regional_DateTimeFormat';
}
if ($field_options[$type] == '_regional_DateTimeFormat') {
$field_options[$type] = $format['date'].$field_options['date_time_separator'].$format['time'];
}
else if(preg_match('/_regional_(.*)/', $field_options[$type], $regs)) {
$field_options[$type] = $this->language->GetDBField($regs[1]);
}
$format['mixed'] = $field_options[$type];
}
/**
* Returns separate formats for date,time,combined for input & display formats
*
* @param Array $field_options options of field
* @param string $type type of requested information = {mixed,date,time}
* @return Array display & input formats
*/
function GetSeparateFormats(&$field_options, $type)
{
if ($type == 'mixed') {
if (!isset($field_options['date_time_separator'])) $field_options['date_time_separator'] = ' ';
$display_format = Array ();
$input_format = Array ();
list ($display_format['date'], $input_format['date']) = $this->GetSeparateFormats($field_options, 'date');
list ($display_format['time'], $input_format['time']) = $this->GetSeparateFormats($field_options, 'time');
$this->SetMixedFormat($field_options, $display_format, 'format');
$this->SetMixedFormat($field_options, $input_format, 'input_format');
return Array ($display_format, $input_format);
}
else {
// 1. set display format
if (isset($field_options[$type.'_format'])) {
$format = $field_options[$type.'_format'];
}
else {
$format = $this->language->GetDBField(ucfirst($type).'Format');
}
// 2. set input format
if (isset($field_options['input_'.$type.'_format'])) {
$input_format = $field_options['input_'.$type.'_format'];
}
else {
$input_format = $this->language->GetDBField('Input'.ucfirst($type).'Format');
}
return Array ($format, $input_format);
}
}
/**
* The method is supposed to alter config options or cofigure object in some way based on its usage of formatters
* The methods is called for every field with formatter defined when configuring item.
* Could be used for adding additional VirtualFields to an object required by some special Formatter
*
* @param string $field_name
* @param array $field_options
* @param kDBBase $object
*/
function PrepareOptions($field_name, &$field_options, &$object)
{
list ($display_format, $input_format) = $this->GetSeparateFormats($field_options, 'mixed');
$field_options['sub_fields'] = Array('date' => $field_name.'_date', 'time' => $field_name.'_time');
if (!isset($field_options['use_timezone'])) {
// apply timezone from server
$field_options['use_timezone'] = true;
}
$add_fields = Array();
// 1. add DATE virtual field
$opts = Array('master_field' => $field_name, 'formatter' => 'kDateFormatter', 'format' => $display_format['date'], 'input_format' => $input_format['date']);
- $copy_options = Array ('default', 'required', 'use_timezone', 'error_msgs');
+ $copy_options = Array ('type', 'default', 'required', 'use_timezone', 'error_msgs');
foreach ($copy_options as $copy_option) {
if (array_key_exists($copy_option, $field_options) ) {
$opts[$copy_option] = $field_options[$copy_option];
}
}
$add_fields[$field_name.'_date'] = $opts;
// 2. add TIME virtual field
$opts['format'] = $display_format['time'];
$opts['input_format'] = $input_format['time'];
$add_fields[$field_name.'_time'] = $opts;
$filter_type = getArrayValue($field_options, 'filter_type');
if($filter_type == 'range')
{
$opts['format'] = $field_options['format'];
$add_fields[$field_name.'_rangefrom'] = $opts;
$add_fields[$field_name.'_rangeto'] = $opts;
}
if ( !$object->isVirtualField($field_name) ) {
// adding caluclated field to format date directly in the query
$object->addCalculatedField($field_name.'_date', '%1$s.'.$field_name);
$object->addCalculatedField($field_name.'_time', '%1$s.'.$field_name);
}
$virtual_fields = $object->getVirtualFields();
$add_fields = kUtil::array_merge_recursive($add_fields, $virtual_fields);
$object->setVirtualFields($add_fields);
}
- function UpdateSubFields($field, $value, &$options, &$object)
+ /**
+ * Used for split fields like timestamp -> date, time
+ * Called from DBItem to update sub fields values after loading item
+ *
+ * @param string $field
+ * @param string $value
+ * @param Array $options
+ * @param kDBItem $object
+ * @return void
+ * @access public
+ */
+ public function UpdateSubFields($field, $value, &$options, &$object)
{
- if ( $sub_fields = getArrayValue($options, 'sub_fields') ) {
- if( isset($value) && $value )
- {
- $object->SetDBField( $sub_fields['date'], $value );
- $object->SetDBField( $sub_fields['time'], $value );
- }
+ $sub_fields = getArrayValue($options, 'sub_fields');
+
+ if ( !$sub_fields || !isset($value) || !$value ) {
+ return ;
}
+
+ $object->SetDBField($sub_fields['date'], $value);
+ $object->SetDBField($sub_fields['time'], $value);
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem Validate (before validation) to get back master field value from its sub_fields
*
* @param string $field
* @param mixed $value
* @param Array $options
* @param kDBItem $object
*/
function UpdateMasterFields($field, $value, &$options, &$object)
{
// when in master field - set own value from sub_fields
if ( $sub_fields = getArrayValue($options, 'sub_fields') ) {
// if date is not empty, but time is empty - set time to 0, otherwise master field fomratter will complain
// when we have only date field on form, we need time hidden field always empty, don't ask me why!
if ($object->GetDBField($sub_fields['date']) != '' && $object->GetDBField($sub_fields['time']) == '') {
$empty_time = getArrayValue($options,'empty_time');
if ($empty_time === false) {
$empty_time = adodb_mktime(0, 0, 0);
}
$object->SetDBField($sub_fields['time'], $empty_time);
}
elseif ($object->GetDBField($sub_fields['time']) != '' && $object->GetDBField($sub_fields['date']) == '') {
$empty_date = getArrayValue($options,'empty_date');
if ($empty_date === false) {
$empty_date = adodb_mktime(0, 0, 0, 1, 1, 1970);
}
$object->SetDBField($sub_fields['date'], $empty_date);
}
$input_format['date'] = $object->GetFieldOption($sub_fields['date'], 'input_format');
$input_format['time'] = $object->GetFieldOption($sub_fields['time'], 'input_format');
$object->SetField($field, $object->GetField($sub_fields['date'], $input_format['date']).$options['date_time_separator'].$object->GetField($sub_fields['time'], $input_format['time']));
}
// when in one of sub_fields - call update for master_field to update its value from sub_fields [are you following ? :) ]
elseif ($master_field = getArrayValue($options, 'master_field') ) {
$opt = $object->GetFieldOptions($master_field);
$this->UpdateMasterFields($master_field, null, $opt, $object);
}
}
-//function Format($value, $options, &$errors)
+ /**
+ * Formats value of a given field
+ *
+ * @param string $value
+ * @param string $field_name
+ * @param kDBItem|kDBList $object
+ * @param string $format
+ * @return string
+ */
function Format($value, $field_name, &$object, $format=null)
{
if ( is_null($value) ) return '';
if ( !is_numeric($value) ) {
return $value; // for leaving badly formatted date on the form
}
settype($value, 'int');
if ( !is_int($value) ) {
return $value;
}
$options = $object->GetFieldOptions($field_name);
if ( isset($format) ) {
$options['format'] = $format;
}
if (preg_match('/_regional_(.*)/', $options['format'], $regs)) {
// when such type of format is given directly to kDBBase::GetField
$options['format'] = $this->language->GetDBField($regs[1]);
}
if ($options['format'] == '_input_') {
// use input format instead of output format
$options['format'] = $options['input_format'];
}
if (!$options['use_timezone']) {
return adodb_gmdate($options['format'], $value);
}
$format = $options['format'];
$dt_separator = getArrayValue($options, 'date_time_separator');
if ($dt_separator) {
$format = trim($format, $dt_separator);
}
return adodb_date($format, $value);
}
function HumanFormat($format)
{
$patterns = Array('/m/',
'/n/',
'/d/',
'/j/',
'/y/',
'/Y/',
'/h|H/',
'/g|G/',
'/i/',
'/s/',
'/a|A/');
$replace = Array( 'mm',
'm',
'dd',
'd',
'yy',
'yyyy',
'hh',
'h',
'mm',
'ss',
'AM');
$res = preg_replace($patterns, $replace, $format);
return $res;
}
function SQLFormat($format)
{
$mapping = Array(
'/%/' => '%%',
'/(?<!%)a/' => '%p', // Lowercase Ante meridiem and Post meridiem => MySQL provides only uppercase
'/(?<!%)A/' => '%p', // Uppercase Ante meridiem and Post meridiem
'/(?<!%)d/' => '%d', // Day of the month, 2 digits with leading zeros
'/(?<!%)D/' => '%a', // A textual representation of a day, three letters
'/(?<!%)F/' => '%M', // A full textual representation of a month, such as January or March
'/(?<!%)g/' => '%l', // 12-hour format of an hour without leading zeros
'/(?<!%)G/' => '%k', // 24-hour format of an hour without leading zeros
'/(?<!%)h/' => '%h', // 12-hour format of an hour with leading zeros
'/(?<!%)H/' => '%H', // 24-hour format of an hour with leading zeros
'/(?<!%)i/' => '%i', // Minutes with leading zeros
'/(?<!%)I/' => 'N/A', // Whether or not the date is in daylights savings time
'/(?<!%)S/' => 'N/A', // English ordinal suffix for the day of the month, 2 characters, see below
'/jS/' => '%D', // MySQL can't return separate suffix, but could return date with suffix
'/(?<!%)j/' => '%e', // Day of the month without leading zeros
'/(?<!%)l/' => '%W', // A full textual representation of the day of the week
'/(?<!%)L/' => 'N/A', // Whether it's a leap year
'/(?<!%)m/' => '%m', // Numeric representation of a month, with leading zeros
'/(?<!%)M/' => '%b', // A short textual representation of a month, three letters
'/(?<!%)n/' => '%c', // Numeric representation of a month, without leading zeros
'/(?<!%)O/' => 'N/A', // Difference to Greenwich time (GMT) in hours
'/(?<!%)r/' => 'N/A', // RFC 2822 formatted date
'/(?<!%)s/' => '%s', // Seconds, with leading zeros
// S and jS moved before j - see above
'/(?<!%)t/' => 'N/A', // Number of days in the given month
'/(?<!%)T/' => 'N/A', // Timezone setting of this machine
'/(?<!%)U/' => 'N/A', // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
'/(?<!%)w/' => '%w', // Numeric representation of the day of the week
'/(?<!%)W/' => '%v', // ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
'/(?<!%)Y/' => '%Y', // A full numeric representation of a year, 4 digits
'/(?<!%)y/' => '%y', // A two digit representation of a year
'/(?<!%)z/' => 'N/A', // The day of the year (starting from 0) => MySQL starts from 1
'/(?<!%)Z/' => 'N/A', // Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.
);
$patterns = array_keys($mapping);
$replacements = array_values($mapping);
$res = preg_replace($patterns, $replacements, $format);
return $res;
}
/**
* Converts formatted date+time to timestamp and validates format
*
* @param mixed $value
* @param string $field_name
* @param kDBItem $object
- * @return string
+ * @return mixed
+ * @access public
*/
- function Parse($value, $field_name, &$object)
+ public function Parse($value, $field_name, &$object)
{
$options = $object->GetFieldOptions($field_name);
$dt_separator = getArrayValue($options,'date_time_separator');
if($dt_separator) $value = trim($value, $dt_separator);
if($value == '') return NULL;
//return strtotime($value);
$format = $options['input_format'];
if ($dt_separator) $format = trim($format, $dt_separator);
$error_params = Array( $this->HumanFormat($format), adodb_date($format), 'value' => $value );
$hour = 0;
$minute = 0;
$second = 0;
$month = 1;
$day = 1;
$year = 1970;
$patterns['n'] = '([0-9]{1,2})';
$patterns['m'] = '([0-9]{1,2})';
$patterns['d'] = '([0-9]{1,2})';
$patterns['j'] = '([0-9]{1,2})';
$patterns['Y'] = '([0-9]{4})';
$patterns['y'] = '([0-9]{2})';
$patterns['G'] = '([0-9]{1,2})';
$patterns['g'] = '([0-9]{1,2})';
$patterns['H'] = '([0-9]{2})';
$patterns['h'] = '([0-9]{2})';
$patterns['i'] = '([0-9]{2})';
$patterns['s'] = '([0-9]{2})';
$patterns['a'] = '(am|pm)';
$patterns['A'] = '(AM|PM)';
$holders_mask = '/' . preg_replace('/[a-zA-Z]{1}/i', '([a-zA-Z]{1})', preg_quote($format, '/')) . '/';
if (!preg_match($holders_mask, $format, $holders)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
$values_mask = '/^' . preg_quote($format, '/') . '$/';
foreach ($patterns as $key => $val) {
$values_mask = str_replace($key, $val, $values_mask);
}
if (!preg_match($values_mask, $value, $values)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
for ($i = 1; $i < count($holders); $i++) {
switch ($holders[$i]) {
case 'n':
case 'm':
$month = $values[$i];
$month = preg_replace('/^0{1}/', '', $month);
break;
case 'd':
$day = $values[$i];
$day = preg_replace('/^0{1}/', '', $day);
break;
case 'Y':
$year = $values[$i];
break;
case 'y':
$year = $values[$i] >= 70 ? 1900 + $values[$i] : 2000 + $values[$i];
break;
case 'H':
case 'h':
case 'G':
case 'g':
$hour = $values[$i];
$hour = preg_replace('/^0{1}/', '', $hour);
break;
case 'i':
$minute = $values[$i];
$minute = preg_replace('/^0{1}/', '', $minute);
break;
case 's':
$second = $values[$i];
$second = preg_replace('/^0{1}/', '', $second);
break;
case 'a':
case 'A':
if ($hour <= 12) { // if AM/PM used with 24-hour - could happen :)
if ($values[$i] == 'pm' || $values[$i] == 'PM') {
$hour += 12;
if ($hour == 24) $hour = 12;
}
elseif ($values[$i] == 'am' || $values[$i] == 'AM') {
if ($hour == 12) $hour = 0;
}
}
break;
}
}
//echo "day: $day, month: $month, year: $year, hour: $hour, minute: $minute<br>";
/*if (!($year >= 1970 && $year <= 2037)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}*/
if (!($month >= 1 && $month <= 12)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
$months_days = Array ( 1 => 31,2 => 28, 3 => 31, 4 => 30,5 => 31,6 => 30, 7 => 31, 8 => 31,9 => 30,10 => 31,11 => 30,12 => 31);
if ($year % 4 == 0) $months_days[2] = 29;
if (!($day >=1 && $day <= $months_days[$month])) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
if (!($hour >=0 && $hour <= 23)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
if (!($minute >=0 && $minute <= 59)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
if (!($second >=0 && $second <= 59)) {
$object->SetError($field_name, 'bad_date_format', null, $error_params);
return $value;
}
if (!$options['use_timezone']) {
return adodb_gmmktime($hour, $minute, $second, $month, $day, $year);
}
return adodb_mktime($hour, $minute, $second, $month, $day, $year);
}
function GetSample($field, &$options, &$object)
{
return $this->Format( adodb_mktime(), $field, $object, $options['input_format']);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/unit_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/unit_formatter.php (revision 14595)
+++ branches/5.2.x/core/kernel/utility/formatters/unit_formatter.php (revision 14596)
@@ -1,117 +1,129 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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.
*/
class kUnitFormatter extends kFormatter {
/**
* The method is supposed to alter config options or cofigure object in some way based on its usage of formatters
* The methods is called for every field with formatter defined when configuring item.
* Could be used for adding additional VirtualFields to an object required by some special Formatter
*
* @param string $field_name
* @param array $field_options
* @param kDBBase $object
*/
function PrepareOptions($field_name, &$field_options, &$object)
{
if( !isset($field_options['master_field']) )
{
$regional =& $this->Application->recallObject('lang.current');
+ /* @var $regional LanguagesItem */
+
$add_fields = Array();
$options_a = Array('type' => 'int','error_field' => $field_name,'master_field' => $field_name,'format' => '%d' );
$options_b = Array('type' => 'double','error_field' => $field_name,'master_field' => $field_name,'format' => '%0.2f' );
+
switch( $regional->GetDBField('UnitSystem') )
{
case 2: // US/UK
$field_options_copy = $field_options;
unset($field_options_copy['min_value_exc']);
$add_fields[$field_name.'_a'] = kUtil::array_merge_recursive($field_options_copy, $options_a);
$add_fields[$field_name.'_b'] = kUtil::array_merge_recursive($field_options_copy, $options_b);
break;
default:
}
+
$add_fields = kUtil::array_merge_recursive($add_fields, $object->getVirtualFields());
$object->setVirtualFields($add_fields);
}
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem Validate (before validation) to get back master field value from its sub_fields
*
* @param string $field
* @param mixed $value
* @param Array $options
* @param kDBItem $object
*/
function UpdateMasterFields($field, $value, &$options, &$object)
{
- if( !isset($options['master_field']) )
- {
- if ($value == -1) return; // for infinity setting, otherwise infinity is incorrectly converted back to Kg
- $regional =& $this->Application->recallObject('lang.current');
- switch( $regional->GetDBField('UnitSystem') )
- {
- case 2: // US/UK
- $major = $this->TypeCast($object->GetDBField($field.'_a'), $options);
- $minor = $this->TypeCast($object->GetDBField($field.'_b'), $options);
- if($major === '' && $minor === '')
- {
- $value = null;
- }
- elseif($major === null && $minor === null)
- {
- $fields = $object->getFields();
- unset($fields[$field]);
- $object->setFields($fields);
- return;
- }
- else
- {
- $value = kUtil::Pounds2Kg($major, $minor);
- }
- break;
- default:
+ if ( isset($options['master_field']) || ($value == -1) ) {
+ // for infinity setting, otherwise infinity is incorrectly converted back to Kg
+ return ;
+ }
+
+ $regional =& $this->Application->recallObject('lang.current');
+ /* @var $regional LanguagesItem */
+
+ if ( $regional->GetDBField('UnitSystem') == 2 ) {
+ // US/UK
+ $major = $this->TypeCast($object->GetDBField($field . '_a'), $options);
+ $minor = $this->TypeCast($object->GetDBField($field . '_b'), $options);
+
+ if ( $major === '' && $minor === '' ) {
+ $value = null;
+ }
+ elseif ( $major === null && $minor === null ) {
+ $fields = $object->getFields();
+ unset($fields[$field]);
+
+ $object->setFields($fields);
+ return;
+ }
+ else {
+ $value = kUtil::Pounds2Kg($major, $minor);
}
- $object->SetDBField($field, $value);
}
+
+ $object->SetDBField($field, $value);
}
- function UpdateSubFields($field, $value, &$options, &$object)
+ /**
+ * Used for split fields like timestamp -> date, time
+ * Called from DBItem to update sub fields values after loading item
+ *
+ * @param string $field
+ * @param string $value
+ * @param Array $options
+ * @param kDBItem $object
+ * @return void
+ * @access public
+ */
+ public function UpdateSubFields($field, $value, &$options, &$object)
{
- if( !isset($options['master_field']) )
- {
+ if ( !isset($options['master_field']) ) {
$regional =& $this->Application->recallObject('lang.current');
- switch( $regional->GetDBField('UnitSystem') )
- {
- case 2: // US/UK
- if($value === null)
- {
- $major = null;
- $minor = null;
- }
- else
- {
- list($major,$minor) = kUtil::Kg2Pounds($value);
- /*$major = floor( $value / 0.5 );
- $minor = ($value - $major * 0.5) * 32;*/
- }
- $object->SetDBField($field.'_a', $major);
- $object->SetDBField($field.'_b', $minor);
- break;
- default:
+ /* @var $regional LanguagesItem */
+
+ if ( $regional->GetDBField('UnitSystem') == 2 ) {
+ // US/UK
+ if ( $value === null ) {
+ $major = null;
+ $minor = null;
+ }
+ else {
+ list($major, $minor) = kUtil::Kg2Pounds($value);
+// $major = floor( $value / 0.5 );
+// $minor = ($value - $major * 0.5) * 32;
+ }
+
+ $object->SetDBField($field . '_a', $major);
+ $object->SetDBField($field . '_b', $minor);
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/formatter.php (revision 14595)
+++ branches/5.2.x/core/kernel/utility/formatters/formatter.php (revision 14596)
@@ -1,258 +1,296 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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.
*/
class kFormatter extends kBase {
/**
* Reference to category helper
*
* @var CategoryHelper
*/
var $_categoryHelper = null;
/**
* Creates formatter instance
*
* @access public
*/
public function __construct()
{
parent::__construct();
$this->_categoryHelper =& $this->Application->recallObject('CategoryHelper');
}
/**
* Replace FCK links like "@@ID@@" to real page urls, when "using_fck" option is set.
*
* @param string $text
* @param Array $options
* @param string $format
* @return string
*/
function _replaceFCKLinks(&$value, $options, $format = null)
{
if ((isset($format) && strpos($format, 'fck_ready') !== false) || (!array_key_exists('using_fck', $options) || !$options['using_fck'])) {
// in textarea, where fck will be used OR not using fck
return $value;
}
return $this->_categoryHelper->replacePageIds($value);
}
/**
* Convert's value to match type from config
*
* @param mixed $value
* @param Array $options
* @return mixed
* @access protected
*/
function TypeCast($value, $options)
{
$ret = true;
- if( isset($options['type']) )
- {
+
+ if ( isset($options['type']) ) {
$field_type = $options['type'];
+
if ($field_type == 'numeric') {
- trigger_error('Invalid field type <strong>'.$field_type.'</strong> (in TypeCast method), please use <strong>float</strong> instead', E_USER_NOTICE);
+ trigger_error('Invalid field type <strong>' . $field_type . '</strong> (in TypeCast method), please use <strong>float</strong> instead', E_USER_NOTICE);
$field_type = 'float';
}
- $type_ok = preg_match('#int|integer|double|float|real|numeric|string#', $field_type);
- if ($field_type == 'string') {
- if (!$this->Application->isAdmin && isset($options['allow_html']) && $options['allow_html']) {
+ elseif ( $field_type == 'string' ) {
+ if ( !$this->Application->isAdmin && isset($options['allow_html']) && $options['allow_html'] ) {
// this allows to revert htmlspecialchars call for each field submitted on front-end
$value = kUtil::unhtmlentities($value);
}
- return $value;
- }
- static $comma = null;
- static $thousands = null;
- if (is_null($comma) || is_null($thousands)) {
- $lang =& $this->Application->recallObject('lang.current');
- $comma = $lang->GetDBField('DecimalPoint');
- $thousands = $lang->GetDBField('ThousandSep');
+ return $value;
}
- $value = str_replace($thousands, '', $value);
- $value = str_replace($comma, '.', $value);
+ $value = $this->formatNumber($value);
+ $type_ok = preg_match('#int|integer|double|float|real|numeric|string#', $field_type);
- if ($value != '' && $type_ok)
- {
+ if ( $value != '' && $type_ok ) {
$ret = is_numeric($value);
- if($ret)
- {
- $f = 'is_'.$field_type;
+
+ if ($ret) {
+ $f = 'is_' . $field_type;
settype($value, $field_type);
$ret = $f($value);
}
}
}
return $ret ? $value : false;
}
- function TypeCastArray($src, &$object)
+ /**
+ * Formats number, according to regional settings
+ *
+ * @param string $number
+ * @return float
+ */
+ function formatNumber($number)
+ {
+ static $comma = null, $thousands = null;
+
+ if ( !isset($comma) || !isset($thousands) ) {
+ $lang =& $this->Application->recallObject('lang.current');
+ /* @var $lang LanguagesItem */
+
+ $comma = $lang->GetDBField('DecimalPoint');
+ $thousands = $lang->GetDBField('ThousandSep');
+ }
+
+ $number = str_replace($thousands, '', $number);
+ $number = str_replace($comma, '.', $number);
+
+ return $number;
+ }
+
+ /**
+ * Applies type casting on each array element
+ * @param Array $src
+ * @param kDBItem|kDBList|kDBBase $object
+ * @return Array
+ * @access public
+ */
+ public function TypeCastArray($src, &$object)
{
- $dst = array();
+ $dst = array ();
+
foreach ($src as $id => $row) {
- $tmp_row = array();
+ $tmp_row = array ();
foreach ($row as $fld => $value) {
$field_options = $object->GetFieldOptions($fld);
$tmp_row[$fld] = $this->TypeCast($value, $field_options);
}
$dst[$id] = $tmp_row;
}
+
return $dst;
}
-//function Format($value, $options, &$errors)
+ /**
+ * Formats value of a given field
+ *
+ * @param string $value
+ * @param string $field_name
+ * @param kDBItem|kDBList|kDBBase $object
+ * @param string $format
+ * @return string
+ */
function Format($value, $field_name, &$object, $format = null)
{
if ( is_null($value) ) {
return '';
}
$options = $object->GetFieldOptions($field_name);
if (!isset($format) && array_key_exists('format', $options)) {
$format = $options['format'];
}
if ($value === false) {
// used ?
return $value; // for leaving badly formatted date on the form
}
$original_format = $format;
if (isset($format)) {
if (strpos($format, 'fck_ready') !== false) {
$format = trim(str_replace('fck_ready', '', $format), ';');
}
}
if (isset($format) && $format) {
$value = sprintf($format, $value);
}
if (preg_match('#int|integer|double|float|real|numeric#', $options['type'])) {
$lang =& $this->Application->recallObject('lang.current');
+ /* @var $lang LanguagesItem */
+
return $lang->formatNumber($value);
}
elseif ($options['type'] == 'string') {
$value = $this->_replaceFCKLinks($value, $options, $original_format);
}
return $value;
}
/**
* Performs basic type validation on form field value
*
* @param mixed $value
* @param string $field_name
- * @param kDBItem $object
+ * @param kDBItem|kDBList|kDBBase $object
* @return mixed
+ * @access public
*/
- function Parse($value, $field_name, &$object)
+ public function Parse($value, $field_name, &$object)
{
if ($value == '') {
return NULL;
}
$options = $object->GetFieldOptions($field_name);
- $tc_value = $this->TypeCast($value,$options);
+ $tc_value = $this->TypeCast($value, $options);
+
if ($tc_value === false) {
return $value; // for leaving badly formatted date on the form
}
if(isset($options['type'])) {
if (preg_match('#double|float|real|numeric#', $options['type'])) {
$tc_value = str_replace(',', '.', $tc_value);
}
}
if (isset($options['regexp'])) {
if (!preg_match($options['regexp'], $value)) {
$object->SetError($field_name, 'invalid_format');
}
}
return $tc_value;
}
function HumanFormat($format)
{
return $format;
}
/**
* The method is supposed to alter config options or cofigure object in some way based on its usage of formatters
* The methods is called for every field with formatter defined when configuring item.
* Could be used for adding additional VirtualFields to an object required by some special Formatter
*
* @param string $field_name
* @param array $field_options
* @param kDBBase $object
*/
function PrepareOptions($field_name, &$field_options, &$object)
{
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem to update sub fields values after loading item
*
- * @param unknown_type $field
- * @param unknown_type $value
- * @param unknown_type $options
- * @param unknown_type $object
+ * @param string $field
+ * @param string $value
+ * @param Array $options
+ * @param kDBItem|kDBList|kDBBase $object
+ * @return void
+ * @access public
*/
- function UpdateSubFields($field, $value, &$options, &$object)
+ public function UpdateSubFields($field, $value, &$options, &$object)
{
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem Validate (before validation) to get back master field value from its sub_fields
*
* @param string $field
* @param mixed $value
* @param Array $options
- * @param kDBItem $object
+ * @param kDBItem|kDBList|kDBBase $object
*/
function UpdateMasterFields($field, $value, &$options, &$object)
{
}
-/* function GetErrorMsg($pseudo_error, $options)
- {
- if ( isset($options['error_msgs'][$pseudo_error]) ) {
- return $options['error_msgs'][$pseudo_error];
- }
- else {
- return $this->ErrorMsgs[$pseudo_error];
- }
- }*/
-
- function GetSample($field, &$options, &$object)
+ /**
+ * Return sample value, that can be entered in this field
+ *
+ * @param string $field
+ * @param Array $options
+ * @param kDBItem|kDBList|kDBBase $object
+ * @return string
+ * @access public
+ */
+ public function GetSample($field, &$options, &$object)
{
- if (isset($options['sample_value'])) return $options['sample_value'];
+ return isset($options['sample_value']) ? $options['sample_value'] : '';
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/validator.php
===================================================================
--- branches/5.2.x/core/kernel/utility/validator.php (nonexistent)
+++ branches/5.2.x/core/kernel/utility/validator.php (revision 14596)
@@ -0,0 +1,493 @@
+<?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() ) {
+ $error_msg = ' Validation failed in prefix <strong>' . $this->dataSource->Prefix . '</strong>,
+ 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 ($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_val, $max_val));
+
+ return false;
+ }
+
+ // 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 ( !$res ) {
+ $error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len'), 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
+ * @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']) ) {
+ return vsprintf($msg, $this->FieldErrors[$field]['params']);
+ }
+
+ 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();
+ }
+}
\ No newline at end of file
Property changes on: branches/5.2.x/core/kernel/utility/validator.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.2.x/core/kernel/kbase.php
===================================================================
--- branches/5.2.x/core/kernel/kbase.php (revision 14595)
+++ branches/5.2.x/core/kernel/kbase.php (revision 14596)
@@ -1,956 +1,1031 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
/**
* Base
*
*/
class kBase {
/**
* Reference to global kApplication instance
*
* @var kApplication
* @access protected
*/
protected $Application = null;
/**
* Connection to database
*
* @var kDBConnection
* @access protected
*/
protected $Conn = null;
/**
* Prefix, used during object creation
*
* @var string
* @access public
*/
public $Prefix = '';
/**
* Special, used during object creation
*
* @var string
* @access public
*/
public $Special = '';
/**
* Joined prefix and special, usually taken directly from
* tag beeing processed, to use in kApplication::recallObject method
*
* @var string
* @access protected
* @see kApplication::recallObject
*/
protected $prefixSpecial = '';
/**
* Set's references to kApplication and kDBConnection class instances
*
* @return kBase
* @access public
* @see kApplication
* @see kDBConnection
*/
public function __construct($application = null)
{
if (!isset($application)) {
$this->Application =& kApplication::Instance();
}
else {
$this->Application =& $application;
}
$this->Conn =& $this->Application->GetADODBConnection();
}
/**
* Set's prefix and special
*
* @param string $prefix
* @param string $special
* @access public
*/
public function Init($prefix, $special)
{
$prefix = explode('_', $prefix, 2);
$this->Prefix = $prefix[0];
$this->Special = $special;
$this->prefixSpecial = rtrim($this->Prefix . '.' . $this->Special, '.');
}
/**
* Returns prefix and special (when present) joined by a "."
*
* @return string
* @access public
*/
public function getPrefixSpecial()
{
return $this->prefixSpecial;
}
}
class kHelper extends kBase {
/**
* Performs helper initialization
*
* @access public
*/
public function InitHelper()
{
}
/**
* Append prefix and special to tag
* params (get them from tagname) like
* they were really passed as params
*
* @param string $prefix_special
* @param Array $tag_params
* @return Array
* @access protected
*/
protected function prepareTagParams($prefix_special, $tag_params = Array())
{
$parts = explode('.', $prefix_special);
$ret = $tag_params;
$ret['Prefix'] = $parts[0];
$ret['Special'] = count($parts) > 1 ? $parts[1] : '';
$ret['PrefixSpecial'] = $prefix_special;
return $ret;
}
}
abstract class kDBBase extends kBase {
/**
* Name of primary key field for the unit
*
* @var string
* @access public
* @see kDBBase::TableName
*/
public $IDField = '';
/**
* Unit's database table name
*
* @var string
* @access public
*/
public $TableName = '';
/**
+ * Form name, used for validation
+ *
+ * @var string
+ */
+ protected $formName = '';
+
+ /**
+ * Final form configuration
+ *
+ * @var Array
+ */
+ protected $formConfig = Array ();
+
+ /**
* SELECT, FROM, JOIN parts of SELECT query (no filters, no limit, no ordering)
*
* @var string
* @access protected
*/
protected $SelectClause = '';
/**
* Unit fields definitions (fields from database plus virtual fields)
*
* @var Array
* @access protected
*/
protected $Fields = Array ();
/**
* Mapping between unit custom field IDs and their names
*
* @var Array
* @access protected
*/
protected $customFields = Array ();
/**
* Unit virtual field definitions
*
* @var Array
* @access protected
*/
protected $VirtualFields = Array ();
/**
* Fields that need to be queried using custom expression, e.g. IF(...) AS value
*
* @var Array
* @access protected
*/
protected $CalculatedFields = Array ();
/**
* Fields that contain aggregated functions, e.g. COUNT, SUM, etc.
*
* @var Array
* @access protected
*/
protected $AggregatedCalculatedFields = Array ();
/**
* Tells, that multilingual fields sould not be populated by default.
* Can be overriden from kDBBase::Configure method
*
* @var bool
* @access protected
*/
protected $populateMultiLangFields = false;
/**
* Set object' TableName to LIVE table, defined in unit config
*
* @access public
*/
public function SwitchToLive()
{
$this->TableName = $this->Application->getUnitOption($this->Prefix, 'TableName');
}
/**
* Set object' TableName to TEMP table created based on table, defined in unit config
*
* @access public
*/
public function SwitchToTemp()
{
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$this->TableName = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix);
}
/**
* Checks if object uses temp table
*
* @return bool
* @access public
*/
public function IsTempTable()
{
return $this->Application->IsTempTable($this->TableName);
}
/**
* Sets SELECT part of list' query
*
* @param string $sql SELECT and FROM [JOIN] part of the query up to WHERE
* @access public
*/
public function SetSelectSQL($sql)
{
$this->SelectClause = $sql;
}
/**
* Returns SELECT part of list' query.
* 1. Occurences of "%1$s" and "%s" are replaced to kDBBase::TableName
* 2. Occurences of "%3$s" are replaced to temp table prefix (only for table, using TABLE_PREFIX)
*
* @param string $base_query given base query will override unit default select query
* @param bool $replace_table replace all possible occurences
* @return string
* @access public
* @see kDBBase::replaceModePrefix
*/
public function GetSelectSQL($base_query = null, $replace_table = true)
{
if (!isset($base_query)) {
$base_query = $this->SelectClause;
}
if (!$replace_table) {
return $base_query;
}
$query = str_replace(Array('%1$s', '%s'), $this->TableName, $base_query);
return $this->replaceModePrefix($query);
}
/**
* Allows substables to be in same mode as main item (e.g. LEFT JOINED ones)
*
* @param string $query
* @return string
* @access protected
*/
protected function replaceModePrefix($query)
{
$live_table = substr($this->Application->GetLiveName($this->TableName), strlen(TABLE_PREFIX));
if (preg_match('/'.preg_quote(TABLE_PREFIX, '/').'(.*)'.preg_quote($live_table, '/').'/', $this->TableName, $rets)) {
// will only happen, when table has a prefix (like in K4)
return str_replace('%3$s', $rets[1], $query);
}
// will happen, when K3 table without prefix is used
return $query;
}
/**
* Sets calculated fields
*
* @param Array $fields
* @access public
*/
public function setCalculatedFields($fields)
{
$this->CalculatedFields = $fields;
}
/**
* Adds calculated field declaration to object.
*
* @param string $name
* @param string $sql_clause
* @access public
*/
public function addCalculatedField($name, $sql_clause)
{
$this->CalculatedFields[$name] = $sql_clause;
}
/**
* Returns required mixing of aggregated & non-aggregated calculated fields
*
* @param int $aggregated 0 - having + aggregated, 1 - having only, 2 - aggregated only
* @return Array
* @access public
*/
public function getCalculatedFields($aggregated = 1)
{
switch ($aggregated) {
case 0:
$fields = array_merge($this->CalculatedFields, $this->AggregatedCalculatedFields);
break;
case 1:
$fields = $this->CalculatedFields;
break;
case 2:
$fields = $this->AggregatedCalculatedFields; // TODO: never used
break;
default:
$fields = Array();
break;
}
return $fields;
}
/**
* Checks, that given field is a calculated field
*
* @param string $field
* @return bool
* @access public
*/
public function isCalculatedField($field)
{
return array_key_exists($field, $this->CalculatedFields);
}
/**
* Insert calculated fields sql into query in place of %2$s,
* return processed query.
*
* @param string $query
* @param int $aggregated 0 - having + aggregated, 1 - having only, 2 - aggregated only
* @return string
* @access protected
*/
protected function addCalculatedFields($query, $aggregated = 1)
{
$fields = $this->getCalculatedFields($aggregated);
if ($fields) {
$sql = Array ();
$fields = str_replace('%2$s', $this->Application->GetVar('m_lang'), $fields);
foreach ($fields as $field_name => $field_expression) {
$sql[] = '('.$field_expression.') AS `'.$field_name.'`';
}
$sql = implode(',',$sql);
return $this->Application->ReplaceLanguageTags( str_replace('%2$s', ','.$sql, $query) );
}
return str_replace('%2$s', '', $query);
}
/**
* Performs initial object configuration, which includes setting the following:
* - primary key and table name
* - field definitions (including field modifiers, formatters, default values)
*
* @param bool $populate_ml_fields create all ml fields from db in config or not
+ * @param string $form_name form name for validation
* @access public
*/
- public function Configure($populate_ml_fields = null)
+ public function Configure($populate_ml_fields = null, $form_name = null)
{
if ( isset($populate_ml_fields) ) {
$this->populateMultiLangFields = $populate_ml_fields;
}
$this->IDField = $this->Application->getUnitOption($this->Prefix, 'IDField');
$this->TableName = $this->Application->getUnitOption($this->Prefix, 'TableName');
+ $this->initForm($form_name);
$this->defineFields();
$this->ApplyFieldModifiers(); // should be called only after all fields definitions been set
$this->prepareConfigOptions(); // this should go last, but before setDefaultValues, order is significant!
// only set on first call of method
if ( isset($populate_ml_fields) ) {
$this->SetDefaultValues();
}
}
/**
+ * Adjusts object accoding to given form name
+ *
+ */
+ protected function initForm($form_name = null)
+ {
+ $forms = $this->Application->getUnitOption($this->Prefix, 'Forms', Array ());
+
+ $this->formName = $form_name;
+ $this->formConfig = isset($forms['default']) ? $forms['default'] : Array ();
+
+ if ( !$this->formName ) {
+ return ;
+ }
+
+ if ( !isset($forms[$this->formName]) ) {
+ trigger_error('Form "<strong>' . $this->formName . '</strong>" isn\'t declared in "<strong>' . $this->Prefix . '</strong>" unit config.', E_USER_NOTICE);
+ }
+ else {
+ $this->formConfig = kUtil::array_merge_recursive($this->formConfig, $forms[$this->formName]);
+ }
+ }
+
+ /**
* Add field definitions from all possible sources
* Used field sources: database fields, custom fields, virtual fields, calculated fields, aggregated calculated fields
*
* @access protected
*/
protected function defineFields()
{
- $this->Fields = $this->Application->getUnitOption($this->Prefix, 'Fields', Array ());
- $this->customFields = $this->Application->getUnitOption($this->Prefix, 'CustomFields', Array());
+ $this->Fields = $this->getFormOption('Fields', Array ());
+ $this->customFields = $this->getFormOption('CustomFields', Array());
- $this->setVirtualFields( $this->Application->getUnitOption($this->Prefix, 'VirtualFields', Array ()) );
+ $this->setVirtualFields( $this->getFormOption('VirtualFields', Array ()) );
- $calculated_fields = $this->Application->getUnitOption($this->Prefix, 'CalculatedFields', Array());
+ $calculated_fields = $this->getFormOption('CalculatedFields', Array());
$this->CalculatedFields = $this->getFieldsBySpecial($calculated_fields);
- $aggregated_calculated_fields = $this->Application->getUnitOption($this->Prefix, 'AggregatedCalculatedFields', Array());
+ $aggregated_calculated_fields = $this->getFormOption('AggregatedCalculatedFields', Array());
$this->AggregatedCalculatedFields = $this->getFieldsBySpecial($aggregated_calculated_fields);
}
/**
+ * Returns form name, used for validation
+ *
+ * @return string
+ */
+ public function getFormName()
+ {
+ return $this->formName;
+ }
+
+ /**
+ * Reads unit (specified by $prefix) option specified by $option and applies form change to it
+ *
+ * @param string $option
+ * @param mixed $default
+ * @return string
+ * @access public
+ */
+ public function getFormOption($option, $default = false)
+ {
+ $ret = $this->Application->getUnitOption($this->Prefix, $option, $default);
+
+ if ( isset($this->formConfig[$option]) ) {
+ $ret = kUtil::array_merge_recursive($ret, $this->formConfig[$option]);
+ }
+
+ return $ret;
+ }
+
+ /**
* Only exteracts fields, that match current object Special
*
* @param Array $fields
* @return Array
* @access protected
*/
protected function getFieldsBySpecial($fields)
{
if ( array_key_exists($this->Special, $fields) ) {
return $fields[$this->Special];
}
return array_key_exists('', $fields) ? $fields[''] : Array();
}
/**
* Sets aggeregated calculated fields
*
* @param Array $fields
* @access public
*/
public function setAggregatedCalculatedFields($fields)
{
$this->AggregatedCalculatedFields = $fields;
}
/**
* Set's field names from table from config
*
* @param Array $fields
* @access public
*/
public function setCustomFields($fields)
{
$this->customFields = $fields;
}
/**
* Returns custom fields information from table from config
*
* @return Array
* @access public
*/
public function getCustomFields()
{
return $this->customFields;
}
/**
* Set's fields information from table from config
*
* @param Array $fields
* @access public
*/
public function setFields($fields)
{
$this->Fields = $fields;
}
/**
* Returns fields information from table from config
*
* @return Array
* @access public
*/
public function getFields()
{
return $this->Fields;
}
/**
* Checks, that given field exists
*
* @param string $field
* @return bool
* @access public
*/
public function isField($field)
{
return array_key_exists($field, $this->Fields);
}
/**
* Override field options with ones defined in submit via "field_modfiers" array (common for all prefixes)
*
- * @author Alex
+ * @param Array $field_modifiers
+ * @return void
* @access public
+ * @author Alex
*/
public function ApplyFieldModifiers($field_modifiers = null)
{
- $allowed_modifiers = Array('required', 'multiple');
+ $allowed_modifiers = Array ('required', 'multiple');
- if ($this->Application->isAdminUser) {
+ if ( $this->Application->isAdminUser ) {
// can change upload dir on the fly (admin only!)
$allowed_modifiers[] = 'upload_dir';
}
- if (!isset($field_modifiers)) {
+ if ( !isset($field_modifiers) ) {
$field_modifiers = $this->Application->GetVar('field_modifiers');
- if (!$field_modifiers) {
+ if ( !$field_modifiers ) {
// no field modifiers
- return false;
+ return ;
}
$field_modifiers = getArrayValue($field_modifiers, $this->getPrefixSpecial());
}
- if (!$field_modifiers) {
+ if ( !$field_modifiers ) {
// no field modifiers for current prefix_special
- return false;
+ return ;
}
- foreach ($field_modifiers as $field => $field_options)
- {
- foreach ($field_options as $option_name => $option_value)
- {
- if ( !in_array(strtolower($option_name), $allowed_modifiers) ) continue;
+ foreach ($field_modifiers as $field => $field_options) {
+ foreach ($field_options as $option_name => $option_value) {
+ if ( !in_array(strtolower($option_name), $allowed_modifiers) ) {
+ continue;
+ }
+
$this->Fields[$field][$option_name] = $option_value;
}
}
}
/**
* Set fields (+options) for fields that physically doesn't exist in database
*
* @param Array $fields
* @access public
*/
public function setVirtualFields($fields)
{
if ($fields) {
$this->VirtualFields = $fields;
$this->Fields = array_merge($this->VirtualFields, $this->Fields);
}
}
/**
* Returns virtual fields
*
* @return Array
* @access public
*/
public function getVirtualFields()
{
return $this->VirtualFields;
}
/**
* Checks, that given field is a virtual field
*
* @param string $field
* @return bool
* @access public
*/
public function isVirtualField($field)
{
return array_key_exists($field, $this->VirtualFields);
}
/**
* Performs additional initialization for field default values
*
* @access protected
*/
protected function SetDefaultValues()
{
foreach ($this->Fields as $field => $options) {
if ( array_key_exists('default', $options) && $options['default'] === '#NOW#' ) {
$this->Fields[$field]['default'] = adodb_mktime();
}
}
}
/**
* Overwrites field definition in unit config
*
* @param string $field
* @param Array $options
* @param bool $is_virtual
* @access public
*/
public function SetFieldOptions($field, $options, $is_virtual = false)
{
if ($is_virtual) {
$this->VirtualFields[$field] = $options;
$this->Fields = array_merge($this->VirtualFields, $this->Fields);
}
else {
$this->Fields[$field] = $options;
}
}
/**
* Changes/sets given option's value in given field definiton
*
* @param string $field
* @param string $option_name
* @param mixed $option_value
* @param bool $is_virtual
* @access public
*/
public function SetFieldOption($field, $option_name, $option_value, $is_virtual = false)
{
if ($is_virtual) {
$this->VirtualFields[$field][$option_name] = $option_value;
}
$this->Fields[$field][$option_name] = $option_value;
}
/**
* Returns field definition from unit config.
* Also executes sql from "options_sql" field option to form "options" field option
*
* @param string $field
* @param bool $is_virtual
* @return Array
* @access public
*/
public function GetFieldOptions($field, $is_virtual = false)
{
$property_name = $is_virtual ? 'VirtualFields' : 'Fields';
if ( !array_key_exists($field, $this->$property_name) ) {
return Array ();
}
if (!$is_virtual) {
if (!array_key_exists('options_prepared', $this->Fields[$field]) || !$this->Fields[$field]['options_prepared']) {
// executes "options_sql" from field definition, only when field options are accessed (late binding)
$this->PrepareFieldOptions($field);
$this->Fields[$field]['options_prepared'] = true;
}
}
return $this->{$property_name}[$field];
}
/**
* Returns field option
*
* @param string $field
* @param string $option_name
* @param string $is_virtual
* @param string $default
* @return string
* @access public
*/
public function GetFieldOption($field, $option_name, $is_virtual = false, $default = false)
{
$field_options = $this->GetFieldOptions($field, $is_virtual);
if (!$field_options) {
return $field_options;
}
return array_key_exists($option_name, $field_options) ? $field_options[$option_name] : $default;
}
/**
* Returns formatted field value
*
* @param string $name
* @param string $format
*
* @return string
* @access protected
*/
public function GetField($name, $format = null)
{
- $options = $this->GetFieldOptions($name);
+ $formatter_class = $this->GetFieldOption($name, 'formatter');
- if (array_key_exists('formatter', $options)) {
- $formatter_class = $options['formatter'];
+ if ( $formatter_class ) {
$value = ($formatter_class == 'kMultiLanguage') && !preg_match('/^l[0-9]+_/', $name) ? '' : $this->GetDBField($name);
$formatter =& $this->Application->recallObject($formatter_class);
+ /* @var $formatter kFormatter */
+
return $formatter->Format($value, $name, $this, $format);
}
return $this->GetDBField($name);
}
/**
* Returns unformatted field value
*
* @param string $field
* @return string
* @access protected
*/
abstract protected function GetDBField($field);
/**
* Checks of object has given field
*
* @param string $name
* @return bool
* @access protected
*/
abstract protected function HasField($name);
/**
* Returns field values
*
* @return Array
* @access protected
*/
abstract protected function GetFieldValues();
/**
* Populates values of sub-fields, based on formatters, set to mater fields
*
* @param Array $fields
* @access public
- * @todo maybe should not be publically accessable
+ * @todo Maybe should not be publicly accessible
*/
public function UpdateFormattersSubFields($fields = null)
{
- if (!is_array($fields)) {
+ if ( !is_array($fields) ) {
$fields = array_keys($this->Fields);
}
+
foreach ($fields as $field) {
if ( isset($this->Fields[$field]['formatter']) ) {
$formatter =& $this->Application->recallObject($this->Fields[$field]['formatter']);
+ /* @var $formatter kFormatter */
+
$formatter->UpdateSubFields($field, $this->GetDBField($field), $this->Fields[$field], $this);
}
}
}
/**
* Use formatters, specified in field declarations to perform additional field initialization in unit config
*
* @access protected
*/
protected function prepareConfigOptions()
{
$field_names = array_keys($this->Fields);
foreach ($field_names as $field_name) {
if ( !array_key_exists('formatter', $this->Fields[$field_name]) ) {
continue;
}
$formatter =& $this->Application->recallObject( $this->Fields[$field_name]['formatter'] );
/* @var $formatter kFormatter */
$formatter->PrepareOptions($field_name, $this->Fields[$field_name], $this);
}
}
/**
* Escapes fields only, not expressions
*
* @param string $field_expr
* @return string
* @access protected
*/
protected function escapeField($field_expr)
{
return preg_match('/[.(]/', $field_expr) ? $field_expr : '`' . $field_expr . '`';
}
/**
* Replaces current language id in given field options
*
* @param string $field_name
* @param Array $field_option_names
* @access protected
*/
protected function _replaceLanguageId($field_name, $field_option_names)
{
// don't use GetVar('m_lang') since it's always equals to default language on editing form in admin
$current_language_id = $this->Application->Phrases->LanguageId;
$primary_language_id = $this->Application->GetDefaultLanguageId();
$field_options =& $this->Fields[$field_name];
foreach ($field_option_names as $option_name) {
$field_options[$option_name] = str_replace('%2$s', $current_language_id, $field_options[$option_name]);
$field_options[$option_name] = str_replace('%3$s', $primary_language_id, $field_options[$option_name]);
}
}
/**
* Transforms "options_sql" field option into valid "options" array for given field
*
* @param string $field_name
* @access protected
*/
protected function PrepareFieldOptions($field_name)
{
$field_options =& $this->Fields[$field_name];
if (array_key_exists('options_sql', $field_options) ) {
// get options based on given sql
$replace_options = Array ('option_title_field', 'option_key_field', 'options_sql');
$this->_replaceLanguageId($field_name, $replace_options);
$select_clause = $this->escapeField($field_options['option_title_field']) . ',' . $this->escapeField($field_options['option_key_field']);
$sql = sprintf($field_options['options_sql'], $select_clause);
if (array_key_exists('serial_name', $field_options)) {
// try to cache option sql on serial basis
$cache_key = 'sql_' . crc32($sql) . '[%' . $field_options['serial_name'] . '%]';
$dynamic_options = $this->Application->getCache($cache_key);
if ($dynamic_options === false) {
$this->Conn->nextQueryCachable = true;
$dynamic_options = $this->Conn->GetCol($sql, preg_replace('/^.*?\./', '', $field_options['option_key_field']));
$this->Application->setCache($cache_key, $dynamic_options);
}
}
else {
// don't cache options sql
$dynamic_options = $this->Conn->GetCol($sql, preg_replace('/^.*?\./', '', $field_options['option_key_field']));
}
$options_hash = array_key_exists('options', $field_options) ? $field_options['options'] : Array ();
$field_options['options'] = kUtil::array_merge_recursive($options_hash, $dynamic_options); // because of numeric keys
}
}
/**
* Returns ID of currently processed record
*
* @return int
* @access public
*/
public function GetID()
{
return $this->GetDBField($this->IDField);
}
/**
* Allows kDBTagProcessor.SectionTitle to detect if it's editing or new item creation
*
* @return bool
* @access public
*/
public function IsNewItem()
{
return $this->GetID() ? false : true;
}
/**
* Returns parent table information
*
* @param string $special special of main item
* @param bool $guess_special if object retrieved with specified special is not loaded, then try not to use special
* @return Array
* @access public
*/
public function getLinkedInfo($special = '', $guess_special = false)
{
$parent_prefix = $this->Application->getUnitOption($this->Prefix, 'ParentPrefix');
if ($parent_prefix) {
// if this is linked table, then set id from main table
$table_info = Array (
'TableName' => $this->Application->getUnitOption($this->Prefix,'TableName'),
'IdField' => $this->Application->getUnitOption($this->Prefix,'IDField'),
'ForeignKey' => $this->Application->getUnitOption($this->Prefix,'ForeignKey'),
'ParentTableKey' => $this->Application->getUnitOption($this->Prefix,'ParentTableKey'),
'ParentPrefix' => $parent_prefix
);
if (is_array($table_info['ForeignKey'])) {
$table_info['ForeignKey'] = getArrayValue($table_info, 'ForeignKey', $parent_prefix);
}
if (is_array($table_info['ParentTableKey'])) {
$table_info['ParentTableKey'] = getArrayValue($table_info, 'ParentTableKey', $parent_prefix);
}
$main_object =& $this->Application->recallObject($parent_prefix.'.'.$special, null, Array ('raise_warnings' => 0));
/* @var $main_object kDBItem */
if (!$main_object->isLoaded() && $guess_special) {
$main_object =& $this->Application->recallObject($parent_prefix);
}
return array_merge($table_info, Array('ParentId'=> $main_object->GetDBField( $table_info['ParentTableKey'] ) ) );
}
return false;
}
/**
* Returns true, when list/item was queried/loaded
*
* @return bool
* @access protected
*/
abstract protected function isLoaded();
/**
* Returns specified field value from all selected rows.
* Don't affect current record index
*
* @param string $field
* @return Array
* @access protected
*/
abstract protected function GetCol($field);
}
\ No newline at end of file
Index: branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php
===================================================================
--- branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php (revision 14595)
+++ branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php (revision 14596)
@@ -1,325 +1,330 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 MailingListEventHandler extends kDBEventHandler {
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnCancelMailing' => Array ('self' => 'edit'),
'OnGenerateEmailQueue' => Array ('self' => true),
'OnProcessEmailQueue' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Prepare recipient list
*
* @param kEvent $event
*/
function OnNew(&$event)
{
parent::OnNew($event);
$recipient_type = $this->Application->GetVar('mailing_recipient_type');
if (!$recipient_type) {
return ;
}
$recipients = $this->Application->GetVar($recipient_type);
if ($recipients) {
$object =& $event->getObject();
/* @var $object kDBItem */
$to = $recipient_type . '_' . implode(';' . $recipient_type . '_', array_keys($recipients));
$object->SetDBField('To', $to);
}
}
/**
* Don't allow to delete mailings in progress
*
* @param kEvent $event
+ * @param string $type
+ * @return void
+ * @access protected
*/
- function customProcessing(&$event, $type)
+ protected function customProcessing(&$event, $type)
{
if ($event->Name == 'OnMassDelete' && $type == 'before') {
$ids = $event->getEventParam('ids');
if ($ids) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $ids) . ') AND Status <> ' . MailingList::PARTIALLY_PROCESSED;
$allowed_ids = $this->Conn->GetCol($sql);
$event->setEventParam('ids', $allowed_ids);
}
}
}
/**
* Delete all realted mails in email queue
*
* @param kEvent $event
*/
function OnAfterItemDelete(&$event)
{
parent::OnAfterItemDelete($event);
$this->_deleteQueue($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// delete mailing attachments after mailing is deleted
$attachments = $object->GetField('Attachments', 'file_paths');
if ($attachments) {
$attachments = explode('|', $attachments);
foreach ($attachments as $attachment_file) {
if (file_exists($attachment_file)) {
unlink($attachment_file);
}
}
}
}
/**
* Cancels given mailing and deletes all it's email queue
*
* @param kEvent $event
*/
function OnCancelMailing(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
foreach ($ids as $id) {
$object->Load($id);
$object->SetDBField('Status', MailingList::CANCELLED);
$object->Update();
}
}
$this->clearSelectedIDs($event);
}
/**
* Checks, that at least one message text field is filled
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
- if (!$this->Application->GetVar('mailing_recipient_type')) {
+ if ( !$this->Application->GetVar('mailing_recipient_type') ) {
// user manually typed email addresses -> normalize
$recipients = str_replace(',', ';', $object->GetDBField('To'));
$recipients = array_map('trim', explode(';', $recipients));
$object->SetDBField('To', implode(';', $recipients));
}
- if (!$object->GetDBField('MessageText')) {
- $object->setRequired('MessageHtml', true);
+ if ( !$object->GetDBField('MessageText') ) {
+ $object->setRequired('MessageHtml');
}
// remember user, who created mailing, because of his name
// is needed for "From" field, but mailing occurs from cron
$user_id = $this->Application->RecallVar('user_id');
$object->SetDBField('PortalUserId', $user_id);
}
/**
* Deletes mailing list email queue, when it becomes cancelled
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$status = $object->GetDBField('Status');
if (($status != $object->GetOriginalField('Status')) && ($status == MailingList::CANCELLED)) {
$this->_deleteQueue($event);
}
}
/**
* Deletes email queue records related with given mailing list
*
* @param kEvent $event
*/
function _deleteQueue(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'DELETE FROM ' . $this->Application->getUnitOption('email-queue', 'TableName') . '
WHERE MailingId = ' . $object->GetID();
$this->Conn->Query($sql);
}
/**
* Allows to safely get mailing configuration variables
*
* @param string $variable_name
* @return int
*/
function _ensureDefault($variable_name)
{
$value = $this->Application->ConfigValue($variable_name);
if ($value === false) {
// ensure default value, when configuration variable is missing
return 10;
}
if (!$value) {
// configuration variable found, but it's value is empty or zero
return false;
}
return $value;
}
/**
* Generates email queue for active mailing lists
*
* @param kEvent $event
*/
function OnGenerateEmailQueue(&$event)
{
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$where_clause = Array (
'Status NOT IN (' . MailingList::CANCELLED . ',' . MailingList::PROCESSED . ')',
'(EmailsQueued < EmailsTotal) OR (EmailsTotal = 0)',
'`To` <> ""',
);
$sql = 'SELECT *
FROM ' . $table_name . '
WHERE (' . implode(') AND (', $where_clause) . ')
ORDER BY ' . $id_field . ' ASC';
$mailing_lists = $this->Conn->Query($sql, $id_field);
if (!$mailing_lists) {
return ;
}
// queue 10 emails per step summary from all mailing lists (FIFO logic)
$to_queue = $this->_ensureDefault('MailingListQueuePerStep');
if ($to_queue === false) {
return ;
}
$mailing_list_helper =& $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
foreach ($mailing_lists as $mailing_id => $mailing_data) {
if ($mailing_data['EmailsTotal'] == 0) {
// no work performed on this mailing list -> calculate totals
$updated_fields = $mailing_list_helper->generateRecipients($mailing_id, $mailing_data);
$updated_fields['Status'] = MailingList::PARTIALLY_PROCESSED;
$mailing_data = array_merge($mailing_data, $updated_fields);
$this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id);
}
$emails = unserialize( $mailing_data['ToParsed'] );
if (!$emails) {
continue;
}
// queue allowed count of emails
$i = 0;
$process_count = count($emails) >= $to_queue ? $to_queue : count($emails);
while ($i < $process_count) {
$mailing_list_helper->queueEmail($emails[$i], $mailing_id, $mailing_data);
$i++;
}
// remove processed emails from array
$to_queue -= $process_count; // decrement available for processing email count
array_splice($emails, 0, $process_count);
$updated_fields = Array (
'ToParsed' => serialize($emails),
'EmailsQueued' => $mailing_data['EmailsQueued'] + $process_count,
);
$mailing_data = array_merge($mailing_data, $updated_fields);
$this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id);
if (!$to_queue) {
// emails to be queued per step reached -> leave
break;
}
}
}
/**
* Process email queue from cron
*
* @param kEvent $event
*/
function OnProcessEmailQueue(&$event)
{
$deliver_count = $this->_ensureDefault('MailingListSendPerStep');
if ($deliver_count === false) {
return ;
}
$queue_table = $this->Application->getUnitOption('email-queue', 'TableName');
// get queue part to send
$sql = 'SELECT *
FROM ' . $queue_table . '
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')
LIMIT 0,' . $deliver_count;
$messages = $this->Conn->Query($sql);
if (!$messages) {
// no more messages left in queue
return ;
}
$mailing_list_helper =& $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
$mailing_list_helper->processQueue($messages);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/users/users_tag_processor.php
===================================================================
--- branches/5.2.x/core/units/users/users_tag_processor.php (revision 14595)
+++ branches/5.2.x/core/units/users/users_tag_processor.php (revision 14596)
@@ -1,336 +1,297 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 UsersTagProcessor extends kDBTagProcessor
{
function LogoutLink($params)
{
$pass = Array('pass' => 'all,m,u', 'u_event' => 'OnLogout', 'm_cat_id' => 0, '__NO_REWRITE__' => 1);
$logout_template = $this->SelectParam($params, 'template,t');
return $this->Application->HREF($logout_template, '', $pass);
}
function UseUsernames($params)
{
return $this->Application->ConfigValue('Email_As_Login') != 1;
}
function RegistrationEnabled($params)
{
return $this->Application->ConfigValue('User_Allow_New') != 2;
}
function SuggestRegister($params)
{
return !$this->Application->LoggedIn() && !$this->Application->ConfigValue('Comm_RequireLoginBeforeCheckout') && $this->RegistrationEnabled($params);
}
function ConfirmPasswordLink($params)
{
$user =& $this->Application->recallObject($this->Prefix . '.email-to');
/* @var $user UsersItem */
$code = $this->getCachedCode();
$user->SetDBField('PwResetConfirm', $code);
$user->SetDBField('PwRequestTime_date', adodb_mktime());
$user->SetDBField('PwRequestTime_time', adodb_mktime());
if ( $user->GetChangedFields() ) {
// tag is called 2 times within USER.PWDC email event, so don't update user record twice
$user->Update();
}
$params['user_key'] = $code;
if ( !$this->SelectParam($params, 'template,t') ) {
$params['template'] = $this->Application->GetVar('reset_confirm_template');
}
return $this->Application->ProcessParsedTag('m', 'Link', $params);
}
/**
* Generates & caches code for password confirmation link
*
* @return string
*/
function getCachedCode()
{
static $code = null;
if ( !isset($code) ) {
$code = md5($this->GenerateCode());
}
return $code;
}
function GenerateCode()
{
list($usec, $sec) = explode(" ",microtime());
$id_part_1 = substr($usec, 4, 4);
$id_part_2 = mt_rand(1,9);
$id_part_3 = substr($sec, 6, 4);
$digit_one = substr($id_part_1, 0, 1);
if ($digit_one == 0) {
$digit_one = mt_rand(1,9);
$id_part_1 = preg_replace('/^0/', '', $id_part_1);
$id_part_1=$digit_one.$id_part_1;
}
return $id_part_1.$id_part_2.$id_part_3;
}
function TestCodeIsValid($params)
{
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$code_type = isset($params['code_type']) ? $params['code_type'] : 'forgot_password';
$expiration_timeout = isset($params['expiration_timeout']) ? $params['expiration_timeout'] : null;
$user_id = $user_helper->validateUserCode($this->Application->GetVar('user_key'), $code_type, $expiration_timeout);
if ( !is_numeric($user_id) ) {
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->getObject( Array('skip_autoload' => true) ); // TODO: change theme too
/* @var $object UsersItem */
$object->SetError('PwResetConfirm', $user_id, $this->_getUserCodeErrorMsg($user_id, $code_type, $params));
return false;
}
return true;
}
/**
* Returns error message set by given code type
*
* @param string $error_code
* @param Array $params
* @return string
*/
function _getUserCodeErrorMsg($error_code, $code_type, $params)
{
$error_messages = Array (
'forgot_password' => Array (
'code_is_not_valid' => 'lu_code_is_not_valid',
'code_expired' => 'lu_code_expired',
),
'activation' => Array (
'code_is_not_valid' => 'lu_error_ActivationCodeNotValid',
'code_expired' => 'lu_error_ActivationCodeExpired',
),
);
if ($code_type == 'custom') {
// custom error messages are given directly in tag
$error_messages[$code_type] = Array (
'code_is_not_valid' => $params['error_invalid'],
'code_expired' => $params['error_expired'],
);
}
return $error_messages[$code_type][$error_code];
}
/**
* Returns sitem administrator email
*
* @param Array $params
* @return string
*/
function SiteAdminEmail($params)
{
return $this->Application->ConfigValue('Smtp_AdminMailFrom');
}
- function AffiliatePaymentTypeChecked($params)
- {
- static $checked = false;
-
- if( $this->Application->GetVar('PaymentTypeId') )
- {
- $apt_object =& $this->Application->recallObject('apt.active');
- if( $this->Application->GetVar('PaymentTypeId') == $apt_object->GetDBField('PaymentTypeId') )
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- if(!$checked)
- {
- $checked = true;
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- function HasError($params)
- {
- $res = parent::HasError($params);
- if($this->SelectParam($params,'field,fields') == 'any')
- {
- $res = $res || $this->Application->GetVar('MustAgreeToTerms'); // need to do it not put module fields into kernel ! (noticed by Alex)
- $res = $res || $this->Application->GetVar('SSNRequiredError');
- }
- return $res;
- }
-
/**
* Returns login name of user
*
* @param Array $params
*/
function LoginName($params)
{
$object =& $this->getObject($params);
return $object->GetID() != USER_ROOT ? $object->GetDBField('Login') : 'root';
}
function CookieUsername($params)
{
$items_info = $this->Application->GetVar( $this->getPrefixSpecial(true) );
if ( $items_info !== false ) {
return $items_info[USER_GUEST][ $params['field'] ];
}
$username = $this->Application->GetVar('save_username'); // from cookie
if ($username == 'super-root') {
$username = 'root';
}
return $username === false ? '' : $username;
}
/**
* Checks if user have one of required permissions
*
* @param Array $params
* @return bool
*/
function HasPermission($params)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
return $perm_helper->TagPermissionCheck($params);
}
/**
* Returns link to user public profile
*
* @param Array $params
* @return string
*/
function ProfileLink($params)
{
$object =& $this->getObject($params);
$params['user_id'] = $object->GetID();
return $this->Application->ProcessParsedTag('m', 'Link', $params);
}
function ImageSrc($params)
{
list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
return $tag_processed ? $ret : false;
}
function LoggedIn($params)
{
static $loggedin_status = Array ();
$object =& $this->getObject($params);
/* @var $object kDBList */
if (!isset($loggedin_status[$this->Special])) {
$user_ids = $object->GetCol($object->IDField);
$sql = 'SELECT LastAccessed, '.$object->IDField.'
FROM '.TABLE_PREFIX.'UserSession
WHERE (PortalUserId IN ('.implode(',', $user_ids).'))';
$loggedin_status[$this->Special] = $this->Conn->GetCol($sql, $object->IDField);
}
return isset($loggedin_status[$this->Special][$object->GetID()]);
}
/**
* Prints user activation link
*
* @param Array $params
* @return string
*/
function ActivationLink($params)
{
$object =& $this->getObject($params);
/* @var $object kDBItem */
$code = $this->getCachedCode();
$object->SetDBField('PwResetConfirm', $code);
$object->SetDBField('PwRequestTime_date', adodb_mktime());
$object->SetDBField('PwRequestTime_time', adodb_mktime());
$object->Update();
$params['user_key'] = $code;
return $this->Application->ProcessParsedTag('m', 'Link', $params);
}
/**
* Activates user using given code
*
* @param Array $params
*/
function ActivateUser($params)
{
$passed_key = trim($this->Application->GetVar('user_key'));
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user =& $user_helper->getUserObject();
$user->Load($passed_key, 'PwResetConfirm');
if ( !$user->isLoaded() ) {
return ;
}
$user->SetDBField('Status', STATUS_ACTIVE);
$user->SetDBField('PwResetConfirm', '');
$user->SetDBField('PwRequestTime_date', NULL);
$user->SetDBField('PwRequestTime_time', NULL);
$user->Update();
if ( $user_helper->checkLoginPermission() ) {
$user_helper->loginUserById( $user->GetID() );
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/users/users_event_handler.php
===================================================================
--- branches/5.2.x/core/units/users/users_event_handler.php (revision 14595)
+++ branches/5.2.x/core/units/users/users_event_handler.php (revision 14596)
@@ -1,1724 +1,1692 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 UsersEventHandler extends kDBEventHandler
{
/**
- * Allows to override standart permission mapping
+ * Allows to override standard permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
// admin
'OnSetPersistantVariable' => Array('self' => 'view'), // because setting to logged in user only
'OnUpdateRootPassword' => Array('self' => true),
'OnUpdatePassword' => Array('self' => true),
'OnSaveSelected' => Array ('self' => 'view'),
'OnGeneratePassword' => Array ('self' => 'view'),
// front
'OnRefreshForm' => Array('self' => true),
'OnForgotPassword' => Array('self' => true),
'OnSubscribeQuery' => Array('self' => true),
'OnSubscribeUser' => Array('self' => true),
'OnRecommend' => Array('self' => true),
'OnItemBuild' => Array('self' => true),
'OnMassResetSettings' => Array('self' => 'edit'),
'OnMassCloneUsers' => Array('self' => 'add'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Builds item (loads if needed)
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
function OnItemBuild(&$event)
{
parent::OnItemBuild($event);
- if ($event->Special == 'forgot') {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ if ( $event->Special == 'forgot' || $object->getFormName() == 'registration' ) {
$this->_makePasswordRequired($event);
}
}
/**
* Shows only admins when required
*
* @param kEvent $event
+ * @return void
+ * @access protected
+ * @see kDBEventHandler::OnListBuild()
*/
- function SetCustomQuery(&$event)
+ protected function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if ($event->Special == 'regular') {
$object->addFilter('primary_filter', '%1$s.UserType = ' . UserType::USER);
}
if ($event->Special == 'admins') {
$object->addFilter('primary_filter', '%1$s.UserType = ' . UserType::ADMIN);
}
if (!$this->Application->isAdminUser) {
$object->addFilter('status_filter', '%1$s.Status = '.STATUS_ACTIVE);
}
if ($event->Special == 'online') {
$object->addFilter('online_users_filter', 's.PortalUserId IS NOT NULL');
}
if ($event->Special == 'group') {
$group_id = $this->Application->GetVar('g_id');
if ($group_id !== false) {
// show only users, that user doesn't belong to current group
$sql = 'SELECT PortalUserId
FROM ' . $this->Application->GetTempName(TABLE_PREFIX.'UserGroup', 'prefix:g') . '
WHERE GroupId = ' . (int)$group_id;
$user_ids = $this->Conn->GetCol($sql);
if ($user_ids) {
$object->addFilter('already_member_filter', '%1$s.PortalUserId NOT IN (' . implode(',', $user_ids) . ')');
}
}
}
}
/**
- * Checks permissions of user
+ * Checks user permission to execute given $event
*
* @param kEvent $event
+ * @return bool
+ * @access public
*/
- function CheckPermission(&$event)
+ public function CheckPermission(&$event)
{
- if ($event->Name == 'OnLogin' || $event->Name == 'OnLogout') {
+ if ( $event->Name == 'OnLogin' || $event->Name == 'OnLogout' ) {
// permission is checked in OnLogin event directly
return true;
}
- if (!$this->Application->isAdminUser) {
+ if ( !$this->Application->isAdminUser ) {
$user_id = $this->Application->RecallVar('user_id');
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- if ($event->Name == 'OnCreate' && $user_id == USER_GUEST) {
+ if ( $event->Name == 'OnCreate' && $user_id == USER_GUEST ) {
// "Guest" can create new users
return true;
}
- if ($event->Name == 'OnUpdate' && $user_id > 0) {
- $user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
+ if ( $event->Name == 'OnUpdate' && $user_id > 0 ) {
+ $user_dummy =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
+ /* @var $user_dummy UsersItem */
foreach ($items_info as $id => $field_values) {
- if ($id != $user_id) {
+ if ( $id != $user_id ) {
// registered users can update their record only
return false;
}
$user_dummy->Load($id);
$status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
- if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
+ if ( $user_dummy->GetDBField($status_field) != STATUS_ACTIVE ) {
// not active user is not allowed to update his record (he could not activate himself manually)
return false;
}
- if (isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field]) {
+ if ( isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field] ) {
// user can't change status by himself
return false;
}
}
return true;
}
if ( $event->Name == 'OnResetLostPassword' && $event->Special == 'forgot' && $user_id == USER_GUEST ) {
// non-logged in users can reset their password, when reset code is valid
- return is_numeric( $this->getPassedID($event) );
+ return is_numeric($this->getPassedID($event));
}
- if ($event->Name == 'OnUpdate' && $user_id <= 0) {
+ if ( $event->Name == 'OnUpdate' && $user_id <= 0 ) {
// guests are not allowed to update their record, because they don't have it :)
return false;
}
}
return parent::CheckPermission($event);
}
/**
* Handles session expiration (redirects to valid template)
*
* @param kEvent $event
*/
function OnSessionExpire(&$event)
{
$this->Application->resetCounters('UserSession');
// place 2 of 2 (also in kHTTPQuery::getRedirectParams)
$admin_url_params = Array (
'm_cat_id' => 0, // category means nothing on admin login screen
'm_wid' => '', // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for <a> targets)
'pass' => 'm', // don't pass any other (except "m") prefixes to admin session expiration template
'expired' => 1, // expiration mark to show special error on login screen
'no_pass_through' => 1, // this way kApplication::HREF won't add them again
);
if ($this->Application->isAdmin) {
$this->Application->Redirect('index', $admin_url_params, '', 'index.php');
}
if ($this->Application->GetVar('admin') == 1) {
// Front-End showed in admin's right frame
$session_admin =& $this->Application->recallObject('Session.admin');
/* @var $session_admin Session */
if (!$session_admin->LoggedIn()) {
// front-end session created from admin session & both expired
$this->Application->DeleteVar('admin');
$this->Application->Redirect('index', $admin_url_params, '', 'admin/index.php');
}
}
// Front-End session expiration
$get = $this->Application->HttpQuery->getRedirectParams();
$t = $this->Application->GetVar('t');
$get['js_redirect'] = $this->Application->ConfigValue('UseJSRedirect');
$this->Application->Redirect($t ? $t : 'index', $get);
}
/**
* [AGENT] Deletes expired sessions
*
* @param kEvent $event
*/
function OnDeleteExpiredSessions(&$event)
{
if (defined('IS_INSTALL') && IS_INSTALL) {
return ;
}
$this->Application->Session->DeleteExpired();
}
/**
* Checks user data and logs it in if allowed
*
* @param kEvent $event
*/
function OnLogin(&$event)
{
- $object =& $event->getObject();
+ $object =& $event->getObject( Array ('form_name' => 'login') );
/* @var $object kDBItem */
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
$username = $object->GetDBField('UserLogin');
$password = $object->GetDBField('UserPassword');
$rember_login = $object->GetDBField('UserRememberLogin') == 1;
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user_helper->event =& $event;
$result = $user_helper->loginUser($username, $password, false, $rember_login);
if ($result != LoginResult::OK) {
$event->status = kEvent::erFAIL;
$object->SetError('UserLogin', $result == LoginResult::NO_PERMISSION ? 'no_permission' : 'invalid_password');
}
}
/**
* [HOOK] Auto-Logins Front-End user when "Remember Login" cookie is found
*
* @param kEvent $event
*/
function OnAutoLoginUser(&$event)
{
$remember_login_cookie = $this->Application->GetVar('remember_login');
if (!$remember_login_cookie || $this->Application->isAdmin || $this->Application->LoggedIn()) {
return ;
}
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user_helper->loginUser('', '', false, false, $remember_login_cookie);
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogin(&$event)
{
$sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize'));
+ /* @var $sync_manager UsersSyncronizeManager */
+
$sync_manager->performAction('LoginUser', $event->getEventParam('user'), $event->getEventParam('pass') );
if ($event->redirect && is_string($event->redirect)) {
// some real template specified instead of true
$this->Application->Redirect($event->redirect, $event->getRedirectParams());
}
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogout(&$event)
{
$sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize'));
+ /* @var $sync_manager UsersSyncronizeManager */
+
$sync_manager->performAction('LogoutUser');
}
function OnLogout(&$event)
{
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user_helper->event =& $event;
$user_helper->logoutUser();
}
/**
- * Redirects user after succesfull registration to confirmation template (on Front only)
+ * Redirects user after successful registration to confirmation template (on Front only)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(&$event)
{
parent::OnAfterItemCreate($event);
$this->afterItemChanged($event);
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- $primary_group_id = $object->GetDBField('PrimaryGroupId');
-
- if ($primary_group_id) {
- $ug_table = TABLE_PREFIX . 'UserGroup';
-
- if ( $object->IsTempTable() ) {
- $ug_table = $this->Application->GetTempName($ug_table, 'prefix:' . $event->Prefix);
- }
-
- $fields_hash = Array (
- 'PortalUserId' => $object->GetID(),
- 'GroupId' => $primary_group_id,
- );
-
- $this->Conn->doInsert($fields_hash, $ug_table, 'REPLACE');
- }
+ $this->assignToPrimaryGroup($event);
}
/**
- * Login user if possible, if not then redirect to corresponding template
+ * Performs user registration
*
* @param kEvent $event
*/
- function autoLoginUser(&$event)
+ function OnCreate(&$event)
{
- $object =& $event->getObject();
- $this->Application->SetVar('u.current_id', $object->GetID());
-
- if ( $object->GetDBField('Status') == STATUS_ACTIVE ) {
- $user_helper =& $this->Application->recallObject('UserHelper');
- /* @var $user_helper UserHelper */
+ if ( $this->Application->isAdmin ) {
+ parent::OnCreate($event);
- if ( $user_helper->checkLoginPermission() ) {
- $user_helper->loginUserById( $object->GetID() );
- }
+ return ;
}
- }
-
-
- /**
- * When creating user & user with such email exists then force to use OnUpdate insted of ?
- *
- * @param kEvent $event
- */
- function OnSubstituteSubscriber(&$event)
- {
- $ret = false;
- $object =& $event->getObject( Array('skip_autoload' => true) );
-
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
-
- if ($items_info) {
- list($id, $field_values) = each($items_info);
- $user_email = isset($field_values['Email']) ? $field_values['Email'] : false;
- if ($user_email) {
- // check if is subscriber
- $verify_user =& $this->Application->recallObject('u.verify', null, Array('skip_autoload' => true) );
- $verify_user->Load($user_email, 'Email');
+ $object =& $event->getObject( Array('form_name' => 'registration') );
+ /* @var $object UsersItem */
- if ( $verify_user->isLoaded() && $verify_user->isSubscriberOnly() ) {
- $items_info = Array( $verify_user->GetDBField('PortalUserId') => $field_values );
- $this->Application->SetVar($event->getPrefixSpecial(true), $items_info);
- $ret = true;
- }
- }
- }
+ $field_values = $this->getSubmittedFields($event);
+ $user_email = getArrayValue($field_values, 'Email');
+ $subscriber_id = $user_email ? $this->getSubscriberByEmail($user_email) : false;
- if ( isset($event->MasterEvent) ) {
- $event->MasterEvent->setEventParam('is_subscriber_only', $ret);
+ if ( $subscriber_id ) {
+ // update existing subscriber
+ $object->Load($subscriber_id);
+ $object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_NewGroup'));
+ $this->Application->SetVar($event->getPrefixSpecial(true), Array ($object->GetID() => $field_values));
}
- else {
- $event->setEventParam('is_subscriber_only', $ret);
- }
- }
+ $object->SetFieldsFromHash($field_values);
- /**
- * Enter description here...
- *
- * @param kEvent $event
- * @param bool $dry_run
- * @return bool
- */
- function isSubscriberOnly(&$event, $dry_run = false)
- {
- $event->CallSubEvent('OnSubstituteSubscriber');
- $is_subscriber = $event->getEventParam('is_subscriber_only');
+ $status = $object->isLoaded() ? $object->Update() : $object->Create();
- if ($dry_run) {
- return $is_subscriber;
+ if ( !$status ) {
+ $event->status = kEvent::erFAIL;
+ $event->redirect = false;
+ $object->setID( (int)$object->GetID() );
}
- if ($is_subscriber) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
- $this->OnUpdate($event);
+ $this->setNextTemplate($event, true);
- if ($event->status == kEvent::erSUCCESS) {
- $this->OnAfterItemCreate($event);
- $object->SendEmailEvents();
+ if ( ($event->status == kEvent::erSUCCESS) && $event->redirect ) {
+ $this->assignToPrimaryGroup($event);
- if (!$this->Application->isAdmin && $event->redirect) {
- $this->autoLoginUser($event);
- }
- }
+ $object->SendEmailEvents();
+ $this->autoLoginUser($event);
}
-
- return $is_subscriber;
}
/**
- * Creates new user
+ * Returns subscribed user ID by given e-mail address
*
- * @param kEvent $event
+ * @param string $email
*/
- function OnCreate(&$event)
+ function getSubscriberByEmail($email)
{
- if (!$this->Application->isAdminUser) {
- $this->setUserStatus($event);
- }
-
- if ( !$this->isSubscriberOnly($event) ) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
- /* @var $object UsersItem */
-
- if ( $this->Application->ConfigValue('User_Password_Auto') ) {
- $password = $object->generatePassword( rand(5, 8) );
- $this->Application->SetVar('user_password', $password);
- }
-
- parent::OnCreate($event);
+ $verify_user =& $this->Application->recallObject('u.verify', null, Array ('skip_autoload' => true));
+ /* @var $verify_user UsersItem */
- $this->Application->SetVar('u.current_id', $object->getID()); // for affil:OnRegisterAffiliate after hook
-
- $this->setNextTemplate($event);
+ $verify_user->Load($email, 'Email');
- if (!$this->Application->isAdmin && ($event->status == kEvent::erSUCCESS) && $event->redirect) {
- $object->SendEmailEvents();
- $this->autoLoginUser($event);
- }
- }
+ return $verify_user->isLoaded() && $verify_user->isSubscriberOnly() ? $verify_user->GetID() : false;
}
/**
- * Set's new user status based on config options
+ * Login user if possible, if not then redirect to corresponding template
*
* @param kEvent $event
*/
- function setUserStatus(&$event)
+ function autoLoginUser(&$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
-
- $new_users_allowed = $this->Application->ConfigValue('User_Allow_New');
-
- switch ($new_users_allowed) {
- case 1: // Immediate
- $object->SetDBField('Status', STATUS_ACTIVE);
- $next_template = $this->Application->GetVar('registration_confirm_template');
- if ($next_template) {
- $event->redirect = $next_template;
- }
- break;
+ $object =& $event->getObject();
+ $this->Application->SetVar('u.current_id', $object->GetID());
- case 3: // Upon Approval
- case 4: // Email Activation
- $next_template = $this->Application->GetVar('registration_confirm_pending_template');
- if ($next_template) {
- $event->redirect = $next_template;
- }
- $object->SetDBField('Status', STATUS_PENDING);
- break;
+ if ( $object->GetDBField('Status') == STATUS_ACTIVE ) {
+ $user_helper =& $this->Application->recallObject('UserHelper');
+ /* @var $user_helper UserHelper */
- case 2: // Not Allowed
- $object->SetDBField('Status', STATUS_DISABLED);
- break;
+ if ( $user_helper->checkLoginPermission() ) {
+ $user_helper->loginUserById( $object->GetID() );
+ }
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
parent::OnBeforeItemCreate($event);
+ $this->beforeItemChanged($event);
+
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
- if ( !$this->isSubscriberOnly($event, true) ) {
+ $object =& $event->getObject();
+ /* @var $object UsersItem */
+
+ if ( !$object->isSubscriberOnly() ) {
+ // don't checck state-to-country relations for subscribers
$cs_helper->CheckStateField($event, 'State', 'Country');
}
$this->_makePasswordRequired($event);
$cs_helper->PopulateStates($event, 'State', 'Country');
- $object =& $event->getObject();
- /* @var $object UsersItem */
-
if ( $this->Application->ConfigValue('Email_As_Login') ) {
- $field_options = $object->GetFieldOptions('Email');
- $field_options['error_msgs']['unique'] = $this->Application->Phrase('lu_user_and_email_already_exist');
- $object->SetFieldOptions('Email', $field_options);
+ $error_msgs = $object->GetFieldOption('Email', 'error_msgs');
+ $error_msgs['unique'] = '!lu_user_and_email_already_exist!';
+ $object->SetFieldOption('Email', 'error_msgs', $error_msgs);
}
$this->setUserGroup($object);
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
- if (!$user_helper->checkBanRules($object)) {
+ if ( !$user_helper->checkBanRules($object) ) {
$object->SetError('Login', 'banned');
}
}
/**
* Sets primary group of the user
*
* @param kDBItem $object
*/
protected function setUserGroup(&$object)
{
if ($object->Special == 'subscriber') {
$object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_SubscriberGroup'));
return ;
}
// set primary group to user
if ( !$this->Application->isAdminUser ) {
$group_id = $object->GetDBField('PrimaryGroupId');
if ($group_id) {
// check, that group is allowed for Front-End
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'PortalGroup
WHERE GroupId = ' . (int)$group_id . ' AND FrontRegistration = 1';
$group_id = $this->Conn->GetOne($sql);
}
if (!$group_id) {
// when group not selected OR not allowed -> use default group
$object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_NewGroup'));
}
}
}
/**
+ * Assigns a user to it's primary group
+ *
+ * @param kEvent $event
+ */
+ protected function assignToPrimaryGroup(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $primary_group_id = $object->GetDBField('PrimaryGroupId');
+
+ if ($primary_group_id) {
+ $ug_table = TABLE_PREFIX . 'UserGroup';
+
+ if ( $object->IsTempTable() ) {
+ $ug_table = $this->Application->GetTempName($ug_table, 'prefix:' . $event->Prefix);
+ }
+
+ $fields_hash = Array (
+ 'PortalUserId' => $object->GetID(),
+ 'GroupId' => $primary_group_id,
+ );
+
+ $this->Conn->doInsert($fields_hash, $ug_table, 'REPLACE');
+ }
+ }
+
+ /**
* Set's new unique resource id to user
*
* @param kEvent $event
*/
function OnAfterItemValidate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$resource_id = $object->GetDBField('ResourceId');
if (!$resource_id) {
$object->SetDBField('ResourceId', $this->Application->NextResourceId());
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnRecommend(&$event)
{
- $object =& $event->getObject();
+ $object =& $event->getObject( Array ('form_name' => 'recommend') );
/* @var $object kDBItem */
- $object->setRequired('RecommendEmail');
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
if ( !$object->ValidateField('RecommendEmail') ) {
$event->status = kEvent::erFAIL;
return ;
}
$send_params = Array (
'to_email' => $object->GetDBField('RecommendEmail'),
'to_name' => $object->GetDBField('RecommendEmail'),
);
$user_id = $this->Application->RecallVar('user_id');
$email_event =& $this->Application->EmailEventUser('USER.SUGGEST', $user_id, $send_params);
$email_event =& $this->Application->EmailEventAdmin('USER.SUGGEST');
if ( $email_event->status == kEvent::erSUCCESS ) {
$event->SetRedirectParam('pass', 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
else {
$event->status = kEvent::erFAIL;
$object->SetError('RecommendEmail', 'send_error');
}
}
/**
* Saves address changes and mades no redirect
*
* @param kEvent $event
*/
function OnUpdateAddress(&$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- if ($items_info) {
+ if ( $items_info ) {
list ($id, $field_values) = each($items_info);
- if ($id > 0) {
+
+ if ( $id > 0 ) {
$object->Load($id);
}
$object->SetFieldsFromHash($field_values);
$object->setID($id);
$object->Validate();
}
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$cs_helper->PopulateStates($event, 'State', 'Country');
$event->redirect = false;
}
/**
* Validate subscriber's email & store it to session -> redirect to confirmation template
*
* @param kEvent $event
*/
function OnSubscribeQuery(&$event)
{
- $user_email = $this->Application->GetVar('subscriber_email');
+ $object =& $event->getObject( Array ('form_name' => 'subscription') );
+ /* @var $object UsersItem */
- if ( preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email) ) {
- $object =& $this->Application->recallObject($this->Prefix . '.subscriber', null, Array('skip_autoload' => true));
- /* @var $object UsersItem */
+ $object->SetFieldsFromHash( $this->getSubmittedFields($event) );
- $object->Load($user_email, 'Email');
- $event->SetRedirectParam('subscriber_email', $user_email);
+ if ( !$object->ValidateField('SubscriberEmail') ) {
+ $event->status = kEvent::erFAIL;
- if ( $object->isLoaded() ) {
- if ( $this->isSubscribed($object) ) {
- $event->redirect = $this->Application->GetVar('unsubscribe_template');
- }
- else {
- $event->redirect = $this->Application->GetVar('subscribe_template');
- }
- }
- else {
- $event->redirect = $this->Application->GetVar('subscribe_template');
- }
+ return ;
}
- else {
- // used for error reporting only -> rewrite code + theme (by Alex)
- $object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
- /* @var $object UsersItem */
- $object->SetError('SubscribeEmail', 'invalid_email', 'lu_InvalidEmail');
- $event->status = kEvent::erFAIL;
+ $user_email = $object->GetDBField('SubscriberEmail');
+ $object->Load($user_email, 'Email');
+ $event->SetRedirectParam('subscriber_email', $user_email);
+
+ if ( $object->isLoaded() && $object->isSubscribed() ) {
+ $event->redirect = $this->Application->GetVar('unsubscribe_template');
+ }
+ else {
+ $event->redirect = $this->Application->GetVar('subscribe_template');
}
+
+ $event->SetRedirectParam('pass', 'm');
}
/**
* Subscribe/Unsubscribe user based on email stored in previous step
*
* @param kEvent $event
*/
function OnSubscribeUser(&$event)
{
- $object = &$this->Application->recallObject($this->Prefix . '.subscriber', null, Array('skip_autoload' => true));
+ $object =& $event->getObject( Array ('form_name' => 'subscription') );
/* @var $object UsersItem */
$user_email = $this->Application->GetVar('subscriber_email');
+ $object->SetDBField('SubscriberEmail', $user_email);
- if ( preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email) ) {
- $this->RemoveRequiredFields($object);
- $object->Load($user_email, 'Email');
+ if ( !$object->ValidateField('SubscriberEmail') ) {
+ $event->status = kEvent::erFAIL;
- if ( $object->isLoaded() ) {
- if ( $this->isSubscribed($object) ) {
- if ( $event->getEventParam('no_unsubscribe') ) {
- // for customization code from FormsEventHandler
- return ;
- }
+ return ;
+ }
- if ( $object->isSubscriberOnly() ) {
- $this->Application->SetVar($object->getPrefixSpecial(true) . '_id', $object->GetID());
- $delete_event = new kEvent($object->getPrefixSpecial() . ':OnDelete');
- $this->Application->HandleEvent($delete_event);
- }
- else {
- $this->RemoveSubscriberGroup( $object->GetID() );
- }
+ $this->RemoveRequiredFields($object);
+ $object->Load($user_email, 'Email');
- $event->redirect = $this->Application->GetVar('unsubscribe_ok_template');
+ if ( $object->isLoaded() ) {
+ if ( $object->isSubscribed() ) {
+ if ( $event->getEventParam('no_unsubscribe') ) {
+ // for customization code from FormsEventHandler
+ return ;
+ }
+
+ if ( $object->isSubscriberOnly() ) {
+ $temp_handler =& $this->Application->recallObject($event->Prefix . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($event->Prefix, '', Array($object->GetID()));
}
else {
- $this->AddSubscriberGroup($object);
- $event->redirect = $this->Application->GetVar('subscribe_ok_template');
+ $this->RemoveSubscriberGroup( $object->GetID() );
}
+
+ $event->redirect = $this->Application->GetVar('unsubscribe_ok_template');
}
else {
- $object->generatePassword();
+ $this->AddSubscriberGroup($object);
+ $event->redirect = $this->Application->GetVar('subscribe_ok_template');
+ }
+ }
+ else {
+ $object->generatePassword();
+ $object->SetDBField('Email', $user_email);
- $object->SetDBField('Email', $user_email);
+ if ( $object->isRequired('Login') ) {
$object->SetDBField('Login', $user_email);
- $object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default
- $object->SetDBField('ip', $_SERVER['REMOTE_ADDR']);
+ }
- if ( $object->Create() ) {
- $this->AddSubscriberGroup($object);
- $event->redirect = $this->Application->GetVar('subscribe_ok_template');
- }
+ $object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default
+ $object->SetDBField('ip', $_SERVER['REMOTE_ADDR']);
+
+ if ( $object->Create() ) {
+ $this->AddSubscriberGroup($object);
+ $event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
}
}
/**
* Adding user to subscribers group
*
* @param UsersItem $object
*/
function AddSubscriberGroup(&$object)
{
if ( !$object->isSubscriberOnly() ) {
$fields_hash = Array (
'PortalUserId' => $object->GetID(),
'GroupId' => $this->Application->ConfigValue('User_SubscriberGroup'),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'UserGroup');
}
$this->Application->EmailEventAdmin('USER.SUBSCRIBE');
$this->Application->EmailEventUser('USER.SUBSCRIBE', $object->GetID());
}
/**
* Removing user from subscribers group
*
* @param int $user_id
*/
function RemoveSubscriberGroup($user_id)
{
$group_id = $this->Application->ConfigValue('User_SubscriberGroup');
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PortalUserId = ' . $user_id . ' AND GroupId = ' . $group_id;
$this->Conn->Query($sql);
$this->Application->EmailEventAdmin('USER.UNSUBSCRIBE');
$this->Application->EmailEventUser('USER.UNSUBSCRIBE', $user_id);
}
/**
- * Checks user subscription status
- *
- * @param kDBItem $object
- * @return bool
- */
- function isSubscribed(&$object)
- {
- $group_id = $this->Application->ConfigValue('User_SubscriberGroup');
-
- $sql = 'SELECT GroupId
- FROM ' . TABLE_PREFIX . 'UserGroup
- WHERE (PortalUserId = ' . $object->GetID() . ') AND (GroupId = ' . $group_id . ')';
-
- return $this->Conn->GetOne($sql);
- }
-
- /**
- * Checks, that user can reset his password
- *
+ * Validates forgot password form and sends password reset confirmation e-mail
+ *
* @param kEvent $event
+ * @return void
*/
function OnForgotPassword(&$event)
{
- $object =& $event->getObject();
+ $object =& $event->getObject( Array ('form_name' => 'forgot_password') );
/* @var $object kDBItem */
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
$user_object =& $this->Application->recallObject('u.tmp', null, Array('skip_autoload' => true));
/* @var $user_object UsersItem */
$found = $allow_reset = false;
$username = $object->GetDBField('ForgotLogin');
$email = $object->GetDBField('ForgotEmail');
if ( strlen($username) ) {
$user_object->Load($username, 'Login');
}
elseif ( strlen($email) ) {
$user_object->Load($email, 'Email');
}
if ( $user_object->isLoaded() ) {
$min_pwd_reset_delay = $this->Application->ConfigValue('Users_AllowReset');
$found = ($user_object->GetDBField('Status') == STATUS_ACTIVE) && strlen( $user_object->GetDBField('Password') );
if ( !$user_object->GetDBField('PwResetConfirm') ) {
// no reset made -> allow
$allow_reset = true;
}
else {
// reset made -> wait N minutes, then allow
$allow_reset = adodb_mktime() > $user_object->GetDBField('PwRequestTime') + $min_pwd_reset_delay;
}
}
if ($found && $allow_reset) {
$this->Application->EmailEventUser('USER.PSWDC', $user_object->GetID());
$event->redirect = $this->Application->GetVar('template_success');
return ;
}
if ( !strlen($username) && !strlen($email) ) {
$object->SetError('ForgotLogin', 'required');
$object->SetError('ForgotEmail', 'required');
}
else {
if ( strlen($username) ) {
$object->SetError('ForgotLogin', $found ? 'reset_denied' : 'unknown_username');
}
if ( strlen($email) ) {
$object->SetError('ForgotEmail', $found ? 'reset_denied' : 'unknown_email');
}
}
if ( !$object->ValidateField('ForgotLogin') || !$object->ValidateField('ForgotEmail') ) {
$event->status = kEvent::erFAIL;
}
}
function OnUpdate(&$event)
{
parent::OnUpdate($event);
- $this->setNextTemplate($event);
+ if ( !$this->Application->isAdmin ) {
+ $this->setNextTemplate($event);
+ }
}
/**
* Checks state against country
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(&$event)
{
parent::OnBeforeItemUpdate($event);
+ $this->beforeItemChanged($event);
+
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$cs_helper->CheckStateField($event, 'State', 'Country');
$cs_helper->PopulateStates($event, 'State', 'Country');
- if ($event->Special == 'forgot') {
- $object =& $event->getObject();
- /* @var $object kDBItem */
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+ if ($event->Special == 'forgot') {
$object->SetDBField('PwResetConfirm', '');
$object->SetDBField('PwRequestTime_date', NULL);
$object->SetDBField('PwRequestTime_time', NULL);
}
$changed_fields = array_keys( $object->GetChangedFields() );
if ( $changed_fields && !in_array('Modified', $changed_fields) ) {
$object->SetDBField('Modified_date', adodb_mktime());
$object->SetDBField('Modified_time', adodb_mktime());
}
}
/**
- * Enter description here...
+ * Occurs before item is changed
*
* @param kEvent $event
*/
- function setNextTemplate(&$event)
+ function beforeItemChanged(&$event)
{
- if ($this->Application->isAdmin) {
- return ;
+ $object =& $event->getObject();
+ /* @var $object UsersItem */
+
+ if ( !$this->Application->isAdmin && $object->getFormName() == 'registration' ) {
+ // sets new user's status based on config options
+ $status_map = Array (1 => STATUS_ACTIVE, 2 => STATUS_DISABLED, 3 => STATUS_PENDING, 4 => STATUS_PENDING);
+ $object->SetDBField('Status', $status_map[ $this->Application->ConfigValue('User_Allow_New') ]);
+
+ if ( $this->Application->ConfigValue('User_Password_Auto') ) {
+ $object->generatePassword( rand(5, 8) );
+ }
+
+ if ( $this->Application->ConfigValue('RegistrationCaptcha') ) {
+ $captcha_helper =& $this->Application->recallObject('CaptchaHelper');
+ /* @var $captcha_helper kCaptchaHelper */
+
+ $captcha_helper->validateCode($event, false);
+ }
+
+ if ( $event->Name == 'OnBeforeItemUpdate' ) {
+ // when a subscriber-only users performs normal registration, then assign him to Member group
+ $this->setUserGroup($object);
+ }
}
+ }
+ /**
+ * Sets redirect template based on user status & user request contents
+ *
+ * @param kEvent $event
+ * @param bool $for_registration
+ */
+ function setNextTemplate(&$event, $for_registration = false)
+ {
$event->SetRedirectParam('opener', 's');
+
$object =& $event->getObject();
+ /* @var $object UsersItem */
+
+ $next_template = false;
- if ($object->GetDBField('Status') == STATUS_ACTIVE) {
+ if ( $object->GetDBField('Status') == STATUS_ACTIVE && $this->Application->GetVar('next_template') ) {
$next_template = $this->Application->GetVar('next_template');
+ }
+ elseif ( $for_registration ) {
+ switch ( $this->Application->ConfigValue('User_Allow_New') ) {
+ case 1: // Immediate
+ $next_template = $this->Application->GetVar('registration_confirm_template');
+ break;
- if ($next_template) {
- $event->redirect = $next_template;
+ case 3: // Upon Approval
+ case 4: // Email Activation
+ $next_template = $this->Application->GetVar('registration_confirm_pending_template');
+ break;
}
}
+
+ if ($next_template) {
+ $event->redirect = $next_template;
+ }
}
/**
* Delete users from groups if their membership is expired
*
* @param kEvent $event
*/
function OnCheckExpiredMembership(&$event)
{
// send pre-expiration reminders: begin
$pre_expiration = adodb_mktime() + $this->Application->ConfigValue('User_MembershipExpirationReminder') * 3600 * 24;
$sql = 'SELECT PortalUserId, GroupId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (ExpirationReminderSent = 0) AND (MembershipExpires < '.$pre_expiration.')';
$skip_clause = $event->getEventParam('skip_clause');
if ($skip_clause) {
$sql .= ' AND !('.implode(') AND !(', $skip_clause).')';
}
$records = $this->Conn->Query($sql);
if ($records) {
$conditions = Array();
foreach ($records as $record) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRATION.NOTICE', $record['PortalUserId']);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRATION.NOTICE');
$conditions[] = '(PortalUserId = '.$record['PortalUserId'].' AND GroupId = '.$record['GroupId'].')';
}
$sql = 'UPDATE '.TABLE_PREFIX.'UserGroup
SET ExpirationReminderSent = 1
WHERE '.implode(' OR ', $conditions);
$this->Conn->Query($sql);
}
// send pre-expiration reminders: end
// remove users from groups with expired membership: begin
$sql = 'SELECT PortalUserId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$user_ids = $this->Conn->GetCol($sql);
if ($user_ids) {
foreach ($user_ids as $id) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRED', $id);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRED');
}
}
$sql = 'DELETE FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$this->Conn->Query($sql);
// remove users from groups with expired membership: end
}
/**
- * Enter description here...
+ * Used to keep user registration form data, while showing affiliate registration form fields
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnRefreshForm(&$event)
+ protected function OnRefreshForm(&$event)
{
$event->redirect = false;
- $item_info = $this->Application->GetVar($event->getPrefixSpecial());
+ $item_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list($id, $fields) = each($item_info);
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
$object->setID($id);
$object->IgnoreValidation = true;
$object->SetFieldsFromHash($fields);
}
/**
* Sets persistant variable
*
* @param kEvent $event
*/
function OnSetPersistantVariable(&$event)
{
$field = $this->Application->GetVar('field');
$value = $this->Application->GetVar('value');
$this->Application->StorePersistentVar($field, $value);
$force_tab = $this->Application->GetVar('SetTab');
if ($force_tab) {
$this->Application->StoreVar('force_tab', $force_tab);
}
}
/**
* Overwritten to return user from order by special .ord
*
* @param kEvent $event
*/
function getPassedID(&$event)
{
switch ($event->Special) {
case 'ord':
$order =& $this->Application->recallObject('ord');
/* @var $order OrdersItem */
return $order->GetDBField('PortalUserId');
break;
case 'profile':
$id = $this->Application->GetVar('user_id');
if (!$id) {
// if none user_id given use current user id
$id = $this->Application->RecallVar('user_id');
}
return $id;
break;
case 'forgot':
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$id = $user_helper->validateUserCode( $this->Application->GetVar('user_key'), 'forgot_password' );
if ( is_numeric($id) ) {
return $id;
}
break;
}
if ( preg_match('/^(login|register|recommend|subscribe|forgot)/', $event->Special) ) {
// this way we can have 2+ objects stating with same special, e.g. "u.login-sidebox" and "u.login-main"
return USER_GUEST;
}
return parent::getPassedID($event);
}
/**
* Allows to change root password
*
* @param kEvent $event
*/
function OnUpdateRootPassword(&$event)
{
return $this->OnUpdatePassword($event);
}
/**
* Allows to change root password
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnUpdatePassword(&$event)
+ protected function OnUpdatePassword(&$event)
{
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if (!$items_info) return ;
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+ if ( !$items_info ) {
+ return;
+ }
+
list ($id, $field_values) = each($items_info);
$user_id = $this->Application->RecallVar('user_id');
- if ($id == $user_id && ($user_id > 0 || $user_id == USER_ROOT)) {
- $user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
+
+ if ( $id == $user_id && ($user_id > 0 || $user_id == USER_ROOT) ) {
+ $user_dummy =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
/* @var $user_dummy kDBItem */
$user_dummy->Load($id);
- $status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
+ $status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
- if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
+ if ( $user_dummy->GetDBField($status_field) != STATUS_ACTIVE ) {
// not active user is not allowed to update his record (he could not activate himself manually)
- return false;
+ return ;
}
}
- if ($user_id == USER_ROOT) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ if ( $user_id == USER_ROOT ) {
+ $object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object UsersItem */
// put salt to user's config
$field_options = $object->GetFieldOptions('RootPassword');
$field_options['salt'] = 'b38';
// this is internal hack to allow root/root passwords for dev
- if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') {
+ if ( $this->Application->isDebugMode() && $field_values['RootPassword'] == 'root' ) {
$field_options['min_length'] = 4;
}
$object->SetFieldOptions('RootPassword', $field_options);
$verify_options = $object->GetFieldOptions('VerifyRootPassword');
$verify_options['salt'] = 'b38';
$object->SetFieldOptions('VerifyRootPassword', $verify_options);
$this->RemoveRequiredFields($object);
$object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass'));
- $object->SetFieldsFromHash($field_values);
- $object->setID(-1);
- $status = $object->Validate();
- if ($status) {
+ $object->SetFieldsFromHash($field_values);
+ $object->setID(-1);
+
+ if ( $object->Validate() ) {
// validation on, password match too
- $fields_hash = Array (
- 'VariableValue' => $object->GetDBField('RootPassword')
- );
+ $fields_hash = Array ('VariableValue' => $object->GetDBField('RootPassword'));
$conf_table = $this->Application->getUnitOption('conf', 'TableName');
$this->Conn->doUpdate($fields_hash, $conf_table, 'VariableName = "RootPass"');
$event->SetRedirectParam('opener', 'u');
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
- return;
+ return ;
}
}
else {
$object =& $event->getObject();
$object->SetFieldsFromHash($field_values);
- if (!$object->Update()) {
+ if ( !$object->Update() ) {
$event->status = kEvent::erFAIL;
$event->redirect = false;
}
}
$event->SetRedirectParam('opener', 'u');
- $event->redirect == true;
- }
-
- /**
- * Apply custom processing to item
- *
- * @param kEvent $event
- */
- function customProcessing(&$event, $type)
- {
- if ($event->Name == 'OnCreate' && $type == 'before') {
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- // if auto password has not been set already - store real one - to be used in email events
- if (!$this->Application->GetVar('user_password')) {
- $this->Application->SetVar('user_password', $object->GetDirtyField('Password'));
- $object->SetDBField('Password_plain', $object->GetDirtyField('Password'));
- }
-
- // validate here, because subscribing procedure should not validate captcha code
- if ($this->Application->ConfigValue('RegistrationCaptcha')) {
- $captcha_helper =& $this->Application->recallObject('CaptchaHelper');
- /* @var $captcha_helper kCaptchaHelper */
-
- $captcha_helper->validateCode($event, false);
- }
- }
}
function OnMassResetSettings(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
$default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
if (in_array($default_user_id, $ids)) {
array_splice($ids, array_search($default_user_id, $ids), 1);
}
if ($ids) {
$q = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData WHERE PortalUserId IN ('.join(',', $ids).') AND
(VariableName LIKE "%_columns_%"
OR
VariableName LIKE "%_filter%"
OR
VariableName LIKE "%_PerPage%")';
$this->Conn->Query($q);
}
$this->clearSelectedIDs($event);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
$virtual_users = Array (USER_ROOT, USER_GUEST);
return ($object->GetDBField('Status') == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users);
}
/**
* Sends approved/declined email event on user status change
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
parent::OnAfterItemUpdate($event);
$this->afterItemChanged($event);
$object =& $event->getObject();
/* @var $object UsersItem */
if (!$this->Application->isAdmin || $object->IsTempTable()) {
return ;
}
$this->sendStatusChangeEvent($object->GetID(), $object->GetOriginalField('Status'), $object->GetDBField('Status'));
}
/**
* Occurs, after item is changed
*
* @param kEvent $event
*/
- function afterItemChanged(&$event)
+ protected function afterItemChanged(&$event)
{
$this->saveUserImages($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('EmailPassword') && $object->GetDBField('Password_plain') ) {
$email_passwords = $this->Application->RecallVar('email_passwords');
$email_passwords = $email_passwords ? unserialize($email_passwords) : Array ();
$email_passwords[ $object->GetID() ] = $object->GetDBField('Password_plain');
$this->Application->StoreVar('email_passwords', serialize($email_passwords));
}
}
/**
* Stores user's original Status before overwriting with data from temp table
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(&$event)
{
- $user_status = $this->Application->GetVar('user_status');
- if (!$user_status) {
- $user_status = Array ();
- }
+ parent::OnBeforeDeleteFromLive($event);
$user_id = $event->getEventParam('id');
- if ($user_id > 0) {
+ $user_status = $this->Application->GetVar('user_status', Array ());
+
+ if ( $user_id > 0 ) {
$user_status[$user_id] = $this->getUserStatus($user_id);
$this->Application->SetVar('user_status', $user_status);
}
}
/**
* Sends approved/declined email event on user status change (in temp tables during editing)
*
* @param kEvent $event
*/
function OnAfterCopyToLive(&$event)
{
parent::OnAfterCopyToLive($event);
$temp_id = $event->getEventParam('temp_id');
$email_passwords = $this->Application->RecallVar('email_passwords');
if ( $email_passwords ) {
$email_passwords = unserialize($email_passwords);
if ( isset($email_passwords[$temp_id]) ) {
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SwitchToLive();
$object->Load( $event->getEventParam('id') );
$object->SetField('Password', $email_passwords[$temp_id]);
$object->SetField('VerifyPassword', $email_passwords[$temp_id]);
$this->Application->EmailEventUser($temp_id > 0 ? 'USER.NEW.PASSWORD': 'USER.ADD.BYADMIN', $object->GetID());
unset($email_passwords[$temp_id]);
$this->Application->StoreVar('email_passwords', serialize($email_passwords));
}
}
if ( $temp_id > 0 ) {
// only send status change e-mail on user update
$new_status = $this->getUserStatus($temp_id);
$user_status = $this->Application->GetVar('user_status');
$this->sendStatusChangeEvent($temp_id, $user_status[$temp_id], $new_status);
}
}
/**
* Returns user status (active, pending, disabled) based on ID and temp mode setting
*
* @param int $user_id
* @return int
*/
function getUserStatus($user_id)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT Status
FROM '.$table_name.'
WHERE '.$id_field.' = '.$user_id;
return $this->Conn->GetOne($sql);
}
/**
* Sends approved/declined email event on user status change
*
* @param int $user_id
* @param int $prev_status
* @param int $new_status
*/
function sendStatusChangeEvent($user_id, $prev_status, $new_status)
{
$status_events = Array (
STATUS_ACTIVE => 'USER.APPROVE',
STATUS_DISABLED => 'USER.DENY',
);
$email_event = isset($status_events[$new_status]) ? $status_events[$new_status] : false;
if (($prev_status != $new_status) && $email_event) {
$this->Application->EmailEventUser($email_event, $user_id);
$this->Application->EmailEventAdmin($email_event);
}
// deletes sessions from users, that are no longer active
if (($prev_status != $new_status) && ($new_status != STATUS_ACTIVE)) {
$sql = 'SELECT SessionKey
FROM ' . TABLE_PREFIX . 'UserSession
WHERE PortalUserId = ' . $user_id;
$session_ids = $this->Conn->GetCol($sql);
$this->Application->Session->DeleteSessions($session_ids);
}
}
/**
* OnAfterConfigRead for users
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
- $fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
+ $forms = $this->Application->getUnitOption($event->Prefix, 'Forms');
+ $form_fields =& $forms['default']['Fields'];
// 1. arrange user registration countries
$site_helper =& $this->Application->recallObject('SiteHelper');
/* @var $site_helper SiteHelper */
$first_country = $site_helper->getDefaultCountry('', false);
if ($first_country === false) {
$first_country = $this->Application->ConfigValue('User_Default_Registration_Country');
}
if ($first_country) {
// update user country dropdown sql
- $fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (CountryStateId = '.$first_country.', 1, 0) DESC, \\1', $fields['Country']['options_sql']);
+ $form_fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (CountryStateId = '.$first_country.', 1, 0) DESC, \\1', $form_fields['Country']['options_sql']);
}
$max_username = $this->Application->ConfigValue('MaxUserName');
$fields['Login']['min_len'] = $this->Application->ConfigValue('Min_UserName');
$fields['Login']['max_len'] = $max_username ? $max_username : 255;
// 2. set default user registration group
- $fields['PrimaryGroupId']['default'] = $this->Application->ConfigValue('User_NewGroup');
+ $form_fields['PrimaryGroupId']['default'] = $this->Application->ConfigValue('User_NewGroup');
// 3. allow avatar upload on Front-End
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->createItemFiles($event->Prefix, true); // create image fields
if ($this->Application->isAdminUser) {
// 4. when in administrative console, then create all users with Active status
- $fields['Status']['default'] = STATUS_ACTIVE;
+ $form_fields['Status']['default'] = STATUS_ACTIVE;
// 5. remove groups tab on editing forms when AdvancedUserManagement config variable not set
if (!$this->Application->ConfigValue('AdvancedUserManagement')) {
$edit_tab_presets = $this->Application->getUnitOption($event->Prefix, 'EditTabPresets');
foreach ($edit_tab_presets as $preset_name => $preset_tabs) {
if (array_key_exists('groups', $preset_tabs)) {
unset($edit_tab_presets[$preset_name]['groups']);
if (count($edit_tab_presets[$preset_name]) == 1) {
// only 1 tab left -> remove it too
$edit_tab_presets[$preset_name] = Array ();
}
}
}
$this->Application->setUnitOption($event->Prefix, 'EditTabPresets', $edit_tab_presets);
}
}
if ( !$this->Application->ConfigValue('Email_As_Login') ) {
// Login becomes required only, when it's used in registration process
- $fields['Login']['required'] = 1;
+ $form_fields['Login']['required'] = 1;
}
- $this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
+ $this->Application->setUnitOption($event->Prefix, 'Forms', $forms);
}
/**
* OnMassCloneUsers
*
* @param kEvent $event
*/
function OnMassCloneUsers(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$temp_handler =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$ids = $this->StoreSelectedIDs($event);
$temp_handler->CloneItems($event->Prefix, '', $ids);
$this->clearSelectedIDs($event);
}
/**
* When cloning users, reset password (set random)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeClone(&$event)
+ protected function OnBeforeClone(&$event)
{
+ parent::OnBeforeClone($event);
+
$object =& $event->getObject();
/* @var $object UsersItem */
$object->generatePassword();
$object->SetDBField('ResourceId', 0); // this will reset it
// change email because it should be unique
$object->NameCopy(Array (), $object->GetID(), 'Email', 'copy%1$s.%2$s');
}
/**
* Saves selected ids to session
*
* @param kEvent $event
*/
function OnSaveSelected(&$event)
{
$this->StoreSelectedIDs($event);
// remove current ID, otherwise group selector will use it in filters
$this->Application->DeleteVar($event->getPrefixSpecial(true) . '_id');
}
/**
* Sets primary group of selected users
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$event->SetRedirectParam('opener', 'u');
$user_ids = $this->getSelectedIDs($event, true);
$this->clearSelectedIDs($event);
$dst_field = $this->Application->RecallVar('dst_field');
if ($dst_field != 'PrimaryGroupId') {
return ;
}
$group_ids = $this->Application->GetVar('g');
$primary_group_id = $group_ids ? array_shift( array_keys($group_ids) ) : false;
if (!$user_ids || !$primary_group_id) {
return ;
}
$table_name = $this->Application->getUnitOption('ug', 'TableName');
// 1. mark group as primary
$sql = 'UPDATE ' . TABLE_PREFIX . 'PortalUser
SET PrimaryGroupId = ' . $primary_group_id . '
WHERE PortalUserId IN (' . implode(',', $user_ids) . ')';
$this->Conn->Query($sql);
$sql = 'SELECT PortalUserId
FROM ' . $table_name . '
WHERE (GroupId = ' . $primary_group_id . ') AND (PortalUserId IN (' . implode(',', $user_ids) . '))';
$existing_members = $this->Conn->GetCol($sql);
// 2. add new members to a group
$new_members = array_diff($user_ids, $existing_members);
foreach ($new_members as $user_id) {
$fields_hash = Array (
'GroupId' => $primary_group_id,
'PortalUserId' => $user_id,
);
$this->Conn->doInsert($fields_hash, $table_name);
}
}
/**
* Loads user images
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(&$event)
{
parent::OnAfterItemLoad($event);
// linking existing images for item with virtual fields
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
$image_helper->LoadItemImages($object);
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$cs_helper->PopulateStates($event, 'State', 'Country');
}
/**
* Save user images
*
* @param kEvent $event
*/
function saveUserImages(&$event)
{
if (!$this->Application->isAdmin) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
}
}
/**
* Makes password required for new users
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
function OnPreCreate(&$event)
{
parent::OnPreCreate($event);
- if ($event->status != kEvent::erSUCCESS) {
- return ;
+ if ( $event->status != kEvent::erSUCCESS ) {
+ return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$user_type = $this->Application->GetVar('user_type');
- if ($user_type) {
+ if ( $user_type ) {
$object->SetDBField('UserType', $user_type);
if ( $user_type == UserType::ADMIN ) {
$object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_AdminGroup'));
}
}
if ( $this->Application->ConfigValue('User_Password_Auto') ) {
$object->SetDBField('EmailPassword', 1);
}
$this->_makePasswordRequired($event);
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
- function OnNew(&$event)
- {
- parent::OnNew($event);
-
- if ($event->status == kEvent::erSUCCESS) {
- $this->_makePasswordRequired($event);
- }
- }
-
- /**
- * Makes password required for new users
- *
- * @param kEvent $event
- */
function _makePasswordRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required_fields = Array ('Password', 'Password_plain', 'VerifyPassword', 'VerifyPassword_plain');
- foreach ($required_fields as $required_field) {
- $object->setRequired($required_field);
- }
+ $object->setRequired($required_fields);
}
/**
* Load item if id is available
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function LoadItem(&$event)
+ protected function LoadItem(&$event)
{
$id = $this->getPassedID($event);
- if ($id < 0) {
+ if ( $id < 0 ) {
// when root, guest and so on
$object =& $event->getObject();
/* @var $object kDBItem */
$object->Clear($id);
return ;
}
parent::LoadItem($event);
}
/**
* Occurs just after login (for hooking)
*
* @param kEvent $event
*/
function OnAfterLogin(&$event)
{
}
/**
* Occurs just before logout (for hooking)
*
* @param kEvent $event
*/
function OnBeforeLogout(&$event)
{
}
/**
* Generates password
*
* @param kEvent $event
*/
function OnGeneratePassword(&$event)
{
$event->status = kEvent::erSTOP;
if ( $this->Application->isAdminUser ) {
echo kUtil::generatePassword();
}
}
/**
* Changes user's password and logges him in
*
* @param kEvent $event
*/
function OnResetLostPassword(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$event->CallSubEvent('OnUpdate');
if ( $event->status == kEvent::erSUCCESS ) {
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user =& $user_helper->getUserObject();
$user->Load( $object->GetID() );
if ( $user_helper->checkLoginPermission() ) {
$user_helper->loginUserById( $user->GetID() );
}
}
}
}
Index: branches/5.2.x/core/units/users/users_item.php
===================================================================
--- branches/5.2.x/core/units/users/users_item.php (revision 14595)
+++ branches/5.2.x/core/units/users/users_item.php (revision 14596)
@@ -1,143 +1,185 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 UsersItem extends kDBItem {
/**
* Returns IDs of groups to which user belongs and membership is not expired
*
* @return Array
* @access public
*/
function getMembershipGroups($force_reload = false)
{
$user_groups = $this->Application->RecallVar('UserGroups');
if($user_groups === false || $force_reload)
{
// primary group goes first
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroup
WHERE (PortalUserId = ' . $this->GetID() . ') AND ( (MembershipExpires IS NULL) OR ( MembershipExpires >= UNIX_TIMESTAMP() ) )
ORDER BY IF(GroupId = ' . $this->GetDBField('PrimaryGroupId') . ', 1, 0) DESC';
return $this->Conn->GetCol($sql);
}
else
{
return explode(',', $user_groups);
}
}
function SendEmailEvents()
{
- switch ($this->GetDBField('Status')) {
+ switch ( $this->GetDBField('Status') ) {
case STATUS_ACTIVE:
$event_name = $this->Application->ConfigValue('User_Password_Auto') ? 'USER.VALIDATE' : 'USER.ADD';
$this->Application->EmailEventAdmin($event_name);
$this->Application->EmailEventUser($event_name, $this->GetID());
break;
case STATUS_PENDING:
$this->Application->EmailEventAdmin('USER.ADD.PENDING');
$this->Application->EmailEventUser('USER.ADD.PENDING', $this->GetID());
break;
}
}
/**
* Checks that user is subscriber only
*
* @return bool
*/
- function isSubscriberOnly()
+ public function isSubscriberOnly()
{
return $this->GetDBField('PrimaryGroupId') == $this->Application->ConfigValue('User_SubscriberGroup');
}
- function Create($force_id=false, $system_create=false)
+ /**
+ * Checks that user is subscribed
+ *
+ * @return bool
+ */
+ public function isSubscribed()
+ {
+ $group_id = $this->Application->ConfigValue('User_SubscriberGroup');
+
+ $sql = 'SELECT GroupId
+ FROM ' . TABLE_PREFIX . 'UserGroup
+ WHERE (PortalUserId = ' . $this->GetID() . ') AND (GroupId = ' . $group_id . ')';
+
+ return $this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Creates a record in the database table with current item' values
+ *
+ * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
+ * @param bool $system_create
+ * @return bool
+ * @access public
+ */
+ public function Create($force_id = false, $system_create = false)
{
$ret = parent::Create($force_id, $system_create);
- if ($ret) {
- // find out how to syncronize user only when it's copied to live table
- $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize'));
+ if ( $ret ) {
+ // find out how to synchronize user only when it's copied to live table
+ $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize'));
+ /* @var $sync_manager UsersSyncronizeManager */
+
$sync_manager->performAction('createUser', $this->FieldValues);
}
return $ret;
}
-
- function Update($id=null, $system_update=false)
+ /**
+ * Updates previously loaded record with current item' values
+ *
+ * @access public
+ * @param int $id Primary Key Id to update
+ * @param bool $system_update
+ * @return bool
+ * @access public
+ */
+ public function Update($id = null, $system_update = false)
{
$ret = parent::Update($id, $system_update);
- if ($ret) {
- // find out how to syncronize user only when it's copied to live table
- $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize'));
+
+ if ( $ret ) {
+ // find out how to synchronize user only when it's copied to live table
+ $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize'));
+ /* @var $sync_manager UsersSyncronizeManager */
+
$sync_manager->performAction('updateUser', $this->FieldValues);
}
+
return $ret;
}
/**
- * Deletes the record from databse
- *
- * @access public
- * @return bool
- */
- function Delete($id = null)
+ * Deletes the record from database
+ *
+ * @param int $id
+ * @return bool
+ * @access public
+ */
+ public function Delete($id = null)
{
$ret = parent::Delete($id);
- if ($ret) {
- $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize'));
+
+ if ( $ret ) {
+ $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize'));
+ /* @var $sync_manager UsersSyncronizeManager */
+
$sync_manager->performAction('deleteUser', $this->FieldValues);
}
return $ret;
}
function setName($full_name)
{
$full_name = explode(' ', $full_name);
if (count($full_name) > 2) {
$last_name = array_pop($full_name);
$first_name = implode(' ', $full_name);
}
else {
$last_name = $full_name[1];
$first_name = $full_name[0];
}
$this->SetDBField('FirstName', $first_name);
$this->SetDBField('LastName', $last_name);
}
/**
* Generates new password for given user
*
* @param int $length
* @return string
* @access public
*/
public function generatePassword($length = 10)
{
$password = kUtil::generatePassword($length);
$this->SetField('Password', $password);
$this->SetField('VerifyPassword', $password);
return $password;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/users/users_config.php
===================================================================
--- branches/5.2.x/core/units/users/users_config.php (revision 14595)
+++ branches/5.2.x/core/units/users/users_config.php (revision 14596)
@@ -1,565 +1,633 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
$config = Array(
'Prefix' => 'u',
'ItemClass' => Array('class'=>'UsersItem','file'=>'users_item.php','build_event'=>'OnItemBuild'),
'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'),
'EventHandlerClass' => Array('class'=>'UsersEventHandler','file'=>'users_event_handler.php','build_event'=>'OnBuild'),
'TagProcessorClass' => Array('class'=>'UsersTagProcessor','file'=>'users_tag_processor.php','build_event'=>'OnBuild'),
'RegisterClasses' => Array(
Array('pseudo' => 'UsersSyncronizeManager', 'class' => 'UsersSyncronizeManager', 'file' => 'users_syncronize.php', 'build_event' => ''),
),
'AutoLoad' => true,
'ConfigPriority' => 0,
'Hooks' => Array (
Array (
'Mode' => hBEFORE,
'Conditional' => false,
- 'HookToPrefix' => 'affil',
- 'HookToSpecial' => '*',
- 'HookToEvent' => Array('OnCheckAffiliateAgreement'),
- 'DoPrefix' => '',
- 'DoSpecial' => '*',
- 'DoEvent' => 'OnSubstituteSubscriber',
- ),
-
- Array (
- 'Mode' => hBEFORE,
- 'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterConfigRead'),
'DoPrefix' => 'cdata',
'DoSpecial' => '*',
'DoEvent' => 'OnDefineCustomFields',
),
Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => 'adm',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnStartup'),
'DoPrefix' => '',
'DoSpecial' => '*',
'DoEvent' => 'OnAutoLoginUser',
),
Array (
'Mode' => hBEFORE,
'Conditional' => false,
'HookToPrefix' => 'img',
'HookToSpecial' => '*',
'HookToEvent' => Array ('OnAfterConfigRead'),
'DoPrefix' => '',
'DoSpecial' => '*',
'DoEvent' => 'OnCloneSubItem',
),
// Captcha processing
Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterConfigRead'),
'DoPrefix' => 'captcha',
'DoSpecial' => '*',
'DoEvent' => 'OnPrepareCaptcha',
),
/*Array (
'Mode' => hAFTER,
'Conditional' => false,
'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnBeforeItemCreate'),
'DoPrefix' => 'captcha',
'DoSpecial' => '*',
'DoEvent' => 'OnValidateCode',
),*/
),
'QueryString' => Array(
1 => 'id',
2 => 'Page',
3 => 'PerPage',
4 => 'event',
5 => 'mode',
),
'RegularEvents' => Array(
'membership_expiration' => Array('EventName' => 'OnCheckExpiredMembership', 'RunInterval' => 1800, 'Type' => reAFTER),
'delete_expired_sessions' => Array('EventName' => 'OnDeleteExpiredSessions', 'RunInterval' => 43200, 'Type' => reAFTER),
),
'IDField' => 'PortalUserId',
'StatusField' => Array('Status'),
'TitleField' => 'Login',
'ItemType' => 6, // used for custom fields only (on user's case)
'StatisticsInfo' => Array(
'pending' => Array(
'icon' => 'icon16_user_pending.gif',
'label' => 'la_Text_Users',
'js_url' => '#url#',
'url' => Array('t' => 'users/users_list', 'pass' => 'm,u', 'u_event' => 'OnSetFilterPattern', 'u_filters' => 'show_active=0,show_pending=1,show_disabled=0'),
'status' => STATUS_PENDING,
),
),
'TitlePresets' => Array (
'default' => Array (
'new_status_labels' => Array ('u' => '!la_title_Adding_User!'),
'edit_status_labels' => Array ('u' => '!la_title_Editing_User!'),
),
'users_list' => Array (
'prefixes' => Array ('u_List'), 'format' => "!la_title_Users!",
'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'setprimary', 'approve', 'decline', 'e-mail', 'export', 'view', 'dbl-click'),
),
'users_edit' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# #u_titlefield#",
'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'),
),
'user_edit_images' => Array (
'prefixes' => Array ('u', 'u-img_List'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Images!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'new_item', 'edit', 'delete', 'approve', 'decline', 'setprimary', 'move_up', 'move_down', 'view', 'dbl-click'),
),
'user_edit_groups' => Array (
'prefixes' => Array ('u', 'u-ug_List'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Groups!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'select_user', 'edit', 'delete', 'setprimary', 'view', 'dbl-click'),
),
'user_edit_items' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Items!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next', 'edit', 'delete', 'view', 'dbl-click'),
),
'user_edit_custom' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# '#u_titlefield#' - !la_title_Custom!",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next'),
),
'admin_list' => Array (
'prefixes' => Array ('u.admins_List'), 'format' => "!la_title_Administrators!",
'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'clone', 'refresh', 'view', 'dbl-click'),
),
'admins_edit' => Array (
'prefixes' => Array ('u'), 'format' => "#u_status# #u_titlefield#",
'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'),
),
'regular_users_list' => Array (
'prefixes' => Array ('u.regular_List'), 'format' => "!la_title_Users!",
'toolbar_buttons' => Array (),
),
'root_edit' => Array (
'prefixes' => Array ('u'), 'format' => "!la_title_Editing_User! 'root'",
'toolbar_buttons' => Array ('select', 'cancel'),
),
'user_edit_group' => Array (
'prefixes' => Array ('u', 'u-ug'),
'edit_status_labels' => Array ('u-ug' => '!la_title_EditingMembership!'),
'format' => "#u_status# '#u_titlefield#' - #u-ug_status# '#u-ug_titlefield#'",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next'),
),
'user_image_edit' => Array (
'prefixes' => Array ('u', 'u-img'),
'new_status_labels' => Array ('u-img' => '!la_title_Adding_Image!'),
'edit_status_labels' => Array ('u-img' => '!la_title_Editing_Image!'),
'new_titlefield' => Array ('u-img' => '!la_title_New_Image!'),
'format' => "#u_status# '#u_titlefield#' - #u-img_status# '#u-img_titlefield#'",
'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next'),
),
'user_select' => Array (
'prefixes' => Array ('u_List'), 'format' => "!la_title_Users! - !la_title_SelectUser!",
'toolbar_buttons' => Array ('select', 'cancel', 'dbl-click'),
),
'group_user_select' => Array (
'prefixes' => Array ('u.group_List'), 'format' => "!la_title_Users! - !la_title_SelectUser!",
'toolbar_buttons' => Array ('select', 'cancel', 'view', 'dbl-click'),
),
'tree_users' => Array('format' => '!la_section_overview!'),
),
'EditTabPresets' => Array (
'Default' => Array (
'general' => Array ('title' => 'la_tab_General', 't' => 'users/users_edit', 'priority' => 1),
'groups' => Array ('title' => 'la_tab_Groups', 't' => 'users/users_edit_groups', 'priority' => 2),
'images' => Array ('title' => 'la_tab_Images', 't' => 'users/user_edit_images', 'priority' => 3),
'items' => Array ('title' => 'la_tab_Items', 't' => 'users/user_edit_items', 'priority' => 4),
'custom' => Array ('title' => 'la_tab_Custom', 't' => 'users/users_edit_custom', 'priority' => 5),
),
'Admins' => Array (
'general' => Array ('title' => 'la_tab_General', 't' => 'users/admins_edit', 'priority' => 1),
'groups' => Array ('title' => 'la_tab_Groups', 't' => 'users/admins_edit_groups', 'priority' => 2),
),
),
'PermSection' => Array('main' => 'in-portal:user_list', 'custom' => 'in-portal:user_custom'),
'Sections' => Array (
'in-portal:user_list' => Array (
'parent' => 'in-portal:users',
'icon' => 'users',
'label' => 'la_title_Users', // 'la_tab_User_List',
'url' => Array ('t' => 'users/users_list', 'pass' => 'm'),
'permissions' => Array ('view', 'add', 'edit', 'delete', 'advanced:ban', 'advanced:send_email', /*'advanced:add_favorite', 'advanced:remove_favorite',*/),
'priority' => 1,
'type' => stTREE,
),
'in-portal:admins' => Array (
'parent' => 'in-portal:users',
'icon' => 'administrators',
'label' => 'la_title_Administrators',
'url' => Array ('t' => 'users/admins_list', 'pass' => 'm'),
'permissions' => Array ('view', 'add', 'edit', 'delete'),
'perm_prefix' => 'u',
'priority' => 2,
'type' => stTREE,
),
// user settings
'in-portal:user_setting_folder' => Array (
'parent' => 'in-portal:system',
'icon' => 'conf_users',
'label' => 'la_title_Users',
'use_parent_header' => 1,
'url' => Array ('t' => 'index', 'pass_section' => true, 'pass' => 'm'),
'permissions' => Array ('view'),
'priority' => 2,
'container' => true,
'type' => stTREE,
),
'in-portal:configure_users' => Array (
'parent' => 'in-portal:user_setting_folder',
'icon' => 'conf_users_general',
'label' => 'la_tab_ConfigSettings',
'url' => Array ('t' => 'config/config_universal', 'module' => 'In-Portal:Users', 'pass_section' => true, 'pass' => 'm'),
'permissions' => Array ('view', 'edit'),
'priority' => 1,
'type' => stTREE,
),
'in-portal:user_custom' => Array (
'parent' => 'in-portal:user_setting_folder',
'icon' => 'conf_customfields',
'label' => 'la_tab_ConfigCustom',
'url' => Array ('t' => 'custom_fields/custom_fields_list', 'cf_type' => 6, 'pass_section' => true, 'pass' => 'm,cf'),
'permissions' => Array ('view', 'add', 'edit', 'delete'),
'priority' => 2,
'type' => stTREE,
),
),
'TableName' => TABLE_PREFIX.'PortalUser',
'ListSQLs' => Array( '' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON %1$s.PrimaryGroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId
LEFT JOIN '.TABLE_PREFIX.'%3$sImages img ON img.ResourceId = %1$s.ResourceId AND img.DefaultImg = 1',
'online' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'UserSession s ON s.PortalUserId = %1$s.PortalUserId
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON %1$s.PrimaryGroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId
LEFT JOIN '.TABLE_PREFIX.'%3$sImages img ON img.ResourceId = %1$s.ResourceId AND img.DefaultImg = 1',
),
'ItemSQLs' => Array( '' => ' SELECT %1$s.* %2$s FROM %1$s
LEFT JOIN '.TABLE_PREFIX.'PortalGroup g ON %1$s.PrimaryGroupId = g.GroupId
LEFT JOIN '.TABLE_PREFIX.'%3$sPortalUserCustomData cust ON %1$s.ResourceId = cust.ResourceId
LEFT JOIN '.TABLE_PREFIX.'%3$sImages img ON img.ResourceId = %1$s.ResourceId AND img.DefaultImg = 1',
),
'ListSortings' => Array (
'' => Array (
'Sorting' => Array ('Login' => 'asc'),
)
),
'SubItems' => Array('addr', 'u-cdata', 'u-ug', 'u-img', 'fav', 'user-profile'),
/**
* Required for depricated public profile templates to work
*/
'UserProfileMapping' => Array (
'pp_firstname' => 'FirstName',
'pp_lastname' => 'LastName',
'pp_dob' => 'dob',
'pp_email' => 'Email',
'pp_phone' => 'Phone',
'pp_street' => 'Street',
'pp_city' => 'City',
'pp_state' => 'State',
'pp_zip' => 'Zip',
'pp_country' => 'Country',
),
'CalculatedFields' => Array(
'' => Array(
'PrimaryGroup' => 'g.Name',
'FullName' => 'CONCAT(FirstName, " ", LastName)',
'AltName' => 'img.AltName',
'SameImages' => 'img.SameImages',
'LocalThumb' => 'img.LocalThumb',
'ThumbPath' => 'img.ThumbPath',
'ThumbUrl' => 'img.ThumbUrl',
'LocalImage' => 'img.LocalImage',
'LocalPath' => 'img.LocalPath',
'FullUrl' => 'img.Url',
),
),
- 'Fields' => Array
- (
- 'PortalUserId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
- 'Login' => Array (
- 'type' => 'string', 'max_len' => 255,
- 'formatter' => 'kFormatter', 'regexp' => '/^[A-Z\d_\-\.]+$/i',
- 'error_msgs' => Array('unique' => '!lu_user_already_exist!', 'invalid_format' => '!la_error_InvalidLogin!', 'banned' => '!la_error_UserBanned!'),
- 'not_null' => 1, 'unique' => Array (), 'default' => '',
- ),
- 'Password' => Array ('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyPassword', 'skip_empty' => 1, 'default' => md5('')),
- 'FirstName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'LastName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'Company' => Array ('type' => 'string','not_null' => 1,'default' => ''),
- 'Email' => Array (
- 'type' => 'string',
- 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
- 'sample_value' => 'email@domain.com',
- 'error_msgs' => Array (
- 'invalid_format' => '!la_invalid_email!', 'unique' => '!lu_email_already_exist!'
- ),
- 'not_null' => 1, 'unique' => Array (), 'required' => 1, 'default' => ''
- ),
- 'CreatedOn' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
- 'Phone' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'Fax' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'Street' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'Street2' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'City' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'State' => Array(
- 'type' => 'string',
- 'formatter' => 'kOptionsFormatter', 'options' => Array(),
- 'not_null' => 1,
- 'default' => '',
+ 'Forms' => Array (
+ 'default' => Array (
+ 'Fields' => Array (
+ 'PortalUserId' => Array ('default' => 0),
+ 'Login' => Array (
+ 'max_len' => 255,
+ 'formatter' => 'kFormatter', 'regexp' => '/^[A-Z\d_\-\.]+$/i',
+ 'error_msgs' => Array(
+ 'unique' => '!lu_user_already_exist!', 'invalid_format' => '!la_error_InvalidLogin!', 'banned' => '!la_error_UserBanned!'
+ ),
+ 'unique' => Array (), 'default' => '',
+ ),
+ 'Password' => Array (
+ 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyPassword',
+ 'default' => 'd41d8cd98f00b204e9800998ecf8427e'
+ ),
+ 'FirstName' => Array ('default' => ''),
+ 'LastName' => Array ('default' => ''),
+ 'Company' => Array ('default' => ''),
+ 'Email' => Array (
+ 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
+ 'sample_value' => 'email@domain.com', 'error_msgs' => Array (
+ 'invalid_format' => '!la_invalid_email!', 'unique' => '!lu_email_already_exist!'
+ ),
+ 'unique' => Array (), 'required' => 1, 'default' => ''
+ ),
+ 'CreatedOn' => Array ('formatter' => 'kDateFormatter', 'default' => '#NOW#'),
+ 'Phone' => Array ('default' => ''),
+ 'Fax' => Array ('default' => ''),
+ 'Street' => Array ('default' => ''),
+ 'Street2' => Array ('default' => ''),
+ 'City' => Array ('default' => ''),
+ 'State' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (),
+ 'default' => '',
+ ),
+ 'Zip' => Array ('default' => ''),
+ 'Country' => Array (
+ 'formatter' => 'kOptionsFormatter',
+ 'options_sql' => ' SELECT IF(l%2$s_Name = "", l%3$s_Name, l%2$s_Name) AS Name, IsoCode
+ FROM ' . TABLE_PREFIX . 'CountryStates
+ WHERE Type = ' . DESTINATION_TYPE_COUNTRY . '
+ ORDER BY Name',
+ 'option_key_field' => 'IsoCode', 'option_title_field' => 'Name',
+ 'default' => '',
+ ),
+ 'ResourceId' => Array ('default' => 0),
+ 'Status' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Enabled', 0 => 'la_Disabled', 2 => 'la_Pending'), 'use_phrases' => 1,
+ 'default' => 1
+ ),
+ 'Modified' => Array ('formatter' => 'kDateFormatter', 'default' => NULL),
+ 'dob' => Array ('formatter' => 'kDateFormatter', 'default' => NULL),
+ 'tz' => Array ('default' => NULL),
+ 'ip' => Array ('default' => ''),
+ 'IsBanned' => Array ('default' => 0),
+ 'PwResetConfirm' => Array ('default' => ''),
+ 'PwRequestTime' => Array ('formatter' => 'kDateFormatter', 'default' => NULL),
+ 'AdminLanguage' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName',
+ 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName', 'default' => NULL
+ ),
+ 'DisplayToPublic' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (
+ 'FirstName' => 'lu_fld_FirstName', 'LastName' => 'lu_fld_LastName', 'dob' => 'lu_fld_BirthDate',
+ 'Email' => 'lu_fld_Email', 'Phone' => 'lu_fld_Phone', 'Street' => 'lu_fld_AddressLine1',
+ 'Street2' => 'lu_fld_AddressLine2', 'City' => 'lu_fld_City', 'State' => 'lu_fld_State',
+ 'Zip' => 'lu_fld_Zip', 'Country' => 'lu_fld_Country',
+ ), 'use_phrases' => 1, 'multiple' => 1,
+ 'default' => NULL
+ ),
+ 'UserType' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_UserTypeUser', 1 => 'la_opt_UserTypeAdmin'), 'use_phrases' => 1,
+ 'default' => 0
+ ),
+ 'PrimaryGroupId' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %1$s FROM ' . TABLE_PREFIX . 'PortalGroup WHERE Enabled = 1 AND FrontRegistration = 1',
+ 'option_key_field' => 'GroupId', 'option_title_field' => 'Name', 'default' => NULL
+ ),
+ 'OldStyleLogin' => Array (
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'default' => 0
+ ),
+ ),
+
+ 'VirtualFields' => Array (
+ 'PrimaryGroup' => Array ('default' => ''),
+ 'RootPassword' => Array (
+ 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5',
+ 'verify_field' => 'VerifyRootPassword', 'default' => 'd41d8cd98f00b204e9800998ecf8427e'
+ ),
+ 'EmailPassword' => Array ('default' => ''),
+ 'FullName' => Array ('default' => ''),
+ 'AltName' => Array ('default' => ''),
+ 'SameImages' => Array ('default' => ''),
+ 'LocalThumb' => Array ('default' => ''),
+ 'ThumbPath' => Array ('default' => ''),
+ 'ThumbUrl' => Array ('default' => ''),
+ 'LocalImage' => Array ('default' => ''),
+ 'LocalPath' => Array ('default' => ''),
+ 'FullUrl' => Array ('default' => ''),
+ ),
+ ),
+
+ 'registration' => Array (
+ // Front-End user registration form
+ /*'Fields' => Array (
+ 'FirstName' => Array ('required' => 1),
+ ),*/
+ ),
+
+ 'recommend' => Array (
+ 'VirtualFields' => Array (
+ 'RecommendEmail' => Array (
+ 'type' => 'string',
+ 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
+ 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!', 'send_error' => '!lu_email_send_error!'),
+ 'sample_value' => 'email@domain.com',
+ 'required' => 1, 'default' => ''
+ ),
+ ),
+ ),
+
+ 'subscription' => Array (
+ 'VirtualFields' => Array (
+ 'SubscriberEmail' => Array (
+ 'type' => 'string',
+ 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
+ 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!'),
+ 'sample_value' => 'email@domain.com',
+ 'required' => 1, 'default' => ''
+ ),
+ ),
+ ),
+
+ 'forgot_password' => Array (
+ 'VirtualFields' => Array (
+ 'ForgotLogin' => Array (
+ 'type' => 'string',
+ 'error_msgs' => Array (
+ 'required' => '!lu_ferror_forgotpw_nodata!',
+ 'unknown_username' => '!lu_ferror_unknown_username!',
+ 'reset_denied' => '!lu_ferror_reset_denied!',
),
- 'Zip' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'Country' => Array(
- 'type' => 'string',
- 'formatter' => 'kOptionsFormatter',
- 'options_sql' => ' SELECT IF(l%2$s_Name = "", l%3$s_Name, l%2$s_Name) AS Name, IsoCode
- FROM ' . TABLE_PREFIX . 'CountryStates
- WHERE Type = ' . DESTINATION_TYPE_COUNTRY . '
- ORDER BY Name',
- 'option_key_field' => 'IsoCode', 'option_title_field' => 'Name',
- 'not_null' => 1, 'default' => '',
+ 'default' => ''
+ ),
+ 'ForgotEmail' => Array (
+ 'type' => 'string',
+ 'error_msgs' => Array (
+ 'required' => '!lu_ferror_forgotpw_nodata!',
+ 'unknown_email' => '!lu_ferror_unknown_email!',
+ 'reset_denied' => '!lu_ferror_reset_denied!',
),
- 'ResourceId' => Array('type' => 'int','not_null' => 1, 'default' => 0),
- 'Status' => Array('type' => 'int', 'formatter'=>'kOptionsFormatter', 'options'=>Array(1=>'la_Enabled', 0=>'la_Disabled', 2=>'la_Pending'), 'use_phrases'=>1, 'not_null' => 1, 'default' => 1),
- 'Modified' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL),
- 'dob' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => NULL),
- 'tz' => Array('type' => 'int', 'default' => NULL),
- 'ip' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'IsBanned' => Array('type' => 'int','not_null' => 1, 'default' => 0),
- 'PwResetConfirm' => Array('type' => 'string', 'not_null' => 1, 'default' => ''),
- 'PwRequestTime' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL),
- 'AdminLanguage' => Array (
- 'type' => 'int',
- 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName', 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName',
- 'default' => NULL
- ),
- 'DisplayToPublic' => Array (
- 'type' => 'string',
- 'formatter' => 'kOptionsFormatter', 'options' => Array (
- 'FirstName' => 'lu_fld_FirstName', 'LastName' => 'lu_fld_LastName', 'dob' => 'lu_fld_BirthDate',
- 'Email' => 'lu_fld_Email', 'Phone' => 'lu_fld_Phone', 'Street' => 'lu_fld_AddressLine1',
- 'Street2' => 'lu_fld_AddressLine2', 'City' => 'lu_fld_City', 'State' => 'lu_fld_State',
- 'Zip' => 'lu_fld_Zip', 'Country' => 'lu_fld_Country',
- ), 'use_phrases' => 1, 'multiple' => 1,
- 'default' => NULL
- ),
- 'UserType' => Array (
- 'type' => 'int',
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_UserTypeUser', 1 => 'la_opt_UserTypeAdmin'), 'use_phrases' => 1,
- 'not_null' => 1, 'default' => 0
- ),
- 'PrimaryGroupId' => Array (
- 'type' => 'int',
- 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %1$s FROM ' . TABLE_PREFIX . 'PortalGroup WHERE Enabled = 1 AND FrontRegistration = 1', 'option_key_field' => 'GroupId', 'option_title_field' => 'Name',
- 'default' => NULL
- ),
- 'OldStyleLogin' => Array (
- 'type' => 'int',
- 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
- 'not_null' => 1, 'default' => 0
+ 'default' => ''
+ ),
+ ),
+ ),
+
+ 'login' => Array (
+ 'VirtualFields' => Array (
+ 'UserLogin' => Array (
+ 'type' => 'string',
+ 'error_msgs' => Array (
+ 'no_permission' => '!la_no_permissions!', 'invalid_password' => '!la_invalid_password!'
),
- ),
+ 'default' => ''
+ ),
+ 'UserPassword' => Array ('type' => 'string', 'default' => ''),
+ 'UserRememberLogin' => Array ('type' => 'int', 'default' => 0),
+ ),
+ ),
+ ),
- 'VirtualFields' => Array(
- 'ValidateLogin' => Array('type'=>'string','default'=>''),
- 'SubscribeEmail' => Array('type'=>'string','default'=>''),
- 'PrimaryGroup' => Array('type' => 'string', 'default' => ''),
- 'RootPassword' => Array('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyRootPassword', 'skip_empty' => 1, 'default' => md5('') ),
- 'EmailPassword' => Array ('type' => 'string', 'default' => ''),
- 'FullName' => Array ('type' => 'string', 'default' => ''),
- 'AltName' => Array ('type' => 'string', 'default' => ''),
- 'SameImages' => Array ('type' => 'string', 'default' => ''),
- 'LocalThumb' => Array ('type' => 'string', 'default' => ''),
- 'ThumbPath' => Array ('type' => 'string', 'default' => ''),
- 'ThumbUrl' => Array ('type' => 'string', 'default' => ''),
- 'LocalImage' => Array ('type' => 'string', 'default' => ''),
- 'LocalPath' => Array ('type' => 'string', 'default' => ''),
- 'FullUrl' => Array ('type' => 'string', 'default' => ''),
-
- // for login form
- 'UserLogin' => Array (
- 'type' => 'string',
- 'error_msgs' => Array (
- 'no_permission' => '!la_no_permissions!', 'invalid_password' => '!la_invalid_password!'
- ),
- 'default' => ''
- ),
- 'UserPassword' => Array ('type' => 'string', 'default' => ''),
- 'UserRememberLogin' => Array ('type' => 'int', 'default' => 0),
-
- // for recommend form
- 'RecommendEmail' => Array (
- 'type' => 'string',
- 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i',
- 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!', 'send_error' => '!lu_email_send_error!'),
- 'sample_value' => 'email@domain.com', 'default' => ''
- ),
-
- // for forgot password form
- 'ForgotLogin' => Array (
- 'type' => 'string',
- 'error_msgs' => Array (
- 'required' => '!lu_ferror_forgotpw_nodata!',
- 'unknown_username' => '!lu_ferror_unknown_username!',
- 'reset_denied' => '!lu_ferror_reset_denied!',
- ),
- 'default' => ''
- ),
- 'ForgotEmail' => Array (
- 'type' => 'string',
- 'error_msgs' => Array (
- 'required' => '!lu_ferror_forgotpw_nodata!',
- 'unknown_email' => '!lu_ferror_unknown_email!',
- 'reset_denied' => '!lu_ferror_reset_denied!',
- ),
- 'default' => ''
- ),
+ 'Fields' => Array (
+ 'PortalUserId' => Array ('type' => 'int', 'not_null' => 1),
+ 'Login' => Array ('type' => 'string', 'not_null' => 1),
+ 'Password' => Array ('type' => 'string', 'skip_empty' => 1),
+ 'FirstName' => Array ('type' => 'string', 'not_null' => 1),
+ 'LastName' => Array ('type' => 'string', 'not_null' => 1),
+ 'Company' => Array ('type' => 'string','not_null' => 1),
+ 'Email' => Array ('type' => 'string', 'not_null' => 1),
+ 'CreatedOn' => Array ('type' => 'int'),
+ 'Phone' => Array ('type' => 'string', 'not_null' => 1),
+ 'Fax' => Array ('type' => 'string', 'not_null' => 1),
+ 'Street' => Array ('type' => 'string', 'not_null' => 1),
+ 'Street2' => Array ('type' => 'string', 'not_null' => 1),
+ 'City' => Array ('type' => 'string', 'not_null' => 1),
+ 'State' => Array ('type' => 'string', 'not_null' => 1),
+ 'Zip' => Array ('type' => 'string', 'not_null' => 1),
+ 'Country' => Array ('type' => 'string', 'not_null' => 1),
+ 'ResourceId' => Array ('type' => 'int', 'not_null' => 1),
+ 'Status' => Array ('type' => 'int', 'not_null' => 1),
+ 'Modified' => Array ('type' => 'int'),
+ 'dob' => Array ('type' => 'int'),
+ 'tz' => Array ('type' => 'int'),
+ 'ip' => Array ('type' => 'string', 'not_null' => 1),
+ 'IsBanned' => Array ('type' => 'int', 'not_null' => 1),
+ 'PwResetConfirm' => Array ('type' => 'string', 'not_null' => 1),
+ 'PwRequestTime' => Array ('type' => 'int'),
+ 'AdminLanguage' => Array ('type' => 'int'),
+ 'DisplayToPublic' => Array ('type' => 'string'),
+ 'UserType' => Array ('type' => 'int', 'not_null' => 1),
+ 'PrimaryGroupId' => Array ('type' => 'int'),
+ 'OldStyleLogin' => Array ('type' => 'int', 'not_null' => 1),
+ ),
+
+ 'VirtualFields' => Array (
+ 'PrimaryGroup' => Array ('type' => 'string'),
+ 'RootPassword' => Array ('type' => 'string', 'skip_empty' => 1),
+ 'EmailPassword' => Array ('type' => 'string'),
+ 'FullName' => Array ('type' => 'string'),
+ 'AltName' => Array ('type' => 'string'),
+ 'SameImages' => Array ('type' => 'string'),
+ 'LocalThumb' => Array ('type' => 'string'),
+ 'ThumbPath' => Array ('type' => 'string'),
+ 'ThumbUrl' => Array ('type' => 'string'),
+ 'LocalImage' => Array ('type' => 'string'),
+ 'LocalPath' => Array ('type' => 'string'),
+ 'FullUrl' => Array ('type' => 'string'),
),
'Grids' => Array(
// not in use
'Default' => Array(
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Fields' => Array(
- 'Login' => Array ('title' => 'column:la_fld_Username', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter'),
- 'LastName' => Array ('filter_block' => 'grid_like_filter'),
- 'FirstName' => Array ('filter_block' => 'grid_like_filter'),
- 'Email' => Array ('filter_block' => 'grid_like_filter'),
- 'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter'),
- 'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter'),
- 'Modified' => Array('filter_block' => 'grid_date_range_filter'),
- 'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ),
- ),
+ 'Login' => Array ('title' => 'column:la_fld_Username', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter'),
+ 'LastName' => Array ('filter_block' => 'grid_like_filter'),
+ 'FirstName' => Array ('filter_block' => 'grid_like_filter'),
+ 'Email' => Array ('filter_block' => 'grid_like_filter'),
+ 'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter'),
+ 'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter'),
+ 'Modified' => Array('filter_block' => 'grid_date_range_filter'),
+ 'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ),
+ ),
),
// used
'UserSelector' => Array(
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Selector' => 'radio',
'Fields' => Array(
'Login' => Array ('title' => 'column:la_fld_Username', 'data_block' => 'grid_login_td', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('filter_block' => 'grid_like_filter', 'width' => 200, ),
'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter', 'width' => 100, ),
'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter', 'width' => 150, ),
'Modified' => Array('filter_block' => 'grid_date_range_filter', 'width' => 150, ),
'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ),
),
),
// used
'Admins' => Array (
'Icons' => Array(
0 => 'icon16_admin_disabled.png',
1 => 'icon16_admin.png',
2 => 'icon16_admin_disabled.png',
),
'Fields' => Array (
'PortalUserId' => Array ('title' => 'column:la_fld_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 70),
'Login' => Array ('title' => 'column:la_fld_Username', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('filter_block' => 'grid_like_filter', 'width' => 200, ),
'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ),
),
),
// used
'RegularUsers' => Array (
'Icons' => Array(
0 => 'icon16_user_disabled.png',
1 => 'icon16_user.png',
2 => 'icon16_user_pending.png'
),
'Fields' => Array(
'PortalUserId' => Array ('title' => 'column:la_fld_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 70),
'Login' => Array ('title' => 'column:la_fld_Username', 'filter_block' => 'grid_like_filter', 'width' => 150, ),
'FirstName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'LastName' => Array ('filter_block' => 'grid_like_filter', 'width' => 150, ),
'Email' => Array ('filter_block' => 'grid_like_filter', 'width' => 200, ),
'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter', 'width' => 140),
'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ),
'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter', 'width' => 100),
'Modified' => Array ('filter_block' => 'grid_date_range_filter', 'width' => 100),
),
),
),
);
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/cat_dbitem_export_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/cat_dbitem_export_helper.php (revision 14595)
+++ branches/5.2.x/core/units/helpers/cat_dbitem_export_helper.php (revision 14596)
@@ -1,1478 +1,1547 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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!');
define('EXPORT_STEP', 100); // export by 200 items (e.g. links)
define('IMPORT_STEP', 20); // export by 200 items (e.g. links)
define('IMPORT_CHUNK', 10240); // 10240); //30720); //50120); // 5 KB
define('IMPORT_TEMP', 1);
define('IMPORT_LIVE', 2);
class kCatDBItemExportHelper extends kHelper {
var $false = false;
var $cache = Array();
/**
* Allows to find out what items are new in cache
*
* @var Array
*/
var $cacheStatus = Array();
var $cacheTable = '';
var $exportFields = Array();
/**
* Export options
*
* @var Array
*/
var $exportOptions = Array();
/**
* Item beeing currenly exported
*
* @var kCatDBItem
*/
var $curItem = null;
/**
* Dummy category object
*
* @var CategoriesItem
*/
var $dummyCategory = null;
/**
* Pointer to opened file
*
* @var resource
*/
var $filePointer = null;
/**
* Custom fields definition of current item
*
* @var Array
*/
var $customFields = Array();
public function __construct()
{
parent::__construct();
$this->cacheTable = TABLE_PREFIX.'ImportCache';
}
/**
* Returns value from cache if found or false otherwise
*
* @param string $type
* @param int $key
* @return mixed
*/
function getFromCache($type, $key)
{
return getArrayValue($this->cache, $type, $key);
}
/**
* Adds value to be cached
*
* @param string $type
* @param int $key
* @param mixed $value
*/
function addToCache($type, $key, $value, $is_new = true)
{
// if (!isset($this->cache[$type])) $this->cache[$type] = Array();
$this->cache[$type][$key] = $value;
if ($is_new) {
$this->cacheStatus[$type][$key] = true;
}
}
function storeCache($cache_types)
{
$cache_types = explode(',', $cache_types);
$values_sql = '';
foreach ($cache_types as $cache_type) {
$sql_mask = '('.$this->Conn->qstr($cache_type).',%s,%s),';
$cache = getArrayValue($this->cacheStatus, $cache_type);
if (!$cache) $cache = Array();
foreach ($cache as $var_name => $cache_status) {
$var_value = $this->cache[$cache_type][$var_name];
$values_sql .= sprintf($sql_mask, $this->Conn->qstr($var_name), $this->Conn->qstr($var_value) );
}
}
$values_sql = substr($values_sql, 0, -1);
if ($values_sql) {
$sql = 'INSERT INTO '.$this->cacheTable.'(`CacheName`,`VarName`,`VarValue`) VALUES '.$values_sql;
$this->Conn->Query($sql);
}
}
function loadCache()
{
$sql = 'SELECT * FROM '.$this->cacheTable;
$records = $this->Conn->Query($sql);
$this->cache = Array();
foreach ($records as $record) {
$this->addToCache($record['CacheName'], $record['VarName'], $record['VarValue'], false);
}
}
/**
* Fill required fields with dummy values
*
* @param kEvent $event
- * @param kCatDBItem $object
+ * @param kCatDBItem|bool $object
* @param bool $set_status
*/
function fillRequiredFields(&$event, &$object, $set_status = false)
{
- if ($object == $this->false) {
+ if ( $object == $this->false ) {
$object =& $event->getObject();
/* @var $object kCatDBItem */
}
$has_empty = false;
$fields = $object->getFields();
foreach ($fields as $field_name => $field_options) {
- if ($object->isVirtualField($field_name) || !getArrayValue($field_options, 'required') ) continue;
- if ( $object->GetDBField($field_name) ) continue;
+ if ( $object->isVirtualField($field_name) || !$object->isRequired($field_name) ) {
+ continue;
+ }
+
+ if ( $object->GetDBField($field_name) ) {
+ continue;
+ }
$formatter_class = getArrayValue($field_options, 'formatter');
- if ($formatter_class) // not tested
- {
+
+ if ( $formatter_class ) {
+ // not tested
$formatter =& $this->Application->recallObject($formatter_class);
+ /* @var $formatter kFormatter */
+
$sample_value = $formatter->GetSample($field_name, $field_options, $object);
}
$has_empty = true;
$object->SetField($field_name, isset($sample_value) && $sample_value ? $sample_value : 'no value');
}
$object->UpdateFormattersSubFields();
- if ($set_status && $has_empty) {
+ if ( $set_status && $has_empty ) {
$object->SetDBField('Status', 0);
}
}
/**
* Verifies that all user entered export params are correct
*
* @param kEvent $event
+ * @return bool
+ * @access protected
*/
- function verifyOptions(&$event)
+ protected function verifyOptions(&$event)
{
if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid'))
{
$this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 0);
return false;
}
$this->fillRequiredFields($event, $this->false);
$object =& $event->getObject();
- /* @var $object kDBItem */
+ /* @var $object kCatDBItem */
$cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy');
if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field
{
- $object->setRequired('CategorySeparator', true);
+ $object->setRequired('CategorySeparator');
$cross_unique_fields[] = 'CategorySeparator';
}
$ret = $object->Validate();
// check if cross unique fields has no same values
foreach ($cross_unique_fields as $field_index => $field_name)
{
if ($object->GetErrorPseudo($field_name) == 'required') {
continue;
}
$check_fields = $cross_unique_fields;
unset($check_fields[$field_index]);
foreach ($check_fields as $check_field)
{
if ($object->GetDBField($field_name) == $object->GetDBField($check_field))
{
$object->SetError($check_field, 'unique');
}
}
}
if ($event->Special == 'import')
{
$this->exportOptions = $this->loadOptions($event);
$automatic_fields = ($object->GetDBField('FieldTitles') == 1);
$object->setRequired('ExportColumns', !$automatic_fields);
$category_prefix = '__CATEGORY__';
if ( $automatic_fields && ($this->exportOptions['SkipFirstRow']) ) {
$this->openFile($event);
$this->exportOptions['ExportColumns'] = $this->readRecord();
if (!$this->exportOptions['ExportColumns']) {
$this->exportOptions['ExportColumns'] = Array ();
}
$this->closeFile();
// remove additional (non-parseble columns)
foreach ($this->exportOptions['ExportColumns'] as $field_index => $field_name) {
if (!$this->validateField($field_name, $object)) {
unset($this->exportOptions['ExportColumns'][$field_index]);
}
}
$category_prefix = '';
}
// 1. check, that we have column definitions
if (!$this->exportOptions['ExportColumns']) {
$object->setError('ExportColumns', 'required');
$ret = false;
}
else {
// 1.1. check that all required fields are present in imported file
$missing_columns = Array();
$fields = $object->getFields();
foreach ($fields as $field_name => $field_options) {
if ($object->skipField($field_name)) continue;
- if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) {
+ if ( $object->isRequired($field_name) && !in_array($field_name, $this->exportOptions['ExportColumns']) ) {
$missing_columns[] = $field_name;
$object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing');
$ret = false;
}
}
if (!$ret && $this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Missing required for import/export:');
$this->Application->Debugger->dumpVars($missing_columns);
}
}
// 2. check, that we have only mixed category field or only separated category fields
$category_found['mixed'] = false;
$category_found['separated'] = false;
foreach ($this->exportOptions['ExportColumns'] as $import_field) {
if (preg_match('/^'.$category_prefix.'Category(Path|[0-9]+)/', $import_field, $rets)) {
$category_found[$rets[1] == 'Path' ? 'mixed' : 'separated'] = true;
}
}
if ($category_found['mixed'] && $category_found['separated']) {
$object->SetError('ExportColumns', 'unique_category', 'la_error_unique_category_field');
$ret = false;
}
// 3. check, that duplicates check fields are selected & present in imported fields
if ($this->exportOptions['ReplaceDuplicates']) {
if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
$check_fields = Array($object->IDField);
}
else {
$check_fields = $this->exportOptions['DuplicateCheckFields'] ? explode('|', substr($this->exportOptions['DuplicateCheckFields'], 1, -1)) : Array();
$object =& $event->getObject();
$fields = $object->getFields();
$language_id = $this->Application->GetDefaultLanguageId();
foreach ($check_fields as $index => $check_field) {
foreach ($fields as $field_name => $field_options) {
if ($field_name == 'l'.$language_id.'_'.$check_field) {
$check_fields[$index] = 'l'.$language_id.'_'.$check_field;
break;
}
}
}
}
$this->exportOptions['DuplicateCheckFields'] = $check_fields;
if (!$check_fields) {
$object->setError('CheckDuplicatesMethod', 'required');
$ret = false;
}
else {
foreach ($check_fields as $check_field) {
$check_field = preg_replace('/^cust_(.*)/', 'Custom_\\1', $check_field);
if (!in_array($check_field, $this->exportOptions['ExportColumns'])) {
$object->setError('ExportColumns', 'required');
$ret = false;
break;
}
}
}
}
$this->saveOptions($event);
}
return $ret;
}
/**
* Returns filename to read import data from
*
* @return string
*/
function getImportFilename()
{
if ($this->exportOptions['ImportSource'] == 1)
{
$ret = $this->exportOptions['ImportFilename']; // ['name']; commented by Kostja
}
else {
$ret = $this->exportOptions['ImportLocalFilename'];
}
return EXPORT_PATH.'/'.$ret;
}
/**
* Returns filename to write export data to
*
* @return string
*/
function getExportFilename()
{
$extension = $this->getFileExtension();
$filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $this->exportOptions['ExportFilename']) . '.' . $extension;
return EXPORT_PATH . DIRECTORY_SEPARATOR . $filename;
}
/**
* Opens file required for export/import operations
*
* @param kEvent $event
*/
function openFile(&$event)
{
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->CheckFolder(EXPORT_PATH);
if ($event->Special == 'export') {
$write_mode = ($this->exportOptions['start_from'] == 0) ? 'w' : 'a';
$this->filePointer = fopen($this->getExportFilename(), $write_mode);
}
else {
$this->filePointer = fopen($this->getImportFilename(), 'r');
}
// skip UTF-8 BOM Modifier
$first_chars = fread($this->filePointer, 3);
if (bin2hex($first_chars) != 'efbbbf') {
fseek($this->filePointer, 0);
}
}
/**
* Closes opened file
*
*/
function closeFile()
{
fclose($this->filePointer);
}
function getCustomSQL()
{
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
+ /* @var $ml_formatter kMultiLanguage */
$custom_sql = '';
+
foreach ($this->customFields as $custom_id => $custom_name) {
- $custom_sql .= 'custom_data.'.$ml_formatter->LangFieldName('cust_'.$custom_id).' AS cust_'.$custom_name.', ';
+ $custom_sql .= 'custom_data.' . $ml_formatter->LangFieldName('cust_' . $custom_id) . ' AS cust_' . $custom_name . ', ';
}
return substr($custom_sql, 0, -2);
}
function getPlainExportSQL($count_only = false) {
if ($count_only && isset($this->exportOptions['ForceCountSQL'])) {
$sql = $this->exportOptions['ForceCountSQL'];
}
elseif (!$count_only && isset($this->exportOptions['ForceSelectSQL'])) {
$sql = $this->exportOptions['ForceSelectSQL'];
}
else {
$items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List');
+ /* @var $items_list kDBList */
+
$items_list->SetPerPage(-1);
if ($options['export_ids'] != '') {
- $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')');
+ $items_list->addFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')');
}
if ($count_only) {
$sql = $items_list->getCountSQL( $items_list->GetSelectSQL(true,false) );
}
else {
$sql = $items_list->GetSelectSQL();
}
}
if (!$count_only)
{
$sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
}
// else {
// $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
// }
return $sql;
}
function getExportSQL($count_only = false)
{
if (!$this->Application->getUnitOption($this->curItem->Prefix, 'CatalogItem')) {
return $this->GetPlainExportSQL($count_only); // in case this is not a CategoryItem
}
if ($this->exportOptions['export_ids'] === false)
{
// get links from current category & all it's subcategories
$join_clauses = Array();
$custom_sql = $this->getCustomSQL();
if ($custom_sql) {
$custom_table = $this->Application->getUnitOption($this->curItem->Prefix.'-cdata', 'TableName');
$join_clauses[$custom_table.' custom_data'] = 'custom_data.ResourceId = item_table.ResourceId';
}
$join_clauses[TABLE_PREFIX.'CategoryItems ci'] = 'ci.ItemResourceId = item_table.ResourceId';
$join_clauses[TABLE_PREFIX.'Category c'] = 'c.CategoryId = ci.CategoryId';
$sql = 'SELECT item_table.*, ci.CategoryId'.($custom_sql ? ', '.$custom_sql : '').'
FROM '.$this->curItem->TableName.' item_table';
foreach ($join_clauses as $table_name => $join_expression) {
$sql .= ' LEFT JOIN '.$table_name.' ON '.$join_expression;
}
$sql .= ' WHERE ';
if ($this->exportOptions['export_cats_ids'][0] == 0)
{
$sql .= '1';
}
else {
foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
$sql .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
}
$sql = substr($sql, 0, -4);
}
$sql .= ' ORDER BY ci.PrimaryCat DESC'; // NEW
}
else {
// get only selected links
$sql = 'SELECT item_table.*, '.$this->exportOptions['export_cats_ids'][0].' AS CategoryId
FROM '.$this->curItem->TableName.' item_table
WHERE '.$this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
}
if (!$count_only)
{
$sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
}
else {
$sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
}
return $sql;
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function performExport(&$event)
{
$this->exportOptions = $this->loadOptions($event);
$this->exportFields = $this->exportOptions['ExportColumns'];
$this->curItem =& $event->getObject( Array('skip_autoload' => true) );
$this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
$this->openFile($event);
if ($this->exportOptions['start_from'] == 0) // first export step
{
if (!getArrayValue($this->exportOptions, 'IsBaseCategory')) {
$this->exportOptions['IsBaseCategory'] = 0;
}
if ($this->exportOptions['IsBaseCategory'] ) {
$sql = 'SELECT ParentPath
FROM '.TABLE_PREFIX.'Category
WHERE CategoryId = ' . (int)$this->Application->GetVar('m_cat_id');
$parent_path = $this->Conn->GetOne($sql);
$parent_path = explode('|', substr($parent_path, 1, -1));
if ($parent_path && $parent_path[0] == $this->Application->getBaseCategory()) {
array_shift($parent_path);
}
$this->exportOptions['BaseLevel'] = count($parent_path); // level to cut from other categories
}
// 1. export field titles if required
if ($this->exportOptions['IncludeFieldTitles'])
{
$data_array = Array();
foreach ($this->exportFields as $export_field)
{
$data_array = array_merge($data_array, $this->getFieldCaption($export_field));
}
$this->writeRecord($data_array);
}
$this->exportOptions['total_records'] = $this->Conn->GetOne( $this->getExportSQL(true) );
}
// 2. export data
$records = $this->Conn->Query( $this->getExportSQL() );
$records_exported = 0;
foreach ($records as $record_info) {
$this->curItem->LoadFromHash($record_info);
$data_array = Array();
foreach ($this->exportFields as $export_field)
{
$data_array = array_merge($data_array, $this->getFieldValue($export_field) );
}
$this->writeRecord($data_array);
$records_exported++;
}
$this->closeFile();
$this->exportOptions['start_from'] += $records_exported;
$this->saveOptions($event);
return $this->exportOptions;
}
function getItemFields()
{
// just in case dummy user selected automtic mode & moved columns too :(
$src_options = $this->curItem->GetFieldOption('ExportColumns', 'options');
$dst_options = $this->curItem->GetFieldOption('AvailableColumns', 'options');
return array_merge($dst_options, $src_options);
}
/**
* Checks if field really belongs to importable field list
*
* @param string $field_name
* @param kCatDBItem $object
* @return bool
*/
function validateField($field_name, &$object)
{
// 1. convert custom field
$field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name);
- // 2. convert category field (mixed version & serparated version)
+ // 2. convert category field (mixed version & separated version)
$field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name);
$valid_fields = $object->getPossibleExportColumns();
return isset($valid_fields[$field_name]) || isset($valid_fields['__VIRTUAL__'.$field_name]);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function performImport(&$event)
{
if (!$this->exportOptions) {
// load import options in case if not previously loaded in verification function
$this->exportOptions = $this->loadOptions($event);
}
$backup_category_id = $this->Application->GetVar('m_cat_id');
$this->Application->SetVar('m_cat_id', (int)$this->Application->RecallVar('ImportCategory') );
$this->openFile($event);
$bytes_imported = 0;
if ($this->exportOptions['start_from'] == 0) // first export step
{
// 1st time run
if ($this->exportOptions['SkipFirstRow']) {
$this->readRecord();
$this->exportOptions['start_from'] = ftell($this->filePointer);
$bytes_imported = ftell($this->filePointer);
}
$current_category_id = $this->Application->GetVar('m_cat_id');
if ($current_category_id > 0) {
$sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$current_category_id;
$this->exportOptions['ImportCategoryPath'] = $this->Conn->GetOne($sql);
}
else {
$this->exportOptions['ImportCategoryPath'] = '';
}
$this->exportOptions['total_records'] = filesize($this->getImportFilename());
}
else {
$this->loadCache();
}
$this->exportFields = $this->exportOptions['ExportColumns'];
$this->addToCache('category_parent_path', $this->Application->GetVar('m_cat_id'), $this->exportOptions['ImportCategoryPath']);
// 2. import data
$this->dummyCategory =& $this->Application->recallObject('c.-tmpitem', 'c', Array('skip_autoload' => true));
fseek($this->filePointer, $this->exportOptions['start_from']);
$items_processed = 0;
while (($bytes_imported < IMPORT_CHUNK && $items_processed < IMPORT_STEP) && !feof($this->filePointer)) {
$data = $this->readRecord();
if ($data) {
if ($this->exportOptions['ReplaceDuplicates']) {
// set fields used as keys for replace duplicates code
$this->resetImportObject($event, IMPORT_TEMP, $data);
}
$this->processCurrentItem($event, $data);
}
$bytes_imported = ftell($this->filePointer) - $this->exportOptions['start_from'];
$items_processed++;
}
$this->closeFile();
$this->Application->SetVar('m_cat_id', $backup_category_id);
$this->exportOptions['start_from'] += $bytes_imported;
$this->storeCache('new_ids');
$this->saveOptions($event);
if ($this->exportOptions['start_from'] == $this->exportOptions['total_records']) {
$this->Conn->Query('TRUNCATE TABLE '.$this->cacheTable);
}
return $this->exportOptions;
}
function setCurrentID()
{
$this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) );
}
- function setFieldValue($field_index, $value)
+ /**
+ * Sets value of import/export object
+ * @param int $field_index
+ * @param mixed $value
+ * @return void
+ * @access protected
+ */
+ protected function setFieldValue($field_index, $value)
{
- if (empty($value)) {
+ if ( empty($value) ) {
$value = null;
}
$field_name = getArrayValue($this->exportFields, $field_index);
- if ($field_name == 'ResourceId') {
- return false;
+ if ( $field_name == 'ResourceId' ) {
+ return ;
}
- if (substr($field_name, 0, 7) == 'Custom_') {
- $field_name = 'cust_'.substr($field_name, 7);
+ if ( substr($field_name, 0, 7) == 'Custom_' ) {
+ $field_name = 'cust_' . substr($field_name, 7);
$this->curItem->SetField($field_name, $value);
}
- elseif ($field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath') {
- $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array();
+ elseif ( $field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath' ) {
+ $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array ();
}
- elseif (substr($field_name, 0, 8) == 'Category') {
- $this->curItem->CategoryPath[ (int)substr($field_name, 8) - 1 ] = $value;
+ elseif ( substr($field_name, 0, 8) == 'Category' ) {
+ $this->curItem->CategoryPath[(int)substr($field_name, 8) - 1] = $value;
}
- elseif (substr($field_name, 0, 20) == '__CATEGORY__Category') {
- $this->curItem->CategoryPath[ (int)substr($field_name, 20) ] = $value;
+ elseif ( substr($field_name, 0, 20) == '__CATEGORY__Category' ) {
+ $this->curItem->CategoryPath[(int)substr($field_name, 20)] = $value;
}
- elseif (substr($field_name, 0, 11) == '__VIRTUAL__') {
+ elseif ( substr($field_name, 0, 11) == '__VIRTUAL__' ) {
$field_name = substr($field_name, 11);
$this->curItem->SetField($field_name, $value);
}
else {
$this->curItem->SetField($field_name, $value);
}
if ( $this->curItem->GetErrorPseudo($field_name) ) {
$this->curItem->SetDBField($field_name, null);
$this->curItem->RemoveError($field_name);
}
}
+ /**
+ * Resets import object
+ *
+ * @param kEvent $event
+ * @param int $object_type
+ * @param Array $record_data
+ * @return void
+ */
function resetImportObject(&$event, $object_type, $record_data = null)
{
switch ($object_type) {
case IMPORT_TEMP:
$this->curItem =& $event->getObject( Array('skip_autoload' => true) );
break;
case IMPORT_LIVE:
$this->curItem =& $this->Application->recallObject($event->Prefix.'.-tmpitem'.$event->Special, $event->Prefix, Array('skip_autoload' => true));
break;
}
$this->curItem->Clear();
$this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if (isset($record_data)) {
$this->setImportData($record_data);
}
}
function setImportData($record_data)
{
foreach ($record_data as $field_index => $field_value) {
$this->setFieldValue($field_index, $field_value);
}
$this->setCurrentID();
}
function getItemCategory()
{
static $lang_prefix = null;
$backup_category_id = $this->Application->GetVar('m_cat_id');
$category_id = $this->getFromCache('category_names', implode(':', $this->curItem->CategoryPath));
if ($category_id) {
$this->Application->SetVar('m_cat_id', $category_id);
return $category_id;
}
if (is_null($lang_prefix)) {
$lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
}
foreach ($this->curItem->CategoryPath as $category_index => $category_name) {
if (!$category_name) continue;
$category_key = crc32( implode(':', array_slice($this->curItem->CategoryPath, 0, $category_index + 1) ) );
$category_id = $this->getFromCache('category_names', $category_key);
if ($category_id === false) {
// get parent category path to search only in it
$current_category_id = $this->Application->GetVar('m_cat_id');
// $parent_path = $this->getParentPath($current_category_id);
// get category id from database by name
$sql = 'SELECT CategoryId
FROM '.TABLE_PREFIX.'Category
WHERE ('.$lang_prefix.'Name = '.$this->Conn->qstr($category_name).') AND (ParentId = '.(int)$current_category_id.')';
$category_id = $this->Conn->GetOne($sql);
if ($category_id === false) {
// category not in db -> create
$category_fields = Array( $lang_prefix.'Name' => $category_name, $lang_prefix.'Description' => $category_name,
'Status' => STATUS_ACTIVE, 'ParentId' => $current_category_id, 'AutomaticFilename' => 1
);
$this->dummyCategory->SetDBFieldsFromHash($category_fields);
if ($this->dummyCategory->Create()) {
$category_id = $this->dummyCategory->GetID();
$this->addToCache('category_parent_path', $category_id, $this->dummyCategory->GetDBField('ParentPath'));
$this->addToCache('category_names', $category_key, $category_id);
}
}
else {
$this->addToCache('category_names', $category_key, $category_id);
}
}
if ($category_id) {
$this->Application->SetVar('m_cat_id', $category_id);
}
}
if (!$this->curItem->CategoryPath) {
$category_id = $backup_category_id;
}
return $category_id;
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function processCurrentItem(&$event, $record_data)
{
$save_method = 'Create';
$load_keys = Array();
// create/update categories
$backup_category_id = $this->Application->GetVar('m_cat_id');
// perform replace duplicates code
if ($this->exportOptions['ReplaceDuplicates']) {
// get replace keys first, then reset current item to empty one
$category_id = $this->getItemCategory();
if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
if ($this->curItem->GetID()) {
$load_keys = Array($this->curItem->IDField => $this->curItem->GetID());
}
}
else {
$key_fields = $this->exportOptions['DuplicateCheckFields'];
foreach ($key_fields as $key_field) {
$load_keys[$key_field] = $this->curItem->GetDBField($key_field);
}
}
$this->resetImportObject($event, IMPORT_LIVE);
if (count($load_keys)) {
$where_clause = '';
$language_id = (int)$this->Application->GetVar('m_lang');
if (!$language_id) {
$language_id = 1;
}
foreach ($load_keys as $field_name => $field_value) {
if (preg_match('/^cust_(.*)/', $field_name, $regs)) {
$custom_id = array_search($regs[1], $this->customFields);
$field_name = 'l'.$language_id.'_cust_'.$custom_id;
$where_clause .= '(custom_data.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
}
else {
$where_clause .= '(item_table.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
}
}
$where_clause = substr($where_clause, 0, -5);
$item_id = $this->getFromCache('new_ids', crc32($where_clause));
if (!$item_id) {
if ($this->exportOptions['CheckDuplicatesMethod'] == 2) {
// by other fields
$parent_path = $this->getParentPath($category_id);
$where_clause = '(c.ParentPath LIKE "'.$parent_path.'%") AND '.$where_clause;
}
$cdata_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$sql = 'SELECT '.$this->curItem->IDField.'
FROM '.$this->curItem->TableName.' item_table
LEFT JOIN '.$cdata_table.' custom_data ON custom_data.ResourceId = item_table.ResourceId
LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId
LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
WHERE '.$where_clause;
$item_id = $this->Conn->GetOne($sql);
}
$save_method = $item_id && $this->curItem->Load($item_id) ? 'Update' : 'Create';
if ($save_method == 'Update') {
// replace id from csv file with found id (only when ID is found in cvs file)
if (in_array($this->curItem->IDField, $this->exportFields)) {
$record_data[ array_search($this->curItem->IDField, $this->exportFields) ] = $item_id;
}
}
}
$this->setImportData($record_data);
}
else {
$this->resetImportObject($event, IMPORT_LIVE, $record_data);
$category_id = $this->getItemCategory();
}
// create main record
if ($save_method == 'Create') {
$this->fillRequiredFields($this->false, $this->curItem, true);
}
// $sql_start = microtime(true);
if (!$this->curItem->$save_method()) {
$this->Application->SetVar('m_cat_id', $backup_category_id);
return false;
}
// $sql_end = microtime(true);
// $this->saveLog('SQL ['.$save_method.'] Time: '.($sql_end - $sql_start).'s');
if ($load_keys && ($save_method == 'Create') && $this->exportOptions['ReplaceDuplicates']) {
// map new id to old id
$this->addToCache('new_ids', crc32($where_clause), $this->curItem->GetID() );
}
// assign item to categories
$this->curItem->assignToCategory($category_id, false);
$this->Application->SetVar('m_cat_id', $backup_category_id);
return true;
}
/*function saveLog($msg)
{
static $first_time = true;
$fp = fopen((defined('RESTRICTED') ? RESTRICTED : FULL_PATH) . '/sqls.log', $first_time ? 'w' : 'a');
fwrite($fp, $msg."\n");
fclose($fp);
$first_time = false;
}*/
/**
* Returns category parent path, if possible, then from cache
*
* @param int $category_id
* @return string
*/
function getParentPath($category_id)
{
$parent_path = $this->getFromCache('category_parent_path', $category_id);
if ($parent_path === false) {
$sql = 'SELECT ParentPath
FROM '.TABLE_PREFIX.'Category
WHERE CategoryId = '.$category_id;
$parent_path = $this->Conn->GetOne($sql);
$this->addToCache('category_parent_path', $category_id, $parent_path);
}
return $parent_path;
}
function getFileExtension()
{
return $this->exportOptions['ExportFormat'] == 1 ? 'csv' : 'xml';
}
function getLineSeparator($option = 'LineEndings')
{
return $this->exportOptions[$option] == 1 ? "\r\n" : "\n";
}
/**
* Returns field caption for any exported field
*
* @param string $field
* @return string
*/
function getFieldCaption($field)
{
if (substr($field, 0, 10) == '__CUSTOM__')
{
$ret = 'Custom_'.substr($field, 10, strlen($field) );
}
elseif (substr($field, 0, 12) == '__CATEGORY__')
{
return $this->getCategoryTitle();
}
elseif (substr($field, 0, 11) == '__VIRTUAL__') {
$ret = substr($field, 11);
}
else
{
$ret = $field;
}
return Array($ret);
}
/**
* Returns requested field value (including custom fields and category fields)
*
* @param string $field
* @return string
*/
function getFieldValue($field)
{
if (substr($field, 0, 10) == '__CUSTOM__') {
$field = 'cust_'.substr($field, 10, strlen($field));
$ret = $this->curItem->GetField($field);
}
elseif (substr($field, 0, 12) == '__CATEGORY__') {
return $this->getCategoryPath();
}
elseif (substr($field, 0, 11) == '__VIRTUAL__') {
$field = substr($field, 11);
$ret = $this->curItem->GetField($field);
}
else
{
$ret = $this->curItem->GetField($field);
}
$ret = str_replace("\r\n", $this->getLineSeparator('LineEndingsInside'), $ret);
return Array($ret);
}
/**
* Returns category field(-s) caption based on export mode
*
* @return string
*/
function getCategoryTitle()
{
// category path in separated fields
$category_count = $this->getMaxCategoryLevel();
if ($this->exportOptions['CategoryFormat'] == 1)
{
// category path in one field
return $category_count ? Array('CategoryPath') : Array();
}
else
{
$i = 0;
$ret = Array();
while ($i < $category_count) {
$ret[] = 'Category'.($i + 1);
$i++;
}
return $ret;
}
}
/**
* Returns category path in required format for current link
*
* @return string
*/
function getCategoryPath()
{
$category_id = $this->curItem->GetDBField('CategoryId');
$category_path = $this->getFromCache('category_path', $category_id);
- if (!$category_path)
- {
+
+ if ( !$category_path ) {
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
- $sql = 'SELECT '.$ml_formatter->LangFieldName('CachedNavbar').'
- FROM '.TABLE_PREFIX.'Category
- WHERE CategoryId = '.$category_id;
+ /* @var $ml_formatter kMultiLanguage */
+
+ $sql = 'SELECT ' . $ml_formatter->LangFieldName('CachedNavbar') . '
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $category_id;
$category_path = $this->Conn->GetOne($sql);
- $category_path = $category_path ? explode('&|&', $category_path) : Array();
- if ($category_path && strtolower($category_path[0]) == 'content') {
+ $category_path = $category_path ? explode('&|&', $category_path) : Array ();
+
+ if ( $category_path && strtolower($category_path[0]) == 'content' ) {
array_shift($category_path);
}
- if ($this->exportOptions['IsBaseCategory']) {
+ if ( $this->exportOptions['IsBaseCategory'] ) {
$i = $this->exportOptions['BaseLevel'];
- while ($i > 0) {
+ while ( $i > 0 ) {
array_shift($category_path);
$i--;
}
}
$category_count = $this->getMaxCategoryLevel();
- if ($this->exportOptions['CategoryFormat'] == 1) {
+
+ if ( $this->exportOptions['CategoryFormat'] == 1 ) {
// category path in single field
- $category_path = $category_count ? Array( implode($this->exportOptions['CategorySeparator'], $category_path) ) : Array();
+ $category_path = $category_count ? Array (implode($this->exportOptions['CategorySeparator'], $category_path)) : Array ();
}
else {
// category path in separated fields
$levels_used = count($category_path);
- if ($levels_used < $category_count)
- {
+
+ if ( $levels_used < $category_count ) {
$i = 0;
- while ($i < $category_count - $levels_used) {
+ while ( $i < $category_count - $levels_used ) {
$category_path[] = '';
$i++;
}
}
}
$this->addToCache('category_path', $category_id, $category_path);
}
return $category_path;
}
/**
* Get maximal category deep level from links beeing exported
*
* @return int
*/
function getMaxCategoryLevel()
{
static $max_level = -1;
if ($max_level != -1)
{
return $max_level;
}
$sql = 'SELECT IF(c.CategoryId IS NULL, 0, MAX( LENGTH(c.ParentPath) - LENGTH( REPLACE(c.ParentPath, "|", "") ) - 1 ))
FROM '.$this->curItem->TableName.' item_table
LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON item_table.ResourceId = ci.ItemResourceId
LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
WHERE (ci.PrimaryCat = 1) AND ';
$where_clause = '';
if ($this->exportOptions['export_ids'] === false) {
// get links from current category & all it's subcategories
if ($this->exportOptions['export_cats_ids'][0] == 0) {
$where_clause = 1;
}
else {
foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
$where_clause .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
}
$where_clause = substr($where_clause, 0, -4);
}
}
else {
// get only selected links
$where_clause = $this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
}
$max_level = $this->Conn->GetOne($sql.'('.$where_clause.')');
if ($this->exportOptions['IsBaseCategory'] ) {
$max_level -= $this->exportOptions['BaseLevel'];
}
return $max_level;
}
/**
* Saves one record to export file
*
* @param Array $fields_hash
*/
function writeRecord($fields_hash)
{
kUtil::fputcsv($this->filePointer, $fields_hash, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy'], $this->getLineSeparator() );
}
function readRecord()
{
return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']);
}
+ /**
+ * Saves import/export options
+ *
+ * @param kEvent $event
+ * @param Array $options
+ * @return void
+ */
function saveOptions(&$event, $options = null)
{
- if (!isset($options)) {
+ if ( !isset($options) ) {
$options = $this->exportOptions;
}
- $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) );
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_options', serialize($options));
}
+ /**
+ * Loads import/export options
+ *
+ * @param kEvent $event
+ * @return void
+ */
function loadOptions(&$event)
{
- return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options'));
+ return unserialize( $this->Application->RecallVar($event->getPrefixSpecial() . '_options') );
}
/**
* Sets correct available & export fields
*
* @param kEvent $event
*/
function prepareExportColumns(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
+ /* @var $object kCatDBItem */
if ( !$object->isField('ExportColumns') ) {
// import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported
return ;
}
$available_columns = Array();
if ($this->Application->getUnitOption($event->Prefix, 'CatalogItem')) {
// category field (mixed)
$available_columns['__CATEGORY__CategoryPath'] = 'CategoryPath';
if ($event->Special == 'import') {
// category field (separated fields)
$max_level = $this->Application->ConfigValue('MaxImportCategoryLevels');
$i = 0;
while ($i < $max_level) {
$available_columns['__CATEGORY__Category'.($i + 1)] = 'Category'.($i + 1);
$i++;
}
}
}
// db fields
$fields = $object->getFields();
foreach ($fields as $field_name => $field_options) {
if ( !$object->skipField($field_name) ) {
- $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : '');
+ $available_columns[$field_name] = $field_name.( $object->isRequired($field_name) ? '*' : '');
}
}
$handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
+ /* @var $handler kDBEventHandler */
+
$available_columns = array_merge($available_columns, $handler->getCustomExportColumns($event));
// custom fields
$custom_fields = $object->getCustomFields();
foreach ($custom_fields as $custom_id => $custom_name)
{
$available_columns['__CUSTOM__'.$custom_name] = $custom_name;
}
// columns already in use
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info)
{
list($item_id, $field_values) = each($items_info);
$export_keys = $field_values['ExportColumns'];
$export_keys = $export_keys ? explode('|', substr($export_keys, 1, -1) ) : Array();
}
else {
$export_keys = Array();
}
$export_columns = Array();
foreach ($export_keys as $field_key)
{
$field_name = $this->getExportField($field_key);
$export_columns[$field_key] = $field_name;
unset($available_columns[$field_key]);
}
$options = $object->GetFieldOptions('ExportColumns');
$options['options'] = $export_columns;
$object->SetFieldOptions('ExportColumns', $options);
$options = $object->GetFieldOptions('AvailableColumns');
$options['options'] = $available_columns;
$object->SetFieldOptions('AvailableColumns', $options);
$this->updateImportFiles($event);
$this->PrepareExportPresets($event);
}
+ /**
+ * Prepares export presets
+ *
+ * @param kEvent $event
+ * @return void
+ */
function PrepareExportPresets(&$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
- $options = $object->GetFieldOptions('ExportPresets');
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
+ $options = $object->GetFieldOptions('ExportPresets');
$export_settings = $this->Application->RecallPersistentVar('export_settings');
- if (!$export_settings) return ;
- $export_settings = unserialize($export_settings);
- if (!isset($export_settings[$event->Prefix])) return ;
+ if ( !$export_settings ) {
+ return;
+ }
+
+ $export_settings = unserialize($export_settings);
+ if ( !isset($export_settings[$event->Prefix]) ) {
+ return;
+ }
- $export_presets = array(''=>'');
+ $export_presets = array ('' => '');
+
foreach ($export_settings[$event->Prefix] as $key => $val) {
$export_presets[implode('|', $val['ExportColumns'])] = $key;
}
$options['options'] = $export_presets;
$object->SetFieldOptions('ExportPresets', $options);
}
function getExportField($field_key)
{
$prepends = Array('__CUSTOM__', '__CATEGORY__');
foreach ($prepends as $prepend)
{
if (substr($field_key, 0, strlen($prepend) ) == $prepend)
{
$field_key = substr($field_key, strlen($prepend), strlen($field_key) );
break;
}
}
return $field_key;
}
/**
* Updates uploaded files list
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function updateImportFiles(&$event)
+ protected function updateImportFiles(&$event)
{
- if ($event->Special != 'import') {
- return false;
+ if ( $event->Special != 'import' ) {
+ return ;
}
$object =& $event->getObject();
- $import_filenames = Array();
+ $import_filenames = Array ();
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->CheckFolder(EXPORT_PATH);
- if ($folder_handle = opendir(EXPORT_PATH)) {
- while (false !== ($file = readdir($folder_handle))) {
- if (is_dir(EXPORT_PATH.'/'.$file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH.'/'.$file) == 0) continue;
+ if ( $folder_handle = opendir(EXPORT_PATH) ) {
+ while ( false !== ($file = readdir($folder_handle)) ) {
+ if ( is_dir(EXPORT_PATH . '/' . $file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH . '/' . $file) == 0 ) {
+ continue;
+ }
- $file_size = kUtil::formatSize( filesize(EXPORT_PATH.'/'.$file) );
- $import_filenames[$file] = $file.' ('.$file_size.')';
+ $file_size = kUtil::formatSize(filesize(EXPORT_PATH . '/' . $file));
+ $import_filenames[$file] = $file . ' (' . $file_size . ')';
}
closedir($folder_handle);
}
$options = $object->GetFieldOptions('ImportLocalFilename');
$options['options'] = $import_filenames;
$object->SetFieldOptions('ImportLocalFilename', $options);
}
/**
* Returns module folder
*
* @param kEvent $event
* @return string
*/
function getModuleName(&$event)
{
$module_path = $this->Application->getUnitOption($event->Prefix, 'ModuleFolder') . '/';
$module_name = $this->Application->findModule('Path', $module_path, 'Name');
return mb_strtolower($module_name);
}
/**
* Export form validation & processing
*
* @param kEvent $event
*/
function OnExportBegin(&$event)
{
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if (!$items_info)
- {
- $items_info = unserialize( $this->Application->RecallVar($event->getPrefixSpecial().'_ItemsInfo') );
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+
+ if ( !$items_info ) {
+ $items_info = unserialize($this->Application->RecallVar($event->getPrefixSpecial() . '_ItemsInfo'));
$this->Application->SetVar($event->getPrefixSpecial(true), $items_info);
}
list($item_id, $field_values) = each($items_info);
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
+
$object->SetFieldsFromHash($field_values);
$field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
$object->setID($item_id);
$this->setRequiredFields($event);
// save export/import options
- if ($event->Special == 'export')
- {
- $export_ids = $this->Application->RecallVar($event->Prefix.'_export_ids');
- $export_cats_ids = $this->Application->RecallVar($event->Prefix.'_export_cats_ids');
+ if ( $event->Special == 'export' ) {
+ $export_ids = $this->Application->RecallVar($event->Prefix . '_export_ids');
+ $export_cats_ids = $this->Application->RecallVar($event->Prefix . '_export_cats_ids');
// used for multistep export
$field_values['export_ids'] = $export_ids ? explode(',', $export_ids) : false;
- $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array( $this->Application->GetVar('m_cat_id') );
+ $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array ($this->Application->GetVar('m_cat_id'));
}
$field_values['ExportColumns'] = $field_values['ExportColumns'] ? explode('|', substr($field_values['ExportColumns'], 1, -1) ) : Array();
$field_values['start_from'] = 0;
- $this->Application->HandleEvent($nevent, $event->Prefix.':OnBeforeExportBegin', array('options'=>$field_values));
+ $nevent = new kEvent($event->Prefix . ':OnBeforeExportBegin');
+ $nevent->setEventParam('options', $field_values);
+ $this->Application->HandleEvent($nevent);
$field_values = $nevent->getEventParam('options');
$this->saveOptions($event, $field_values);
- if( $this->verifyOptions($event) )
- {
- if ($this->_getExportSavePreset($object)) {
+ if ( $this->verifyOptions($event) ) {
+ if ( $this->_getExportSavePreset($object) ) {
$name = $object->GetDBField('ExportPresetName');
$export_settings = $this->Application->RecallPersistentVar('export_settings');
- $export_settings = $export_settings ? unserialize($export_settings) : array();
+ $export_settings = $export_settings ? unserialize($export_settings) : array ();
$export_settings[$event->Prefix][$name] = $field_values;
$this->Application->StorePersistentVar('export_settings', serialize($export_settings));
}
$progress_t = $this->Application->RecallVar('export_progress_t');
- if ($progress_t) {
+ if ( $progress_t ) {
$this->Application->RemoveVar('export_progress_t');
}
else {
- $progress_t = $this->getModuleName($event).'/'.$event->Special.'_progress';
+ $progress_t = $this->getModuleName($event) . '/' . $event->Special . '_progress';
}
$event->redirect = $progress_t;
- if ($event->Special == 'import') {
+ if ( $event->Special == 'import' ) {
$import_category = (int)$this->Application->RecallVar('ImportCategory');
// in future could use module root category if import category will be unavailable :)
$event->SetRedirectParam('m_cat_id', $import_category); // for template permission checking
$this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking
}
}
- else
- {
+ else {
// make uploaded file local & change source selection
$filename = getArrayValue($field_values, 'ImportFilename');
- if ($filename) {
+
+ if ( $filename ) {
$this->updateImportFiles($event);
$object->SetDBField('ImportSource', 2);
$field_values['ImportSource'] = 2;
$object->SetDBField('ImportLocalFilename', $filename);
$field_values['ImportLocalFilename'] = $filename;
$this->saveOptions($event, $field_values);
}
$event->status = kEvent::erFAIL;
$event->redirect = false;
}
}
/**
* Returns export save preset name, when used at all
*
* @param kDBItem $object
* @return string
*/
function _getExportSavePreset(&$object)
{
if ( !$object->isField('ExportSavePreset') ) {
return '';
}
return $object->GetDBField('ExportSavePreset');
}
/**
* set required fields based on import or export params
*
* @param kEvent $event
*/
function setRequiredFields(&$event)
{
$required_fields['common'] = Array('FieldsSeparatedBy', 'LineEndings', 'CategoryFormat');
$required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns');
$object =& $event->getObject();
+ /* @var $object kDBItem */
+
if ($this->_getExportSavePreset($object)) {
$required_fields['export'][] = 'ExportPresetName';
}
$required_fields['import'] = Array('FieldTitles', 'ImportSource', 'CheckDuplicatesMethod'); // ImportFilename, ImportLocalFilename
if ($event->Special == 'import')
{
$import_source = Array(1 => 'ImportFilename', 2 => 'ImportLocalFilename');
$used_field = $import_source[ $object->GetDBField('ImportSource') ];
$required_fields[$event->Special][] = $used_field;
$object->SetFieldOption($used_field, 'error_field', 'ImportSource');
if ($object->GetDBField('FieldTitles') == 2) $required_fields[$event->Special][] = 'ExportColumns'; // manual field titles
}
$required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]);
- foreach ($required_fields as $required_field) {
- $object->setRequired($required_field, true);
- }
+ $object->setRequired($required_fields);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/configuration/configuration_tag_processor.php
===================================================================
--- branches/5.2.x/core/units/configuration/configuration_tag_processor.php (revision 14595)
+++ branches/5.2.x/core/units/configuration/configuration_tag_processor.php (revision 14596)
@@ -1,261 +1,261 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 ConfigurationTagProcessor extends kDBTagProcessor {
public function __construct()
{
parent::__construct();
$this->Application->LinkVar('module_key');
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList($params)
{
$list =& $this->GetList($params);
$id_field = $this->Application->getUnitOption($this->Prefix,'IDField');
$list->Query();
$o = '';
$list->GoFirst();
$block_params=$this->prepareTagParams($params);
$block_params['pass_params'] = 'true';
$block_params['IdField'] = $list->IDField;
$prev_heading = '';
$next_block = $params['full_block'];
$list->groupRecords('Heading');
$field_values = $this->Application->GetVar( $this->getPrefixSpecial(true) );
while (!$list->EOL()) {
$this->Application->SetVar( $this->getPrefixSpecial() . '_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
// using 2 blocks for drawing o row in case if current & next record titles match
$next_record =& $list->getCurrentRecord(1);
$next_item_prompt = $next_record !== false ? $next_record['Prompt'] : '';
$this_item_prompt = $list->GetDBField('Prompt');
if ($next_item_prompt == $this_item_prompt) {
$curr_block = $params['half_block1'];
$next_block = $params['half_block2'];
} else {
$curr_block = $next_block;
$next_block = $params['full_block'];
}
$variable_name = $list->GetDBField('VariableName');
// allows to override value part of block
if ($this->Application->ParserBlockFound('cf_' . $variable_name . '_value')) {
$block_params['value_render_as'] = 'cf_' . $variable_name . '_value';
}
else {
$block_params['value_render_as'] = $params['value_render_as'];
}
// allow to completely override whole block
if ($this->Application->ParserBlockFound('cf_' . $variable_name . '_element')) {
$block_params['name'] = 'cf_' . $variable_name . '_element';
$block_params['original_render_as'] = $curr_block;
}
else {
$block_params['name'] = $curr_block;
$block_params['original_render_as'] = $curr_block;
}
$block_params['show_heading'] = ($prev_heading != $list->GetDBField('Heading') ) ? 1 : 0;
// set values from submit if any
if ($field_values) {
$list->SetDBField('VariableValue', $field_values[ $list->GetID() ]['VariableValue']);
}
$list->SetDBField('DirectOptions', '');
$o.= $this->Application->ParseBlock($block_params);
$prev_heading = $list->GetDBField('Heading');
$list->GoNext();
}
$this->Application->RemoveVar('ModuleRootCategory');
$this->Application->SetVar($this->getPrefixSpecial() . '_id', '');
return $o;
}
function getModuleItemName()
{
$module = $this->Application->GetVar('module');
$table = $this->Application->getUnitOption('confs', 'TableName');
$sql = 'SELECT ConfigHeader
FROM '.$table.'
WHERE ModuleName = '.$this->Conn->qstr($module);
return $this->Conn->GetOne($sql);
}
function PrintConfList($params)
{
$list =& $this->GetList($params);
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$list->Query();
$o = '';
$list->GoFirst();
$tmp_row = Array();
while (!$list->EOL()) {
$rec = $list->getCurrentRecord();
$tmp_row[0][$rec['VariableName']] = $rec['VariableValue'];
$tmp_row[0][$rec['VariableName'].'_prompt'] = $rec['Prompt'];
$list->GoNext();
}
$list->Records = $tmp_row;
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['module_key'] = $this->Application->GetVar('module_key');
$block_params['module_item'] = $this->getModuleItemName();
$list->GoFirst();
return $this->Application->ParseBlock($block_params);
}
function ShowRelevance($params)
{
return $this->Application->GetVar('module_key') != '_';
}
function ConfigValue($params)
{
return $this->Application->ConfigValue($params['name']);
}
function IsRequired($params)
{
$object =& $this->getObject($params);;
/* @var $object kDBList */
$field_options = $object->GetDBField('Validation');
$field_options = $field_options ? unserialize($field_options) : Array ();
- return array_key_exists('required', $field_options) && $field_options['required'];
+ return isset($field_options['required']) && $field_options['required'];
}
function Error($params)
{
$object =& $this->getObject($params);
/* @var $object kDBList */
$field = $object->GetDBField($params['id_field']);
$errors = $this->Application->GetVar('errors_' . $this->getPrefixSpecial(), Array ());
return array_key_exists($field, $errors) ? $errors[$field] : '';
}
/**
* Allows to show category path of selected module
*
* @param Array $params
* @return string
*/
function CategoryPath($params)
{
if (!isset($params['cat_id'])) {
$params['cat_id'] = $this->ModuleRootCategory( Array() );
}
return $this->Application->ProcessParsedTag('c', 'CategoryPath', $params);
}
/**
* Shows edit warning in case if module root category changed but not saved
*
* @param Array $params
* @return string
*/
function SaveWarning($params)
{
$temp_category_id = $this->Application->RecallVar('ModuleRootCategory');
if ($temp_category_id !== false) {
return $this->Application->ParseBlock($params);
}
return '';
}
function ModuleRootCategory($params)
{
$category_id = $this->Application->RecallVar('ModuleRootCategory');
if ($category_id === false) {
$category_id = $this->Application->findModule('Name', $this->Application->GetVar('module'), 'RootCat');
}
return $category_id;
}
/**
* Returns variable ID by it's name (used on search relevance configuration screen)
*
* @param Array $params
* @return int
*/
function GetVariableID($params)
{
static $cached_ids = Array ();
$var_name = $params['name'];
if (!isset($cached_ids[$var_name])) {
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT '.$id_field.'
FROM '.$table_name.'
WHERE VariableName = '.$this->Conn->qstr($params['name']);
$cached_ids[$var_name] = $this->Conn->GetOne($sql);
}
return $cached_ids[$var_name];
}
function GetVariableSection($params)
{
static $cached_sections = Array ();
$var_name = $params['name'];
if (!isset($cached_sections[$var_name])) {
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT Section
FROM '.$table_name.'
WHERE VariableName = '.$this->Conn->qstr($params['name']);
$cached_sections[$var_name] = $this->Conn->GetOne($sql);
}
return $cached_sections[$var_name];
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/forms/forms/forms_eh.php
===================================================================
--- branches/5.2.x/core/units/forms/forms/forms_eh.php (revision 14595)
+++ branches/5.2.x/core/units/forms/forms/forms_eh.php (revision 14596)
@@ -1,585 +1,622 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 FormsEventHandler extends kDBEventHandler {
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
// user can view any form on front-end
'OnItemBuild' => Array('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function OnCreateSubmissionNodes(&$event)
{
if (defined('IS_INSTALL') && IS_INSTALL) {
// skip any processing, because Forms table doesn't exists until install is finished
return ;
}
$forms = $this->getForms();
if (!$forms) {
return ;
}
$form_subsection = Array(
'parent' => 'in-portal:forms',
'icon' => 'form_submission',
'label' => '',
'url' => Array('t' => 'submissions/submissions_list', 'pass' => 'm,form'),
'permissions' => Array('view', 'add', 'edit', 'delete'),
'priority' => 1,
'type' => stTREE,
);
$priority = 1;
$sections = $this->Application->getUnitOption($event->Prefix, 'Sections');
foreach ($forms as $form_id => $form_name) {
$this->Application->Phrases->AddCachedPhrase('form_sub_label_'.$form_id, $form_name);
$this->Application->Phrases->AddCachedPhrase('la_description_in-portal:submissions:'.$form_id, $form_name.' Submissions');
$form_subsection['label'] = 'form_sub_label_'.$form_id;
$form_subsection['url']['form_id'] = $form_id;
$form_subsection['priority'] = $priority++;
$sections['in-portal:submissions:'.$form_id] = $form_subsection;
}
$this->Application->setUnitOption($event->Prefix, 'Sections', $sections);
}
function getForms()
{
$cache_key = 'forms[%FormSerial%]';
$forms = $this->Application->getCache($cache_key);
if ($forms === false) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT Title, FormId
FROM ' . TABLE_PREFIX . 'Forms
ORDER BY Title ASC';
$forms = $this->Conn->GetCol($sql, 'FormId');
$this->Application->setCache($cache_key, $forms);
}
return $forms;
}
- function OnSave(&$event)
+ /**
+ * Saves content of temp table into live and
+ * redirects to event' default redirect (normally grid template)
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnSave(&$event)
{
parent::OnSave($event);
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
$this->OnCreateFormFields($event);
-
$this->_deleteSectionCache();
}
}
- function OnMassDelete(&$event)
+ /**
+ * Deletes all selected items.
+ * Automatically recurse into sub-items using temp handler, and deletes sub-items
+ * by calling its Delete method if sub-item has AutoDelete set to true in its config file
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnMassDelete(&$event)
{
parent::OnMassDelete($event);
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
$this->_deleteSectionCache();
}
}
function _deleteSectionCache()
{
$reset_event = new kEvent('adm:OnResetSections');
$this->Application->HandleEvent($reset_event);
$this->Application->StoreVar('RefreshStructureTree', 1);
}
/**
- * Dynamically fills customdata config
+ * Dynamically fills custom data config
*
* @param kEvent $event
*/
function OnCreateFormFields(&$event)
{
$cur_fields = $this->Conn->Query('DESCRIBE '.TABLE_PREFIX.'FormSubmissions', 'Field');
$cur_fields = array_keys($cur_fields);
// keep all fields, that are not created on the fly (includes ones, that are added during customizations)
foreach ($cur_fields as $field_index => $field_name) {
if (!preg_match('/^fld_[\d]+/', $field_name)) {
unset($cur_fields[$field_index]);
}
}
$desired_fields = $this->Conn->GetCol('SELECT CONCAT(\'fld_\', FormFieldId) FROM '.TABLE_PREFIX.'FormFields ORDER BY FormFieldId');
$sql = array();
$fields_to_add = array_diff($desired_fields, $cur_fields);
foreach ($fields_to_add as $field) {
$field_expression = $field.' Text NULL';
$sql[] = 'ADD COLUMN '.$field_expression;
}
$fields_to_drop = array_diff($cur_fields, $desired_fields);
foreach ($fields_to_drop as $field) {
$sql[] = 'DROP COLUMN '.$field;
}
if ($sql) {
$query = 'ALTER TABLE '.TABLE_PREFIX.'FormSubmissions '.implode(', ', $sql);
$this->Conn->Query($query);
}
}
/**
* Enter description here...
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnFormSubmit(&$event)
+ protected function OnFormSubmit(&$event)
{
- $object =& $event->GetObject();
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
$fields = explode(',',$this->Application->GetVar('fields'));
$required_fields = explode(',', $this->Application->GetVar('required_fields'));
$fields_params = $this->Application->GetVar('fields_params');
+ $virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
+
foreach ($fields as $field) {
- $virt_fields[$field] = Array();
- if (in_array($field, $required_fields)) {
- $virt_fields[$field]['required'] = 1;
+ $virtual_fields[$field] = Array ();
+
+ if ( in_array($field, $required_fields) ) {
+ $virtual_fields[$field]['required'] = 1;
}
+
$params = getArrayValue($fields_params, $field);
- if ($params !== false) {
- if (getArrayValue($params, 'Type') == 'email') {
- //'formatter'=>'kFormatter', 'regexp'=>'/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', 'error_msgs' => Array('invalid_format'=>'!la_invalid_email!')
- $virt_fields[$field]['formatter'] = 'kFormatter';
- $virt_fields[$field]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
- $virt_fields[$field]['error_msgs'] = Array('invalid_format'=>'!la_invalid_email!');
+
+ if ( $params !== false ) {
+ if ( getArrayValue($params, 'Type') == 'email' ) {
+ $virtual_fields[$field]['formatter'] = 'kFormatter';
+ $virtual_fields[$field]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
+ $virtual_fields[$field]['error_msgs'] = Array ('invalid_format' => '!la_invalid_email!');
}
- if (getArrayValue($params, 'Type') == 'file') {
- $virt_fields[$field]['formatter'] = 'kUploadFormatter';
- $virt_fields[$field]['upload_dir'] = '/uploads/sketches/';
+
+ if ( getArrayValue($params, 'Type') == 'file' ) {
+ $virtual_fields[$field]['formatter'] = 'kUploadFormatter';
+ $virtual_fields[$field]['upload_dir'] = '/uploads/sketches/';
}
}
}
- $object->SetVirtualFields($virt_fields);
+ $object->SetVirtualFields($virtual_fields);
$field_values = $this->getSubmittedFields($event);
+ $checkboxes = explode(',', $this->Application->GetVar('checkbox_fields')); // MailingList,In-Link,In-Newz,In-Bulletin
-
- $checkboxes = Array('MailingList', 'In-Link', 'In-Newz', 'In-Bulletin');
- $checkboxes = explode(',', $this->Application->GetVar('checkbox_fields'));
foreach ($checkboxes as $checkbox) {
if (isset($field_values[$checkbox])) {
$field_values[$checkbox] = 1;
}
else {
$field_values[$checkbox] = '0';
}
}
$object->SetFieldsFromHash($field_values);
- if ($object->Validate()) {
+
+ if ( $object->Validate() ) {
$event->redirect = $this->Application->GetVar('success_template');
$this->Application->EmailEventAdmin($this->Application->GetVar('email_event'));
- $this->Application->EmailEventUser($this->Application->GetVar('email_event'), null,
- Array('to_email' => $field_values[$this->Application->GetVar('email_field')],
- 'to_name' => $field_values[$this->Application->GetVar('name_field')]));
- if ($field_values['MailingList']) {
+ $send_params = Array (
+ 'to_email' => $field_values[$this->Application->GetVar('email_field')],
+ 'to_name' => $field_values[$this->Application->GetVar('name_field')]
+ );
+
+ $this->Application->EmailEventUser($this->Application->GetVar('email_event'), null, $send_params);
+
+ if ( $field_values['MailingList'] ) {
$this->Application->StoreVar('SubscriberEmail', $field_values['Email']);
- $this->Application->HandleEvent($sub_event, 'u:OnSubscribeUser', Array('no_unsubscribe' => 1));
+ $this->Application->HandleEvent($sub_event, 'u:OnSubscribeUser', Array ('no_unsubscribe' => 1));
}
}
else {
$event->status = kEvent::erFAIL;
}
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
parent::OnBeforeItemCreate($event);
- $this->_validatePopSettings($event);
- $this->_disableSecurityImage($event);
- $this->_setRequired($event);
+ $this->itemChanged($event);
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(&$event)
{
parent::OnBeforeItemUpdate($event);
+ $this->itemChanged($event);
+ }
+
+ /**
+ * Occurs before item is changed
+ *
+ * @param kEvent $event
+ */
+ function itemChanged(&$event)
+ {
$this->_validatePopSettings($event);
$this->_disableSecurityImage($event);
$this->_setRequired($event);
}
/**
* Validates POP3 settings (performs test connect)
*
* @param kEvent $event
*/
function _validatePopSettings(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$modes = Array ('Reply', 'Bounce');
$fields = Array ('Server', 'Port', 'Username', 'Password');
$changed_fields = array_keys( $object->GetChangedFields() );
foreach ($modes as $mode) {
$set = true;
$changed = false;
foreach ($fields as $field) {
$value = $object->GetDBField($mode . $field);
if (strlen( trim($value) ) == 0) {
$set = false;
break;
}
if (!$changed && in_array($mode . $field, $changed_fields)) {
$changed = true;
}
}
if ($set && $changed) {
// fields are set and at least on of them is changed
$connection_info = Array ();
foreach ($fields as $field) {
$connection_info[ strtolower($field) ] = $object->GetDBField($mode . $field);
}
$pop3_helper =& $this->Application->makeClass('POP3Helper', Array ($connection_info, 10));
/* @var $pop3_helper POP3Helper */
switch ( $pop3_helper->initMailbox(true) ) {
case 'socket':
$object->SetError($mode . 'Server', 'connection_failed');
break;
case 'login':
$object->SetError($mode . 'Username', 'login_failed');
break;
case 'list':
$object->SetError($mode . 'Server', 'message_listing_failed');
break;
}
}
}
}
/**
* Makes email communication fields required, when form uses email communication
*
* @param kEvent $event
*/
function _setRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required = $object->GetDBField('EnableEmailCommunication');
$fields = Array (
'ReplyFromName', 'ReplyFromEmail', 'ReplyServer', 'ReplyPort', 'ReplyUsername', 'ReplyPassword',
);
if ($required && $object->GetDBField('BounceEmail')) {
$bounce_fields = Array ('BounceEmail', 'BounceServer', 'BouncePort', 'BounceUsername', 'BouncePassword');
$fields = array_merge($fields, $bounce_fields);
}
- foreach ($fields as $field) {
- $object->setRequired($field, $required);
- }
+ $object->setRequired($fields, $required);
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
*/
function _disableSecurityImage(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ($object->GetDBField('RequireLogin')) {
$object->SetDBField('UseSecurityImage', 0);
}
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
*/
function OnProcessReplies(&$event)
{
$this->_processMailbox($event, false);
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
*/
function OnProcessBouncedReplies(&$event)
{
$this->_processMailbox($event, true);
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
*/
function _processMailbox(&$event, $bounce_mode = false)
{
$this->Application->SetVar('client_mode', 1);
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT *
FROM ' . $table_name . '
WHERE EnableEmailCommunication = 1';
$forms = $this->Conn->Query($sql, $id_field);
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
$field_prefix = $bounce_mode ? 'Bounce' : 'Reply';
foreach ($forms as $form_id => $form_info) {
$recipient_email = $bounce_mode ? $form_info['BounceEmail'] : $form_info['ReplyFromEmail'];
if (!$recipient_email) {
continue;
}
$mailbox_helper->process(
Array (
'server' => $form_info[$field_prefix . 'Server'],
'port' => $form_info[$field_prefix . 'Port'],
'username' => $form_info[$field_prefix . 'Username'],
'password' => $form_info[$field_prefix . 'Password']
),
Array (&$this, 'isValidRecipient'),
Array (&$this, 'processEmail'),
Array (
'recipient_email' => $recipient_email,
'bounce_mode' => $bounce_mode,
'form_info' => $form_info,
)
);
}
}
function isValidRecipient($params)
{
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
$recipients = $mailbox_helper->getRecipients();
$recipient_email = $params['recipient_email'];
$emails_found = preg_match_all('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $recipients, $all_emails);
if (is_array($all_emails)) {
for ($i = 0; $i < $emails_found; $i++) {
if ($all_emails[1][$i] == $recipient_email) {
// only read messages, that are addresses to submission reply email
return true;
}
}
}
// If this is a forwarded message - we drop all the other aliases and deliver only to the x-forward to address;
if (preg_match('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $mailbox_helper->headers['x-forward-to'], $get_to_email)) {
if ($get_to_email[1] == $recipient_email) {
// only read messages, that are addresses to submission reply email
return true;
}
}
return false;
}
function processEmail($params, &$fields_hash)
{
if ($params['bounce_mode']) {
// mark original message as bounced
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
if (!array_key_exists('attachments', $mailbox_helper->parsedMessage)) {
// for now only parse bounces based on attachments, skip other bounce types
return false;
}
for ($i = 0; $i < count($mailbox_helper->parsedMessage['attachments']); $i++) {
$attachment =& $mailbox_helper->parsedMessage['attachments'][$i];
switch ($attachment['headers']['content-type']) {
case 'message/delivery-status':
// save as BounceInfo
$mime_decode_helper =& $this->Application->recallObject('MimeDecodeHelper');
/* @var $mime_decode_helper MimeDecodeHelper */
$charset = $mailbox_helper->parsedMessage[ $fields_hash['MessageType'] ][0]['charset'];
$fields_hash['Message'] = $mime_decode_helper->convertEncoding($charset, $attachment['data']);
break;
case 'message/rfc822':
// undelivered message
$fields_hash['Subject'] = $attachment['filename2'] ? $attachment['filename2'] : $attachment['filename'];
break;
}
}
}
if (!preg_match('/^(.*) #verify(.*)$/', $fields_hash['Subject'], $regs)) {
// incorrect subject, no verification code
$form_info = $params['form_info'];
if ($form_info['ProcessUnmatchedEmails'] && ($fields_hash['FromEmail'] != $params['recipient_email'])) {
// it's requested to convert unmatched emails to new submissions
$form_id = $form_info['FormId'];
$this->Application->SetVar('form_id', $form_id);
$sql = 'SELECT ' . $this->Application->getUnitOption('formsubs', 'IDField') . '
FROM ' . $this->Application->getUnitOption('formsubs', 'TableName') . '
WHERE MessageId = ' . $this->Conn->qstr($fields_hash['MessageId']);
$found = $this->Conn->GetOne($sql);
if ($found) {
// don't process same message twice
return false;
}
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'FormFields
WHERE (FormId = ' . $form_info['FormId'] . ') AND (EmailCommunicationRole > 0)';
$form_fields = $this->Conn->Query($sql, 'EmailCommunicationRole');
// what roles are filled from what fields
$role_mapping = Array (
SubmissionFormField::COMMUNICATION_ROLE_EMAIL => 'FromEmail',
SubmissionFormField::COMMUNICATION_ROLE_NAME => 'FromName',
SubmissionFormField::COMMUNICATION_ROLE_SUBJECT => 'Subject',
SubmissionFormField::COMMUNICATION_ROLE_BODY => 'Message',
);
$submission_fields = Array ();
foreach ($role_mapping as $role => $email_field) {
if (array_key_exists($role, $form_fields)) {
$submission_fields[ 'fld_' . $form_fields[$role]['FormFieldId'] ] = $fields_hash[$email_field];
}
}
if ($submission_fields) {
// remove object, because it's linked to single form upon creation forever
$this->Application->removeObject('formsubs.-item');
$form_submission =& $this->Application->recallObject('formsubs.-item', null, Array ('skip_autoload' => true));
/* @var $form_submission kDBItem */
// in case that other non-role mapped fields are required
$form_submission->IgnoreValidation = true;
$form_submission->SetDBFieldsFromHash($submission_fields);
$form_submission->SetDBField('FormId', $form_id);
$form_submission->SetDBField('MessageId', $fields_hash['MessageId']);
$form_submission->SetDBField('SubmissionTime_date', adodb_mktime());
$form_submission->SetDBField('SubmissionTime_time', adodb_mktime());
$form_submission->SetDBField('ReferrerURL', $this->Application->Phrase('la_Text_Email'));
return $form_submission->Create();
}
}
return false;
}
$sql = 'SELECT ' . $this->Application->getUnitOption('submission-log', 'IDField') . '
FROM ' . $this->Application->getUnitOption('submission-log', 'TableName') . '
WHERE MessageId = ' . $this->Conn->qstr($fields_hash['MessageId']);
$found = $this->Conn->GetOne($sql);
if ($found) {
// don't process same message twice
return false;
}
$reply_to =& $this->Application->recallObject('submission-log.-reply-to', null, Array ('skip_autoload' => true));
/* @var $reply_to kDBItem */
$reply_to->Load($regs[2], 'VerifyCode');
if (!$reply_to->isLoaded()) {
// fake verification code OR feedback, containing submission log was deleted
return false;
}
if ($params['bounce_mode']) {
// mark original message as bounced
$reply_to->SetDBField('BounceInfo', $fields_hash['Message']);
$reply_to->SetDBField('BounceDate_date', TIMENOW);
$reply_to->SetDBField('BounceDate_time', TIMENOW);
$reply_to->SetDBField('SentStatus', SUBMISSION_LOG_BOUNCE);
$reply_to->Update();
return true;
}
$reply =& $this->Application->recallObject('submission-log.-reply', null, Array ('skip_autoload' => true));
/* @var $reply kDBItem */
$reply->SetDBFieldsFromHash($fields_hash);
$reply->SetDBField('ReplyTo', $reply_to->GetID());
$reply->SetDBField('FormSubmissionId', $reply_to->GetDBField('FormSubmissionId'));
$reply->SetDBField('ToEmail', $params['recipient_email']);
$reply->SetDBField('Subject', $regs[1]); // save subject without verification code
$reply->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
return $reply->Create();
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/phrases/phrases_event_handler.php
===================================================================
--- branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 14595)
+++ branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 14596)
@@ -1,391 +1,394 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 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 PhrasesEventHandler extends kDBEventHandler
{
/**
- * Apply some special processing to
- * object beeing recalled before using
- * it in other events that call prepareObject
+ * Apply some special processing to object being
+ * recalled before using it in other events that
+ * call prepareObject
*
- * @param Object $object
+ * @param kDBItem|kDBList $object
* @param kEvent $event
+ * @return void
* @access protected
*/
- function prepareObject(&$object, &$event)
+ protected function prepareObject(&$object, &$event)
{
// don't call parent
if ($event->Special == 'import' || $event->Special == 'export') {
$this->RemoveRequiredFields($object);
- $object->setRequired('LangFile');
- $object->setRequired('PhraseType');
- $object->setRequired('Module');
+ $object->setRequired( Array ('LangFile', 'PhraseType', 'Module') );
// allow multiple phrase types to be selected during import/export
- $field_options = $object->GetFieldOptions('PhraseType');
- $field_options['type'] = 'string';
- $object->SetFieldOptions('PhraseType', $field_options);
+ $object->SetFieldOption('PhraseType', 'type', 'string');
}
}
/**
* Allow to create phrases from front end in debug mode with DBG_PHRASES constant set
*
* @param kEvent $event
+ * @return bool
+ * @access public
*/
- function CheckPermission(&$event)
+ public function CheckPermission(&$event)
{
if (!$this->Application->isAdmin && $this->Application->isDebugMode(false) && kUtil::constOn('DBG_PHRASES')) {
$allow_events = Array ('OnCreate', 'OnUpdate');
if (in_array($event->Name, $allow_events)) {
return true;
}
}
return parent::CheckPermission($event);
}
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array('self' => true, 'subitem' => true),
'OnPreparePhrase' => Array('self' => true, 'subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Prepares phrase for translation
*
* @param kEvent $event
*/
function OnPreparePhrase(&$event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if (!$label) {
return ;
}
// we got label, try to get it's ID then if any
$phrase_id = $this->_getPhraseId($label);
if ($phrase_id) {
$event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $phrase_id);
$event->SetRedirectParam('pass', 'm,' . $event->getPrefixSpecial());
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->SetRedirectParam('next_template', $next_template);
}
}
else {
$event->CallSubEvent('OnNew');
}
if ($this->Application->GetVar('simple_mode')) {
$event->SetRedirectParam('simple_mode', 1);
}
}
function _getPhraseId($phrase)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($this->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Forces new label in case if issued from get link
*
* @param kEvent $event
*/
function OnNew(&$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if ($label) {
// phrase is created in language, used to display phrases
$object->SetDBField('Phrase', $label);
$object->SetDBField('PhraseType', 1); // admin
$object->SetDBField('PrimaryTranslation', $this->_getPrimaryTranslation($label));
}
// set module from cookie
$last_module = $this->Application->GetVar('last_module');
if ($last_module) {
$object->SetDBField('Module', $last_module);
}
if (($event->Special == 'export') || ($event->Special == 'import')) {
$object->SetDBField('PhraseType', '|0|1|2|');
$object->SetDBField('Module', '|' . implode('|', array_keys($this->Application->ModuleInfo)) . '|' );
}
}
/**
* Returns given phrase translation on primary language
*
* @param string $phrase
* @return string
*/
function _getPrimaryTranslation($phrase)
{
$sql = 'SELECT l' . $this->Application->GetDefaultLanguageId() . '_Translation
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Forces create to use live table
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
$object =& $event->getObject( Array('skip_autoload' => true) );
if ($this->Application->GetVar('m_lang') != $this->Application->GetVar('lang_id')) {
$object->SwitchToLive();
}
$this->returnToOriginalTemplate($event);
}
parent::OnCreate($event);
}
/**
* Redirects to original template after phrase is being update
*
* @param kEvent $event
*/
function OnUpdate(&$event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
$this->returnToOriginalTemplate($event);
}
parent::OnUpdate($event);
}
/**
* Returns to original template after phrase adding/editing
*
* @param kEvent $event
*/
function returnToOriginalTemplate(&$event)
{
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->redirect = $next_template;
$event->SetRedirectParam('opener', 's');
}
}
/**
* Set last change info, when phrase is created
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$primary_language_id = $this->Application->GetDefaultLanguageId();
- if (!$object->GetDBField('l' . $primary_language_id . '_Translation')) {
+ if ( !$object->GetDBField('l' . $primary_language_id . '_Translation') ) {
// no translation on primary language -> try to copy from other language
$src_languages = Array ('lang_id', 'm_lang'); // editable language, theme language
foreach ($src_languages as $src_language) {
$src_language = $this->Application->GetVar($src_language);
$src_value = $src_language ? $object->GetDBField('l' . $src_language . '_Translation') : false;
- if ($src_value) {
+ if ( $src_value ) {
$object->SetDBField('l' . $primary_language_id . '_Translation', $src_value);
break;
}
}
}
$this->_phraseChanged($event);
}
/**
* Update last change info, when phrase is updated
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(&$event)
{
parent::OnBeforeItemUpdate($event);
$this->_phraseChanged($event);
}
/**
* Set's phrase key and last change info, used for phrase updating and loading
*
* @param kEvent $event
*/
function _phraseChanged(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('PhraseKey', mb_strtoupper($object->GetDBField('Phrase')));
if ( $this->translationChanged($object) ) {
$object->SetDBField('LastChanged_date', adodb_mktime() );
$object->SetDBField('LastChanged_time', adodb_mktime() );
$object->SetDBField('LastChangeIP', $_SERVER['REMOTE_ADDR']);
}
$this->Application->Session->SetCookie('last_module', $object->GetDBField('Module'));
}
/**
* Checks, that at least one of phrase's translations was changed
*
* @param kDBItem $object
* @return bool
*/
function translationChanged(&$object)
{
$changed_fields = array_keys( $object->GetChangedFields() );
$translation_fields = Array ('Translation', 'HintTranslation', 'ColumnTranslation');
foreach ($changed_fields as $changed_field) {
$changed_field = preg_replace('/^l[\d]+_/', '', $changed_field);
if ( in_array($changed_field, $translation_fields) ) {
return true;
}
}
return false;
}
/**
* Changes default module to custom (when available)
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
if ($this->Application->findModule('Name', 'Custom')) {
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Module']['default'] = 'Custom';
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
// make sure, that PrimaryTranslation column always refrers to primary language column
$language_id = $this->Application->GetVar('lang_id');
if (!$language_id) {
$language_id = $this->Application->GetVar('m_lang');
}
$primary_language_id = $this->Application->GetDefaultLanguageId();
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
foreach ($calculated_fields[''] as $field_name => $field_expression) {
$field_expression = str_replace('%5$s', $language_id, $field_expression);
$field_expression = str_replace('%4$s', $primary_language_id, $field_expression);
$calculated_fields[''][$field_name] = $field_expression;
}
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
if ($this->Application->GetVar('regional')) {
$this->Application->setUnitOption($event->Prefix, 'PopulateMlFields', true);
}
}
/**
* Saves changes & changes language
*
* @param kEvent $event
*/
function OnPreSaveAndChangeLanguage(&$event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if ($label && !$this->UseTempTables($event)) {
$phrase_id = $this->_getPhraseId($label);
if ($phrase_id) {
$event->CallSubEvent('OnUpdate');
$event->SetRedirectParam('opener', 's');
}
else {
$event->CallSubEvent('OnCreate');
$event->SetRedirectParam('opener', 's');
}
if ($event->status != kEvent::erSUCCESS) {
return ;
}
$event->SetRedirectParam($event->getPrefixSpecial() . '_event', 'OnPreparePhrase');
$event->SetRedirectParam('pass_events', true);
}
if ($this->Application->GetVar('simple_mode')) {
$event->SetRedirectParam('simple_mode', 1);
}
parent::OnPreSaveAndChangeLanguage($event);
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
*/
function OnEdit(&$event)
{
parent::OnEdit($event);
// use language from grid, instead of primary language used by default
$event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang'));
}
}
\ No newline at end of file
Index: branches/5.2.x/core/admin_templates/login.tpl
===================================================================
--- branches/5.2.x/core/admin_templates/login.tpl (revision 14595)
+++ branches/5.2.x/core/admin_templates/login.tpl (revision 14596)
@@ -1,242 +1,244 @@
<inp2:m_Set skip_last_template="1"/>
<inp2:adm_HTTPAuth result_to_var="http_auth"/>
<inp2:m_include t="incs/header" nobody="yes"/>
<body topmargin="0" leftmargin="0" marginheight="0" marginwidth="0" bgcolor="#FFFFFF">
<style type="text/css">
<!--
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#header-div {
position: absolute;
top: 0px;
height: 160px;
left: 0px;
right: 0px;
background: url('img/login/login-top.png') no-repeat right top #007bf4;
z-index: 2;
}
#body-div {
position: absolute;
top: 160px;
bottom: 160px;
width: 100%;
text-align: center;
z-index: 5;
}
#footer-div {
position: absolute;
bottom: 0px;
height: 160px;
left: 0px;
right: 0px;
background: url('img/login/login-bottom.png') no-repeat left bottom #007bf4;
z-index: 2;
}
#outer {
position: absolute;
top: 50%;
left: 0px;
width: 100%;
height: 1px;
overflow: visible;
z-index: 10;
}
#inner {
text-align: left;
width: 100%;
height: 300px;
margin-left: -50%; /*** width / 2 ***/
position: absolute;
top: -150px; /*** height / 2 ***/
left: 50%;
z-index: 5;
/* border: 1px solid #000000; */
}
#form table {
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border: 1px solid #CCCCCC;
font-weight: normal;
background-color: #ECECEC;
z-index: 5;
}
#form table td {
padding: 2px 15px 2px 15px;
}
.login-table {
background: #ECECEC;
}
.roundbutton {
-moz-border-radius: 11px;
-webkit-border-radius: 11px;
cursor: pointer;
padding: 2px 5px;
text-decoration: none;
}
-->
</style>
<div id="header-div"></div>
<div id="body-div">
<div id="outer">
<div id="inner" align="center">
<div id="logo" align="center" style="margin-bottom: 20px;">
<table class="head-table" style="background: none;">
<tr>
<inp2:m_if check="adm_AdminSkin" type="LogoLogin">
<td align="center"><img src="<inp2:adm_AdminSkin type='LogoLogin'/>" alt="<inp2:m_GetConfig var='Site_Name'/>"></td>
<inp2:m_else/>
<inp2:m_if check="adm_AdminSkin" type="Logo">
<td>
<img src="<inp2:adm_AdminSkin type='Logo'/>" alt="<inp2:m_GetConfig var='Site_Name'/>"><br/>
<inp2:m_if check="adm_AdminSkin" type="LogoBottom">
<img src="<inp2:adm_AdminSkin type='LogoBottom'/>" alt="<inp2:m_GetConfig var='Site_Name'/>">
</inp2:m_if>
</td>
</inp2:m_if>
<td align="left" valign="middle">
<span style="font-size: 48px; color: black;"><inp2:m_GetConfig var="Site_Name"/></span>
</td>
</inp2:m_if>
</tr>
</table>
</div>
<div id="form" align="center">
<inp2:m_if check="m_Param" name="http_auth">
+ <inp2:u.login-admin_FormName name="login"/>
+
<table class="login-table">
<tr>
<td colspan="2" style="text-align: center">
<inp2:m_if check="u.login-admin_HasError" field="any">
<span class="error-cell"><inp2:u.login-admin_Error field="UserLogin"/></span>
</inp2:m_if><br/>
</td>
</tr>
<tr>
<td class="text"><inp2:m_phrase name="la_Text_Login"/>:</td>
<td><input type="text" name="<inp2:u.login-admin_InputName name='UserLogin'/>" class="text" value="<inp2:u.login-admin_CookieUsername field='UserLogin'/>" style="width: 150px;"></td>
</tr>
<tr>
<td class="text"><inp2:m_phrase name="la_prompt_Password"/>:</td>
<td><input type="password" name="<inp2:u.login-admin_InputName name='UserPassword'/>" class="text" style="width: 150px;"></td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" id="save_username" name="cb_save_username"<inp2:m_if check="m_GetEquals" name="save_username" value="" inverse="inverse"> checked="checked"</inp2:m_if>/>&nbsp;
<label for="save_username"><inp2:m_Phrase label="la_SaveLogin"/></label>
</td>
</tr>
<tr>
<td colspan="2" align="center" style="padding: 5px 15px 10px 15px;">
<input type="submit" name="login_button" value="<inp2:m_phrase name='la_Login' no_editing='1'/>" class="kx-login-button roundbutton"></td>
</tr>
</table>
<inp2:m_else/>
<h1 style="color: red;">401 Authentication Required</h1>
</inp2:m_if>
</div>
</div>
</div>
</div>
<div id="footer-div"></div>
<inp2:m_if check="m_Param" name="http_auth">
<input type="hidden" name="next_template" value="<inp2:m_if check='m_GetEquals' name='next_template' value="">index<inp2:m_else/><inp2:m_get var='next_template'/></inp2:m_if>"/>
<input type="hidden" name="skip_last_template" value="1"/>
<script type="text/javascript">
$(document).ready(
function() {
$("input[name='login']").focus();
Application.SetVar('events[u.login-admin]', 'OnLogin');
}
);
var a_parent = window.parent;
var to_close = new Array();
function redirect() {
// alert('running redirect in "' + window.name + '"');
// window.name = 'redirect';
var $main_frame = getFrame('main');
a_parent = window;
try {
var i = 0;
while (i < 10) {
i++;
var $opener = $main_frame.getWindowOpener(a_parent);
// console.log('window: ', a_parent.name, '; opener: ', $opener ? $opener.name : null);
if ($opener) {
to_close.push(a_parent);
a_parent = $opener;
continue;
}
if (a_parent.name == 'main_frame') {
break;
}
if (a_parent.parent && a_parent.parent.name != a_parent.name) {
a_parent = a_parent.parent;
continue;
}
}
}
catch (err) {
// another website is opened in parent window
alert('Error while trying to access window opener: [' + err.message + ']');
i = 10;
}
if (i < 10) {
// console.log('to close: ', to_close);
setTimeout(close_windows, 100);
}
}
function close_windows() {
page = '<inp2:m_t t="index" expired="1" escape="1" no_amp="1" m_wid=""/>'; // a_parent.location.href + '?expired=1';
// alert('redirecting ' + a_parent.name + ' to ' + page);
a_parent.location.href = page;
// alert('closing ' + to_close.length + ' windows');
for (var c = (to_close.length - 1); c >= 0; c--) {
// alert('closing ' + to_close[c].name);
window_close(to_close[c]);
}
}
if (window.top.frames.length > 0) {
redirect();
}
</script>
</inp2:m_if>
<inp2:m_include t="incs/footer"/>
\ No newline at end of file

Event Timeline