Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Wed, Aug 13, 1:42 PM

in-portal

Index: branches/5.2.x/core/kernel/db/db_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/db_event_handler.php (revision 14757)
+++ branches/5.2.x/core/kernel/db/db_event_handler.php (revision 14758)
@@ -1,3141 +1,3186 @@
<?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 standard 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'),
+ 'OnValidateField' => Array ('self' => true, 'subitem' => true),
);
$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 ( $event->Special == 'previous' || $event->Special == 'next' ) {
$object =& $this->Application->recallObject( $event->getEventParam('item') );
/* @var $object kDBItem */
$list_helper =& $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
return $list_helper->getNavigationResource($object, $event->getEventParam('list'), $event->Special == 'next');
}
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|kDBItem|kDBList $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));
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);
$parent_event = $event->getEventParam('parent_event');
if ( is_object($parent_event) ) {
$object->setParentEvent($parent_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();
/* @var $object kDBItem */
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();
/* @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->InitDone ? $this->Application->RecallVar('user_id') : USER_ROOT;
$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');
/* @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 */
$parent_event = $event->getEventParam('parent_event');
if ( is_object($parent_event) ) {
$object->setParentEvent($parent_event);
}
$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
*/
protected function LoadItem(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $this->getPassedID($event);
if ( $object->isLoaded() && !is_array($id) && ($object->GetID() == $id) ) {
// object is already loaded by same id
return ;
}
if ( $object->Load($id) ) {
$actions =& $this->Application->recallObject('kActions');
/* @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);
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'));
$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->SetPagination($event);
$this->SetSorting($event);
$actions =& $this->Application->recallObject('kActions');
/* @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 kDBEventHandler::OnListBuild()
*/
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 {
$sorting_settings = $this->getListSetting($event, 'Sortings');
$cur_sort1 = getArrayValue($sorting_settings, 'Sort1');
$cur_sort1_dir = getArrayValue($sorting_settings, 'Sort1_Dir');
$cur_sort2 = getArrayValue($sorting_settings, 'Sort2');
$cur_sort2_dir = getArrayValue($sorting_settings, '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']),
);
// TODO: lowercase configuration variable values in db, instead of here
$list_sortings[$sorting_prefix]['Sorting'] = array_map('strtolower', $list_sortings[$sorting_prefix]['Sorting']);
}
// 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 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 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|Array
* @access protected
*/
protected 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 persistent 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);
}*/
if ( kUtil::IsSerialized($variable_value) ) {
$variable_value = unserialize($variable_value);
}
return $variable_value;
}
/**
* Sets list setting by name (persistent and real session)
*
* @param kEvent $event
* @param string $variable_name
* @param string|Array $variable_value
* @return void
* @access protected
*/
protected 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) ) {
if ( is_array($variable_value) ) {
$variable_value = serialize($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), '_');
// add search filter
$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 ) {
$grid_name = $event->getEventParam('grid');
$custom_filters = unserialize($custom_filters);
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'] ) {
$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 = unserialize($view_filter);
$temp_filter =& $this->Application->makeClass('kMultipleFilter');
/* @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_info = $filter_menu['Groups'][$group_key];
$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]);
}
}
$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)
{
$sorting_settings = $this->getListSetting($event, 'Sortings');
$cur_sort1 = getArrayValue($sorting_settings, 'Sort1');
$cur_sort1_dir = getArrayValue($sorting_settings, 'Sort1_Dir');
$use_double_sorting = $this->Application->ConfigValue('UseDoubleSorting');
if ( $use_double_sorting ) {
$cur_sort2 = getArrayValue($sorting_settings, 'Sort2');
$cur_sort2_dir = getArrayValue($sorting_settings, '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';
}
$sorting_settings = Array ('Sort1' => $cur_sort1, 'Sort1_Dir' => $cur_sort1_dir);
if ( $use_double_sorting ) {
$sorting_settings['Sort2'] = $cur_sort2;
$sorting_settings['Sort2_Dir'] = $cur_sort2_dir;
}
$this->setListSetting($event, 'Sortings', $sorting_settings);
}
/**
* 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, 'Sortings', Array ('Sort1' => $field, '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, 'Sortings');
}
/**
* 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)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$sqls = $object->getFormOption('ItemSQLs', Array ());
$special = isset($sqls[$event->Special]) ? $event->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)
{
$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
*/
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
*/
protected function OnUpdate(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
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) ) {
$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_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$temp_handler->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', Array ('parent_event' => &$event));
/* @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;
}
/**
* Cancels kDBItem Editing/Creation
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCancel(&$event)
{
$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_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @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) ) {
$delete_ids[] = $id;
}
}
if ( $delete_ids ) {
$temp_handler->DeleteItems($event->Prefix, $event->Special, $delete_ids);
}
}
$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
*/
protected function OnMassDelete(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return ;
}
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$ids = $this->StoreSelectedIDs($event);
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('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_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$temp_handler->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
*/
protected function OnSave(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status != kEvent::erSUCCESS) {
return ;
}
$skip_master = false;
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
if ( !$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$live_ids = $temp_handler->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 ;
}
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);
}
$object =& $event->getObject();
/* @var $object kDBItem */
$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
*/
protected function OnCancelEdit(&$event)
{
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$temp_handler->CancelEdit();
-
$this->clearSelectedIDs($event);
- $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);
+
+ $event->SetRedirectParam('opener', 'u');
}
/**
* 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) );
/* @var $object kDBItem */
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
*/
protected function OnPreSave(&$event)
{
// if there is no id - it means we need to create an item
if ( is_object($event->MasterEvent) ) {
$event->MasterEvent->setEventParam('IsNew', false);
}
if ( $this->isNewItemCreate($event) ) {
$event->CallSubEvent('OnPreSaveCreated');
if ( is_object($event->MasterEvent) ) {
$event->MasterEvent->setEventParam('IsNew', true);
}
return ;
}
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
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) ) {
$this->customProcessing($event, 'after');
$event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
}
/**
* [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
*/
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) );
/* @var $object kDBItem */
$temp_handler =& $this->Application->recallObject($event->Prefix . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$temp_handler->PrepareEdit();
$object->setID(0);
$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 success
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreSaveCreated(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
$this->customProcessing($event, 'before');
if ( $object->Create() ) {
$this->customProcessing($event, 'after');
$event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $object->GetID());
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
$object->setID(0);
}
}
/**
* 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) ) {
// just reset id to 0 in case it was create
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$object->setID(0);
$this->Application->SetVar($event->getPrefixSpecial() . '_id', 0);
}
}
/**
* Apply same processing to each item being selected in grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function iterateItems(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return ;
}
$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 ( !$order_field ) {
$order_field = 'Priority';
}
foreach ($ids as $id) {
$object->Load($id);
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() ) {
$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) ) {
$event->status = kEvent::erFAIL;
return ;
}
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$ids = $this->StoreSelectedIDs($event);
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;
}
/**
* 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');
$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)
{
}
/**
* Occurs after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemLoad(&$event)
{
}
/**
* Occurs before creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemCreate(&$event)
{
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemCreate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->IsTempTable() ) {
$this->_proccessPendingActions($event);
}
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemUpdate(&$event)
{
}
/**
* 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
* @return void
* @access protected
*/
protected function OnBeforeItemValidate(kEvent &$event)
{
}
/**
* Occurs after successful item validation
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemValidate(kEvent &$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)
{
}
/**
* 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
*/
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;
}
/**
* 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
*/
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
* @return void
* @access protected
* @deprecated
*/
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) );
}
/**
* 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;
}
$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));
$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
*/
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 ) {
$resource_id = $this->Application->GetVar('translator_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));
/* @var $cdata kDBItem */
$cdata->Load($resource_id, 'ResourceId');
if ( !$cdata->isLoaded() ) {
$cdata->SetDBField('ResourceId', $resource_id);
$cdata->Create();
}
$this->Application->SetVar($cdata->getPrefixSpecial() . '_id', $cdata->GetID());
}
$event->redirect = $this->Application->GetVar('translator_t');
$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'),
);
$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);
$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 = array_keys( $object->getFields() );
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 ) {
$user_id = array_shift( array_keys($items_info) );
$this->RemoveRequiredFields($object);
$is_new = !$object->isLoaded();
$is_main = substr($this->Application->GetVar($event->Prefix . '_mode'), 0, 1) == 't';
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 ) {
$object->Create();
}
else {
$object->Update();
}
}
$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 being
* recalled before using it in other events that
* call prepareObject
*
* @param kDBItem|kDBList $object
* @param kEvent $event
* @return void
* @access protected
*/
protected function prepareObject(&$object, &$event)
{
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)
{
}
/**
* Deletes export preset
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnDeleteExportPreset(&$event)
{
$field_values = $this->getSubmittedFields($event);
if ( !$field_values ) {
return ;
}
$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
*/
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 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');
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$field_options = array_key_exists($field_name, $fields) ? $fields[$field_name] : $virtual_fields[$field_name];
$upload_dir = $field_options['upload_dir'];
$storage_format = array_key_exists('storage_format', $field_options) ? $field_options['storage_format'] : false;
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 ;
}
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$fname = $file_helper->ensureUniqueFilename($tmp_path, $fname);
if ($storage_format) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
move_uploaded_file($value['tmp_name'], $value['tmp_name'] . '.jpg'); // add extension, so ResizeImage can work
$url = $image_helper->ResizeImage($value['tmp_name'] . '.jpg', $storage_format);
$tmp_name = preg_replace('/^' . preg_quote($this->Application->BaseURL(), '/') . '/', '/', $url);
rename($tmp_name, $tmp_path.$fname);
}
else {
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;
}
header('Content-Length: ' . filesize($path));
header('Content-Type: ' . kUtil::mimeContentType($path));
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);
}
/**
+ * Validates individual object field and returns the result
+ *
+ * @param kEvent $event
+ */
+ function OnValidateField(&$event)
+ {
+ $event->status = kEvent::erSTOP;
+ $field = $this->Application->GetVar('field');
+
+ if ( ($this->Application->GetVar('ajax') != 'yes') || !$field ) {
+ return;
+ }
+
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
+
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+
+ if ( !$items_info ) {
+ return;
+ }
+
+ list ($id, $field_values) = each($items_info);
+ $object->Load($id);
+ $object->SetFieldsFromHash($field_values);
+ $object->setID($id);
+
+ $response = Array ('status' => 'OK',);
+
+ $event->CallSubEvent($object->isLoaded() ? 'OnBeforeItemUpdate' : 'OnBeforeItemCreate');
+
+ // validate all fields, since "Password_plain" field sets error to "Password" field, which is passed here
+ $error_field = $object->GetFieldOption($field, 'error_field', false, $field);
+
+ if ( !$object->Validate() && $object->GetErrorPseudo($error_field) ) {
+ $response['status'] = $object->GetErrorMsg($error_field);
+ }
+
+ $event->status = kEvent::erSTOP; // since event's OnBefore... events can change this event status
+ echo json_encode($response);
+ }
+
+ /**
* 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'));*/
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
$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);
}
/**
* Returns constrain for priority calculations
*
* @param kEvent $event
* @return void
* @see PriorityEventHandler
* @access protected
*/
protected function OnGetConstrainInfo(&$event)
{
$event->setEventParam('constrain_info', Array ('', ''));
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/password_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/password_formatter.php (revision 14757)
+++ branches/5.2.x/core/kernel/utility/formatters/password_formatter.php (revision 14758)
@@ -1,158 +1,158 @@
<?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 kPasswordFormatter 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['verify_field'] ) ) {
$add_fields = Array ();
- $options = Array ('master_field' => $field_name, 'formatter' => 'kPasswordFormatter');
+ $options = Array ('master_field' => $field_name, /*'error_field' => $field_name,*/ 'formatter' => 'kPasswordFormatter');
$copy_options = Array ('encryption_method', 'salt', 'required', 'skip_empty');
foreach ($copy_options as $copy_option) {
if (array_key_exists($copy_option, $field_options)) {
$options[$copy_option] = $field_options[$copy_option];
}
}
$add_fields[ $field_options['verify_field'] ] = $options;
$add_fields[$field_name.'_plain'] = Array('type'=>'string', 'error_field'=>$field_name);
$add_fields[ $field_options['verify_field'].'_plain' ] = Array('type'=>'string', 'error_field'=>$field_options['verify_field'] );
$virtual_fields = $object->getVirtualFields();
$add_fields = kUtil::array_merge_recursive($add_fields, $virtual_fields);
$object->setVirtualFields($add_fields);
}
}
/**
* 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)
{
return $value;
}
/**
* Performs password & verify password field validation
*
* @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);
$flip_count = 0;
$fields_set = true;
$password_field = $verify_field = '';
$fields = Array ('master_field', 'verify_field');
-
+
// 1. collect values from both Password and VerifyPassword fields
while ($flip_count < 2) {
if ( getArrayValue($options, $fields[0]) ) {
$tmp_field = $options[ $fields[0] ];
$object->SetDBField($field_name.'_plain', $value);
if ( !$object->GetFieldOption($tmp_field, $fields[1].'_set') ) {
$object->SetFieldOption($tmp_field, $fields[1].'_set', true);
}
$password_field = $options[ $fields[0] ];
$verify_field = $field_name;
}
$fields = array_reverse($fields);
$flip_count++;
}
$salt = $object->GetFieldOption($password_field, 'salt', false, '');
if ($object->GetFieldOption($password_field, 'verify_field_set') && $object->GetFieldOption($verify_field, 'master_field_set')) {
$new_password = $object->GetDBField($password_field . '_plain');
$verify_password = $object->GetDBField($verify_field . '_plain');
if ($new_password == '' && $verify_password == '') {
// both passwords are empty -> keep old password
if ($object->GetDBField($password_field) != $this->EncryptPassword('', $salt)) {
if ($options['encryption_method'] == 'plain') {
return $value;
}
return $this->EncryptPassword($value);
}
else {
return $value;
}
}
// determine admin or front
$phrase_error_prefix = $this->Application->isAdmin ? 'la' : 'lu';
if ($new_password != $verify_password) {
// passwords don't match (no matter what is their length)
$object->SetError($verify_field, 'passwords_do_not_match', $phrase_error_prefix.'_passwords_do_not_match');
}
$min_length = $this->Application->ConfigValue('Min_Password'); // for error message too
$min_length = $object->GetFieldOption($password_field, 'min_length', false, $min_length);
if (mb_strlen($new_password) < $min_length) {
$error_msg = '+' . sprintf($this->Application->Phrase($phrase_error_prefix.'_passwords_too_short'), $min_length); // + -> not phrase
$object->SetError($password_field, 'passwords_min_length', $error_msg);
}
}
if ($value == '') {
return $object->GetDBField($field_name);
}
if ($options['encryption_method'] == 'plain') {
return $value;
}
return $this->EncryptPassword($value, $salt);
}
function EncryptPassword($value, $salt=null)
{
if (!isset($salt) || !$salt) {
// if empty salt, assume, that it's not passed at all
return md5($value);
}
return md5(md5($value).$salt);
}
}
\ 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 14757)
+++ branches/5.2.x/core/units/users/users_event_handler.php (revision 14758)
@@ -1,1790 +1,1805 @@
<?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 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);
$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()
*/
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 user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(&$event)
{
if ( $event->Name == 'OnLogin' || $event->Name == 'OnLogout' ) {
// permission is checked in OnLogin event directly
return true;
}
if ( $event->Name == 'OnResetRootPassword' ) {
return defined('DBG_RESET_ROOT') && DBG_RESET_ROOT;
}
if ( $event->Name == 'OnLoginAs' ) {
$admin_session =& $this->Application->recallObject('Session.admin');
/* @var $admin_session Session */
return $admin_session->LoggedIn();
}
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' || $event->Name == 'OnRegisterAjax') && $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));
/* @var $user_dummy UsersItem */
foreach ($items_info as $id => $field_values) {
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 ) {
// 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] ) {
// 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));
}
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
* @return void
* @access protected
*/
protected function OnLogin(&$event)
{
$object =& $event->getObject( Array ('form_name' => 'login') );
/* @var $object kDBItem */
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
$username = $object->GetDBField('UserLogin');
$password = $object->GetDBField('UserPassword');
$remember_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, $remember_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');
}
/**
* Performs user logout
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnLogout(&$event)
{
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user_helper->event =& $event;
$user_helper->logoutUser();
}
/**
* Redirects user after successful registration to confirmation template (on Front only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemCreate(&$event)
{
parent::OnAfterItemCreate($event);
$this->afterItemChanged($event);
$this->assignToPrimaryGroup($event);
}
/**
* Performs user registration
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
if ( $this->Application->isAdmin ) {
parent::OnCreate($event);
return ;
}
$object =& $event->getObject( Array('form_name' => 'registration') );
/* @var $object UsersItem */
$field_values = $this->getSubmittedFields($event);
$user_email = getArrayValue($field_values, 'Email');
$subscriber_id = $user_email ? $this->getSubscriberByEmail($user_email) : false;
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));
}
$object->SetFieldsFromHash($field_values);
$status = $object->isLoaded() ? $object->Update() : $object->Create();
if ( !$status ) {
$event->status = kEvent::erFAIL;
$event->redirect = false;
$object->setID( (int)$object->GetID() );
}
$this->setNextTemplate($event, true);
if ( ($event->status == kEvent::erSUCCESS) && $event->redirect ) {
$this->assignToPrimaryGroup($event);
$object->SendEmailEvents();
$this->autoLoginUser($event);
}
}
/**
+ * Processes user registration from ajax request
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnRegisterAjax(kEvent &$event)
+ {
+ $ajax_form_helper =& $this->Application->recallObject('AjaxFormHelper');
+ /* @var $ajax_form_helper AjaxFormHelper */
+
+ $ajax_form_helper->transitEvent($event, 'OnCreate');
+ }
+
+ /**
* Returns subscribed user ID by given e-mail address
*
* @param string $email
* @return int|bool
* @access protected
*/
protected function getSubscriberByEmail($email)
{
$verify_user =& $this->Application->recallObject('u.verify', null, Array ('skip_autoload' => true));
/* @var $verify_user UsersItem */
$verify_user->Load($email, 'Email');
return $verify_user->isLoaded() && $verify_user->isSubscriberOnly() ? $verify_user->GetID() : false;
}
/**
* Login user if possible, if not then redirect to corresponding template
*
* @param kEvent $event
*/
function autoLoginUser(&$event)
{
$object =& $event->getObject();
/* @var $object UsersItem */
$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 ( $user_helper->checkLoginPermission() ) {
$user_helper->loginUserById( $object->GetID() );
}
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemCreate(&$event)
{
parent::OnBeforeItemCreate($event);
$this->beforeItemChanged($event);
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$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');
$this->setUserGroup($object);
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
if ( !$user_helper->checkBanRules($object) ) {
$object->SetError('Username', 'banned');
}
$object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']);
}
/**
* 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
* @return void
* @access protected
*/
protected function OnAfterItemValidate(kEvent &$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( Array ('form_name' => 'recommend') );
/* @var $object kDBItem */
$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));
/* @var $object kDBItem */
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ( $items_info ) {
list ($id, $field_values) = each($items_info);
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)
{
$object =& $event->getObject( Array ('form_name' => 'subscription') );
/* @var $object UsersItem */
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
if ( !$object->ValidateField('SubscriberEmail') ) {
$event->status = kEvent::erFAIL;
return ;
}
$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 =& $event->getObject( Array ('form_name' => 'subscription') );
/* @var $object UsersItem */
$user_email = $this->Application->GetVar('subscriber_email');
$object->SetDBField('SubscriberEmail', $user_email);
if ( !$object->ValidateField('SubscriberEmail') ) {
$event->status = kEvent::erFAIL;
return ;
}
$this->RemoveRequiredFields($object);
$object->Load($user_email, 'Email');
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->RemoveSubscriberGroup( $object->GetID() );
}
$event->redirect = $this->Application->GetVar('unsubscribe_ok_template');
}
else {
$this->AddSubscriberGroup($object);
$event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
}
else {
$object->generatePassword();
$object->SetDBField('Email', $user_email);
if ( $object->isRequired('Username') ) {
$object->SetDBField('Username', $user_email);
}
$object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default
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);
}
/**
* Validates forgot password form and sends password reset confirmation e-mail
*
* @param kEvent $event
* @return void
*/
function OnForgotPassword(&$event)
{
$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, 'Username');
}
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;
}
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @access protected
*/
protected function OnUpdate(&$event)
{
parent::OnUpdate($event);
if ( !$this->Application->isAdmin ) {
$this->setNextTemplate($event);
}
}
/**
* Checks state against country
*
* @param kEvent $event
* @return void
* @access protected
*/
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');
$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());
}
}
/**
* Occurs before item is changed
*
* @param kEvent $event
*/
function beforeItemChanged(&$event)
{
$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 && $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;
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) {
$this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRATION.NOTICE', $record['PortalUserId']);
$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) {
$this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRED', $id);
$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
}
/**
* Used to keep user registration form data, while showing affiliate registration form fields
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnRefreshForm(&$event)
{
$event->redirect = false;
$item_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list($id, $fields) = each($item_info);
$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);
}
}
/**
* Return user from order by special .ord
*
* @param kEvent $event
* @return int
*/
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
*/
protected function OnUpdatePassword(&$event)
{
$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));
/* @var $user_dummy kDBItem */
$user_dummy->Load($id);
$status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
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 ;
}
}
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' ) {
$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);
if ( $object->Validate() ) {
// validation on, password match too
$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 ;
}
}
else {
$object =& $event->getObject();
$object->SetFieldsFromHash($field_values);
if ( !$object->Update() ) {
$event->status = kEvent::erFAIL;
$event->redirect = false;
}
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Resets grid settings, remembered in each user record
*
* @param kEvent $event
* @return void
* @access protected
*/
protected 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();
/* @var $object kDBItem */
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
*/
protected function afterItemChanged(&$event)
{
$this->saveUserImages($event);
$object =& $event->getObject();
/* @var $object UsersItem */
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));
}
// update user subscription status (via my profile or new user registration)
if ( !$this->Application->isAdmin && !$object->isSubscriberOnly() ) {
if ( $object->GetDBField('SubscribeToMailing') && !$object->isSubscribed() ) {
$this->AddSubscriberGroup($object);
}
elseif ( !$object->GetDBField('SubscribeToMailing') && $object->isSubscribed() ) {
$this->RemoveSubscriberGroup( $object->GetID() );
}
}
}
/**
* Stores user's original Status before overwriting with data from temp table
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeDeleteFromLive(&$event)
{
parent::OnBeforeDeleteFromLive($event);
$user_id = $event->getEventParam('id');
$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);
$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
$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['Username']['min_len'] = $this->Application->ConfigValue('Min_UserName');
$fields['Username']['max_len'] = $max_username ? $max_username : 255;
// 2. set default user registration group
$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
$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('RegistrationUsernameRequired') ) {
// Username becomes required only, when it's used in registration process
$form_fields['Username']['required'] = 1;
}
$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
*/
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
*/
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 UsersItem */
$image_helper->LoadItemImages($object);
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$cs_helper->PopulateStates($event, 'State', 'Country');
// get user subscription status
$object->SetDBField('SubscribeToMailing', $object->isSubscribed() ? 1 : 0);
}
/**
* 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;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$user_type = $this->Application->GetVar('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 _makePasswordRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required_fields = Array ('Password', 'Password_plain', 'VerifyPassword', 'VerifyPassword_plain');
$object->setRequired($required_fields);
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(&$event)
{
$id = $this->getPassedID($event);
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() );
}
}
}
/**
* Generates new Root password and email it
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnResetRootPassword(&$event)
{
$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
/* @var $password_formatter kPasswordFormatter */
$new_root_password = kUtil::generatePassword();
$new_root_password_encrypted = $password_formatter->EncryptPassword($new_root_password, 'b38');
$this->Application->SetConfigValue('RootPass', $new_root_password_encrypted);
$this->Application->EmailEventAdmin('ROOT.RESET.PASSWORD', null, Array ('password' => $new_root_password));
$event->SetRedirectParam('reset', 1);
$event->SetRedirectParam('pass', 'm');
}
/**
* Perform login of user, selected in Admin Console, on Front-End in a separate window
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnLoginAs(kEvent &$event)
{
$user_helper =& $this->Application->recallObject('UserHelper');
/* @var $user_helper UserHelper */
$user =& $user_helper->getUserObject();
$user->Load( $this->Application->GetVar('user_id') );
if ( !$user->isLoaded() ) {
return ;
}
if ( $user_helper->checkLoginPermission() ) {
$user_helper->loginUserById( $user->GetID() );
}
}
}
Index: branches/5.2.x/core/units/users/users_config.php
===================================================================
--- branches/5.2.x/core/units/users/users_config.php (revision 14757)
+++ branches/5.2.x/core/units/users/users_config.php (revision 14758)
@@ -1,642 +1,642 @@
<?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' => '',
'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' => 'Username',
'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', 'frontend_mail', '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 ('Username' => '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',
),
),
'Forms' => Array (
'default' => Array (
'Fields' => Array (
'PortalUserId' => Array ('default' => 0),
'Username' => 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' => ''),
+ 'Street2' => Array ('error_field' => 'Street', '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),
'IPAddress' => 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
),
'IPRestrictions' => Array ('default' => NULL),
),
'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' => ''),
'SubscribeToMailing' => Array (
- 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'lu_No', 1 => 'lu_Yes'), 'use_phrases' => 1,
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'lu_Yes', 0 => 'lu_No'), 'use_phrases' => 1,
'default' => 0,
),
),
),
'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!',
),
'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' => ''
),
),
),
'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),
),
),
),
'Fields' => Array (
'PortalUserId' => Array ('type' => 'int', 'not_null' => 1),
'Username' => 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'),
'IPAddress' => 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),
'IPRestrictions' => Array ('type' => 'string'),
),
'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'),
'SubscribeToMailing' => Array ('type' => 'int'),
),
'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(
'Username' => Array ('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(
'Username' => Array ('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),
'Username' => Array ('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),
'Username' => Array ('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),
'IPAddress' => Array ('filter_block' => 'grid_date_range_filter', 'width' => 100, 'hidden' => 1),
),
),
),
);
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/ajax_form_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/ajax_form_helper.php (nonexistent)
+++ branches/5.2.x/core/units/helpers/ajax_form_helper.php (revision 14758)
@@ -0,0 +1,72 @@
+<?php
+
+ class AjaxFormHelper extends kHelper {
+
+ /**
+ * Sets error info as parameters in response object
+ * Expects that event status is not erSUCCESS
+ *
+ * @param kEvent $event
+ * @param Array $response
+ */
+ function prepareJSONErrors(&$event, &$response)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $error_msgs = Array ();
+
+ $field_errors = array_keys( $object->GetFieldErrors() );
+
+ foreach ($field_errors as $field) {
+ if ( !$object->GetErrorPseudo($field) ) {
+ continue;
+ }
+
+ if ( $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage') {
+ $field = 'l' . $this->Application->GetVar('m_lang') . '_' . $field;
+ }
+
+ $error_field = $object->GetFieldOption($field, 'error_field', false, $field);
+ $error_msgs[$field] = $object->GetErrorMsg($error_field);
+ }
+
+ $response['status'] = 'FAILED';
+ $response['field_errors'] = $error_msgs;
+ }
+
+ /**
+ * Sends JSON-encoded responce as event result to the browser
+ *
+ * @param kEvent $event
+ * @param Array $response
+ */
+ function sendResponse(&$event, $response)
+ {
+ $json_helper =& $this->Application->recallObject('JSONHelper');
+ /* @var $json_helper JSONHelper */
+
+ echo $json_helper->encode($response);
+
+ $event->status = kEvent::erSTOP;
+ }
+
+ /**
+ * Calls given event and returns nice JSON output
+ *
+ * @param kEvent $event
+ * @param string $call_event
+ * @param Array $params
+ */
+ function transitEvent(&$event, $call_event, $params = Array ())
+ {
+ $params['status'] = 'OK';
+ $event->CallSubEvent($call_event);
+
+ if ( $event->status != kEvent::erSUCCESS ) {
+ $this->prepareJSONErrors($event, $params);
+ }
+
+ $this->sendResponse($event, $params);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.2.x/core/units/helpers/ajax_form_helper.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/units/helpers/helpers_config.php
===================================================================
--- branches/5.2.x/core/units/helpers/helpers_config.php (revision 14757)
+++ branches/5.2.x/core/units/helpers/helpers_config.php (revision 14758)
@@ -1,73 +1,74 @@
<?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' => 'helpers',
'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
'RegisterClasses' => Array (
Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SearchHelper', 'class' => 'kSearchHelper', 'file' => 'search_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SectionsHelper', 'class' => 'kSectionsHelper', 'file' => 'sections_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PermissionsHelper', 'class' => 'kPermissionsHelper', 'file' => 'permissions_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModulesHelper', 'class' => 'kModulesHelper', 'file' => 'modules_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CategoryItemRewrite', 'class' => 'CategoryItemRewrite', 'file' => 'mod_rewrite_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RecursiveHelper', 'class' => 'kRecursiveHelper', 'file' => 'recursive_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FilenamesHelper', 'class' => 'kFilenamesHelper', 'file' => 'filenames_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ClipboardHelper', 'class' => 'kClipboardHelper', 'file' => 'clipboard_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ColumnPickerHelper', 'class' => 'kColumnPickerHelper', 'file' => 'col_picker_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ThemesHelper', 'class' => 'kThemesHelper', 'file' => 'themes_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CaptchaHelper', 'class' => 'kCaptchaHelper', 'file' => 'captcha_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PriorityHelper', 'class' => 'kPriorityHelper', 'file' => 'priority_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CurlHelper', 'class' => 'kCurlHelper', 'file' => 'curl_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountHelper', 'class' => 'kCountHelper', 'file' => 'count_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ImageHelper', 'class' => 'ImageHelper', 'file' => 'image_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FileHelper', 'class' => 'FileHelper', 'file' => 'file_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CategoryHelper', 'class' => 'CategoryHelper', 'file' => 'category_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CSVHelper', 'class' => 'kCSVHelper', 'file' => 'csv_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ChartHelper', 'class' => 'kChartHelper', 'file' => 'chart_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RatingHelper', 'class' => 'RatingHelper', 'file' => 'rating_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FCKHelper', 'class' => 'fckFCKHelper', 'file' => 'fck_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SpamHelper', 'class' => 'SpamHelper', 'file' => 'spam_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'TemplateHelper', 'class' => 'TemplateHelper', 'file' => 'template_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SiteConfigHelper', 'class' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MenuHelper', 'class' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'InpCustomFieldsHelper', 'class' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountryStatesHelper', 'class' => 'kCountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'BracketsHelper', 'class' => 'kBracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'kXMLHelper', 'class' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CatItemExportHelper', 'class' => 'kCatDBItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'EmailMessageHelper', 'class' => 'EmailMessageHelper', 'file' => 'email_message_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ListHelper', 'class' => 'ListHelper', 'file' => 'list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FormSubmissionHelper', 'class' => 'FormSubmissionHelper', 'file' => 'form_submission_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailboxHelper', 'class' => 'MailboxHelper', 'file' => 'mailbox_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'POP3Helper', 'class' => 'POP3Helper', 'file' => 'pop3_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MimeDecodeHelper', 'class' => 'MimeDecodeHelper', 'file' => 'mime_decode_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'UserHelper', 'class' => 'UserHelper', 'file' => 'user_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SiteHelper', 'class' => 'SiteHelper', 'file' => 'site_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'DeploymentHelper', 'class' => 'DeploymentHelper', 'file' => 'deployment_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'BackupHelper', 'class' => 'BackupHelper', 'file' => 'backup_helper.php', 'build_event' => ''),
+ Array ('pseudo' => 'AjaxFormHelper', 'class' => 'AjaxFormHelper', 'file' => 'ajax_form_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
),
);
\ No newline at end of file

Event Timeline