Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Wed, Feb 5, 10:36 PM

in-portal

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: branches/5.2.x/core/kernel/db/db_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/db_event_handler.php (revision 15064)
+++ branches/5.2.x/core/kernel/db/db_event_handler.php (revision 15065)
@@ -1,3312 +1,3429 @@
<?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 addressing 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 current Prefix_Special
* for variables being 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
*/
public function CheckPermission(kEvent &$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
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected 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);
}
/**
* Define alternative event processing method names
*
* @return void
* @see kEventHandler::$eventMethods
* @access protected
*/
protected 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
* @access public
*/
public function getPassedID(kEvent &$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 */
$select_clause = $this->Application->getUnitOption($object->Prefix, 'NavigationSelectClause', null);
return $list_helper->getNavigationResource($object, $event->getEventParam('list'), $event->Special == 'next', $select_clause);
}
elseif ( $event->Special == 'filter' ) {
// temporary object, used to print filter options only
return 0;
}
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
* @access protected
*/
protected function StoreSelectedIDs(kEvent &$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
* @access protected
*/
protected function getSelectedIDs(kEvent &$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
* @return void
* @access protected
*/
protected function OnStoreSelected(kEvent &$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());
}
}
/**
* Returns 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
* @return Array
* @access protected
*/
protected function getSubmittedFields(kEvent &$event)
{
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
$field_values = $items_info ? array_shift($items_info) : Array ();
return $field_values;
}
/**
* Returns fields, that are not allowed to be changed from request
*
* @param Array $hash
* @return Array
* @access protected
*/
protected function getRequestProtectedFields($hash)
{
// by default don't allow changing ID or foreign key from request
$fields = Array ();
$fields[] = $this->Application->getUnitOption($this->Prefix, 'IDField');
$parent_prefix = $this->Application->getUnitOption($this->Prefix, 'ParentPrefix');
if ( $parent_prefix ) {
$foreign_key = $this->Application->getUnitOption($this->Prefix, 'ForeignKey');
$fields[] = is_array($foreign_key) ? $foreign_key[$parent_prefix] : $foreign_key;
}
return $fields;
}
/**
* Removes any information about current/selected ids
* from Application variables and Session
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function clearSelectedIDs(kEvent &$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
* @return void
* @access protected
*/
protected function dbBuild(&$object, kEvent &$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
* @access protected
*/
protected function checkItemStatus(kEvent &$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
* @return void
* @access protected
*/
protected function _errorNotFound(kEvent &$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
*/
protected function OnItemBuild(kEvent &$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_autoload = $event->getEventParam('skip_autoload');
if ( $auto_load && !$skip_autoload ) {
$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 permission 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 ( $this->Application->GetVar('t') != $template ) {
// don't perform "no_permission" redirect if already on a "no_permission" template
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 sub-tables array from configs
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnTempHandlerBuild(kEvent &$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
* @access protected
*/
protected function UseTempTables(kEvent &$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);
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(kEvent &$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( is_array($id) ? false : $id );
}
}
/**
* Builds list
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
protected function OnListBuild(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
/*if ( $this->Application->isDebugMode() ) {
$event_params = http_build_query($event->getEventParams());
$this->Application->Debugger->appendHTML('InitList "<strong>' . $event->getPrefixSpecial() . '</strong>" (' . $event_params . ')');
}*/
$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();
if ( $event->getEventParam('skip_parent_filter') === false ) {
$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', '');
}
/**
* Returns special of main item for linking with sub-item
*
* @param kEvent $event
* @return string
* @access protected
*/
protected function getMainSpecial(kEvent &$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(kEvent &$event)
{
}
/**
* Set's new per-page for grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPerPage(kEvent &$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');
}
}
/**
* Occurs when page is changed (only for hooking)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPage(kEvent &$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 ) {
$this->_passListParams($event, 'page');
}
}
/**
* Passes through main list pagination and sorting
*
* @param kEvent $event
* @param string $skip_var
* @return void
* @access protected
*/
protected 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
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetPagination(kEvent &$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
* @access protected
*/
protected function getPerPage(kEvent &$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
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetSorting(kEvent &$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(kEvent &$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(kEvent &$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
* @return void
* @access protected
*/
protected function AddFilters(kEvent &$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);
}
}
}
}
// add view filter
$view_filter = $this->Application->RecallVar($event->getPrefixSpecial() . '_view_filter');
if ( $view_filter ) {
$view_filter = unserialize($view_filter);
$temp_filter =& $this->Application->makeClass('kMultipleFilter');
/* @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++;
}
}
// add item filter
if ( $object->isMainList() ) {
$this->applyItemFilters($event);
}
}
/**
* Applies item filters
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function applyItemFilters(&$event)
{
$filter_values = $this->Application->GetVar('filters', Array ());
if ( !$filter_values ) {
return;
}
$object =& $event->getObject();
/* @var $object kDBList */
$where_clause = Array (
'ItemPrefix = ' . $this->Conn->qstr($object->Prefix),
'FilterField IN (' . implode(',', $this->Conn->qstrArray(array_keys($filter_values))) . ')',
'Enabled = 1',
);
$sql = 'SELECT *
FROM ' . $this->Application->getUnitOption('item-filter', 'TableName') . '
WHERE (' . implode(') AND (', $where_clause) . ')';
$filters = $this->Conn->Query($sql, 'FilterField');
foreach ($filters as $filter_field => $filter_data) {
$filter_value = $filter_values[$filter_field];
if ( "$filter_value" === '' ) {
// ListManager don't pass empty values, but check here just in case
continue;
}
$table_name = $object->isVirtualField($filter_field) ? '' : '%1$s.';
switch ($filter_data['FilterType']) {
case 'radio':
$filter_value = $table_name . '`' . $filter_field . '` = ' . $this->Conn->qstr($filter_value);
break;
case 'checkbox':
$filter_value = explode('|', substr($filter_value, 1, -1));
$filter_value = $this->Conn->qstrArray($filter_value, 'escape');
if ( $object->GetFieldOption($filter_field, 'multiple') ) {
$filter_value = $table_name . '`' . $filter_field . '` LIKE "%|' . implode('|%" OR ' . $table_name . '`' . $filter_field . '` LIKE "%|', $filter_value) . '|%"';
}
else {
$filter_value = $table_name . '`' . $filter_field . '` IN (' . implode(',', $filter_value) . ')';
}
break;
case 'range':
$filter_value = $this->Conn->qstrArray(explode('-', $filter_value));
$filter_value = $table_name . '`' . $filter_field . '` BETWEEN ' . $filter_value[0] . ' AND ' . $filter_value[1];
break;
}
$object->addFilter('item_filter_' . $filter_field, $filter_value, $object->isVirtualField($filter_field) ? kDBList::HAVING_FILTER : kDBList::WHERE_FILTER);
}
}
/**
* Set's new sorting for list
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnSetSorting(&$event)
+ protected function OnSetSorting(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnSetSortingDirect(&$event)
+ protected function OnSetSortingDirect(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnResetSorting(&$event)
+ protected function OnResetSorting(kEvent &$event)
{
$this->setListSetting($event, 'Sortings');
}
/**
* Sets grid refresh interval
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnSetAutoRefreshInterval(&$event)
+ protected function OnSetAutoRefreshInterval(kEvent &$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);
+ $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
+ * @return void
+ * @access protected
*/
- function OnAutoRefreshToggle(&$event)
+ protected function OnAutoRefreshToggle(kEvent &$event)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
- if (!$refresh_intervals) {
- return ;
+ if ( !$refresh_intervals ) {
+ return;
}
- $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
- $auto_refresh = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name);
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
+ $auto_refresh = $this->Application->RecallPersistentVar($event->getPrefixSpecial() . '_auto_refresh.' . $view_name);
- if ($auto_refresh === false) {
+ 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() . '_refresh_interval.' . $view_name, $refresh_intervals[0]);
}
- $this->Application->StorePersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name, $auto_refresh ? 0 : 1);
+ $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
+ * special requested, then use list query
*
* @param kEvent $event
+ * @return string
* @access protected
*/
- function ItemPrepareQuery(&$event)
+ protected function ItemPrepareQuery(kEvent &$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
+ * @return string
* @access protected
*/
- function ListPrepareQuery(&$event)
+ protected function ListPrepareQuery(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$sqls = $object->getFormOption('ListSQLs', Array ());
- return $sqls[ array_key_exists($event->Special, $sqls) ? $event->Special : '' ];
+ 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)
+ protected function customProcessing(kEvent &$event, $type)
{
}
/* Edit Events mostly used in Admin */
/**
* Creates new kDBItem
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
- list($id,$field_values) = each($items_info);
- $object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+
+ if ( !$items_info ) {
+ return;
}
- $this->customProcessing($event,'before');
+ list($id, $field_values) = each($items_info);
+ $object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
+
+ $this->customProcessing($event, 'before');
- //look at kDBItem' Create for ForceCreateId description, it's rarely used and is NOT set by default
+ // 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);
+ $this->customProcessing($event, 'after');
+ $event->SetRedirectParam('opener', 'u');
+ return;
}
+
+ $event->redirect = false;
+ $event->status = kEvent::erFAIL;
+ $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
+ $object->setID($id);
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$this->_update($event);
$event->SetRedirectParam('opener', 'u');
}
/**
* Updates data in database based on request
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function _update(kEvent &$event)
{
$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->getRequestProtectedFields($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;
}
}
}
}
/**
* Delete's kDBItem object
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnDelete(&$event)
+ protected function OnDelete(kEvent &$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ 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));
+ $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
+ * @return void
+ * @access protected
*/
- function OnDeleteAll(&$event)
+ protected function OnDeleteAll(kEvent &$event)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName');
$ids = $this->Conn->GetCol($sql);
- if ($ids) {
+ 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
+ * @return void
* @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->Clear(0);
- $this->Application->SetVar($event->getPrefixSpecial().'_SaveEvent', 'OnCreate');
+ $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
- if ($event->getEventParam('top_prefix') != $event->Prefix) {
+ if ( $event->getEventParam('top_prefix') != $event->Prefix ) {
// this is subitem prefix, so use main item special
- $table_info = $object->getLinkedInfo( $this->getMainSpecial($event) );
+ $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)
+ protected function OnCancel(kEvent &$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)
+ protected function OnMassDelete(kEvent &$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
+ * @return void
+ * @access protected
*/
- function setTempWindowID(&$event)
+ protected function setTempWindowID(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnEdit(&$event)
+ protected function OnEdit(kEvent &$event)
{
$this->setTempWindowID($event);
$ids = $this->StoreSelectedIDs($event);
- $this->Application->RemoveVar( $this->_getPendingActionVariableName($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));
+ $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)
+ protected function OnSave(kEvent &$event)
{
$event->CallSubEvent('OnPreSave');
- if ($event->status != kEvent::erSUCCESS) {
- return ;
+ 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 ;
+ 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);
+ $event->SetRedirectParam('opener', 'u');
$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)
+ /**
+ * Saves changes made in temporary table to log
+ *
+ * @param string $changes_var_name
+ * @param bool $save
+ * @return void
+ * @access public
+ */
+ public 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)
+ protected function OnCancelEdit(kEvent &$event)
{
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler', Array ('parent_event' => &$event));
/* @var $temp_handler kTempTablesHandler */
$temp_handler->CancelEdit();
$this->clearSelectedIDs($event);
$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
+ * @access public
*/
- function isNewItemCreate(&$event)
+ public function isNewItemCreate(kEvent &$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)
+ protected function OnPreSave(kEvent &$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 ;
}
// don't just call OnUpdate event here, since it maybe overwritten to Front-End specific behavior
$this->_update($event);
}
/**
* [HOOK] Saves sub-item
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveSubItem(&$event)
+ protected function OnPreSaveSubItem(kEvent &$event)
{
$not_created = $this->isNewItemCreate($event);
$event->CallSubEvent($not_created ? 'OnCreate' : 'OnUpdate');
- if ($event->status == kEvent::erSUCCESS) {
+ 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
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndGo(&$event)
+ protected function OnPreSaveAndGo(kEvent &$event)
{
$event->CallSubEvent('OnPreSave');
- if ($event->status == kEvent::erSUCCESS) {
+ 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
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndGoToTab(&$event)
+ protected function OnPreSaveAndGoToTab(kEvent &$event)
{
$event->CallSubEvent('OnPreSave');
- if ($event->status==kEvent::erSUCCESS) {
- $event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
+
+ 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
+ * @return void
+ * @access protected
*/
- function OnUpdateAndGoToTab(&$event)
+ protected function OnUpdateAndGoToTab(kEvent &$event)
{
$event->setPseudoClass('_List');
$event->CallSubEvent('OnUpdate');
- if ($event->status==kEvent::erSUCCESS) {
- $event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
+
+ 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)
+ protected function OnPreCreate(kEvent &$event)
{
$this->setTempWindowID($event);
$this->clearSelectedIDs($event);
$this->Application->SetVar('m_lang', $this->Application->GetDefaultLanguageId());
- $object =& $event->getObject( Array ('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$temp_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)
+ protected function OnPreSaveCreated(kEvent &$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$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)
+ protected function OnReset(kEvent &$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)
+ protected function iterateItems(kEvent &$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...
+ * Clones selected items in list
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnMassClone(&$event)
+ protected function OnMassClone(kEvent &$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return ;
+ 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)
+ /**
+ * Checks if given value is present in given array
+ *
+ * @param Array $records
+ * @param string $field
+ * @param mixed $value
+ * @return bool
+ * @access protected
+ */
+ protected 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)
+ protected function OnPreSavePopup(kEvent &$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
+ * Occurs before loading item, 'id' parameter
+ * allows to get id of item being loaded
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemLoad(&$event)
+ protected function OnBeforeItemLoad(kEvent &$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)
+ protected function OnAfterItemLoad(kEvent &$event)
{
}
/**
* Occurs before creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$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)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
}
/**
* Occurs after updating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->IsTempTable() ) {
$this->_proccessPendingActions($event);
}
}
/**
* Occurs before deleting item, id of item being
* deleted is stored as 'id' event param
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
}
/**
- * Occurse after deleting item, id of deleted item
+ * Occurs after deleting item, id of deleted item
* is stored as 'id' param of event
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$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
+ * Occurs after an item has been copied to temp
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterCopyToTemp(&$event)
+ protected function OnAfterCopyToTemp(kEvent &$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)
+ protected function OnBeforeDeleteFromLive(kEvent &$event)
{
}
/**
- * Occures before an item is copied to live table (after all foreign keys have been updated)
+ * Occurs 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
+ * @return void
+ * @access protected
*/
- function OnBeforeCopyToLive(&$event)
+ protected function OnBeforeCopyToLive(kEvent &$event)
{
}
/**
- * Occures after an item has been copied to live table
+ * Occurs after an item has been copied to live table
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterCopyToLive(&$event)
+ protected function OnAfterCopyToLive(kEvent &$event)
{
$this->_proccessPendingActions($event);
}
/**
* Processing file pending actions (e.g. delete scheduled files)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function _proccessPendingActions(&$event)
+ protected function _proccessPendingActions(kEvent &$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'] );
+ unlink($data['file']);
}
}
$this->Application->RemoveVar($var_name);
}
}
/**
* Returns variable name, used to store pending file actions
*
* @param kEvent $event
* @return string
+ * @access protected
*/
- function _getPendingActionVariableName(&$event)
+ protected function _getPendingActionVariableName(kEvent &$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)
+ protected function OnBeforeClone(kEvent &$event)
{
}
/**
- * Occures after an item has been cloned
+ * Occurs after an item has been cloned
* Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterClone(&$event)
+ protected function OnAfterClone(kEvent &$event)
{
}
/**
- * Occures after list is queried
+ * Occurs after list is queried
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterListQuery(&$event)
+ protected function OnAfterListQuery(kEvent &$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)
+ protected function finalizePopup(kEvent &$event)
{
$event->SetRedirectParam('opener', 'u');
}
/**
* Create search filters based on search query
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnSearch(&$event)
+ protected function OnSearch(kEvent &$event)
{
$event->setPseudoClass('_List');
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->performSearch($event);
}
/**
* Clear search keywords
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnSearchReset(&$event)
+ protected function OnSearchReset(kEvent &$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
+ * @return void
+ * @access protected
+ * @deprecated
*/
- function OnSetFilter(&$event)
+ protected function OnSetFilter(kEvent &$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 = $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) );
+ $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)
+ protected function OnSetFilterPattern(kEvent &$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
+ * @return void
+ * @access protected
*/
- function FilterAction(&$event)
+ protected function FilterAction(kEvent &$event)
{
- $view_filter = Array();
- $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
- switch ($event->Name)
- {
+ $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;
+
+ default:
+ $filter_value = 0;
+ break;
}
- foreach($filter_menu['Filters'] as $filter_key => $filter_params)
- {
- if(!$filter_params) continue;
+ 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) );
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_view_filter', serialize($view_filter));
}
/**
* Enter description here...
*
* @param kEvent $event
* @access protected
*/
- protected function OnPreSaveAndOpenTranslator(&$event)
+ protected function OnPreSaveAndOpenTranslator(kEvent &$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);
+ $event->setRedirectParams($redirect_params);
// 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
+ * @return void
+ * @access protected
*/
- function RemoveRequiredFields(&$object)
+ protected 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
+ * @return void
+ * @access protected
*/
- function OnSelectUser(&$event)
+ protected function OnSelectUser(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$items_info = $this->Application->GetVar('u');
if ( $items_info ) {
- $user_id = array_shift( array_keys($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
+ * @return void
+ * @access protected
*/
- function OnExport(&$event)
+ protected function OnExport(kEvent &$event)
{
$selected_ids = $this->StoreSelectedIDs($event);
- if (implode(',', $selected_ids) == '') {
+ 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->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;
+ $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, kEvent &$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
+ * @access public
*/
- function getCustomExportColumns(&$event)
+ public function getCustomExportColumns(kEvent &$event)
{
return Array();
}
/**
* Export form validation & processing
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnExportBegin(&$event)
+ protected function OnExportBegin(kEvent &$event)
{
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
+
$export_helper->OnExportBegin($event);
}
/**
* Enter description here...
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnExportCancel(&$event)
+ protected function OnExportCancel(kEvent &$event)
{
$this->OnGoBack($event);
}
/**
* Allows configuring export options
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeExportBegin(&$event)
+ protected function OnBeforeExportBegin(kEvent &$event)
{
}
/**
* Deletes export preset
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnDeleteExportPreset(&$event)
+ protected function OnDeleteExportPreset(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndChangeLanguage(&$event)
+ protected function OnPreSaveAndChangeLanguage(kEvent &$event)
{
- if ($this->UseTempTables($event)) {
+ if ( $this->UseTempTables($event) ) {
$event->CallSubEvent('OnPreSave');
}
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
$this->Application->SetVar('m_lang', $this->Application->GetVar('language'));
$data = $this->Application->GetVar('st_id');
- if ($data) {
+ 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)
+ protected function OnUploadFile(kEvent &$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) {
+ 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 ;
+ return;
}
- if (!$this->_checkFlashUploaderPermission($event)) {
+ if ( !$this->_checkFlashUploaderPermission($event) ) {
// 403 Forbidden
header('HTTP/1.0 403 You don\'t have permissions to upload');
echo $default_msg;
- return ;
+ return;
}
$value = $this->Application->GetVar('Filedata');
- if (!$value || ($value['error'] != UPLOAD_ERR_OK)) {
+ 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 ;
+ return;
}
$tmp_path = WRITEABLE . '/tmp/';
$fname = $value['name'];
$id = $this->Application->GetVar('id');
- if ($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)) {
+ 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 ;
+ return;
}
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$fname = $file_helper->ensureUniqueFilename($tmp_path, $fname);
- if ($storage_format) {
+ 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);
+ rename($tmp_name, $tmp_path . $fname);
}
else {
- move_uploaded_file($value['tmp_name'], $tmp_path.$fname);
+ move_uploaded_file($value['tmp_name'], $tmp_path . $fname);
}
echo preg_replace('/^' . preg_quote($id, '/') . '_/', '', $fname);
$this->deleteTempFiles($tmp_path);
}
/**
* Delete temporary files, that won't be used for sure
*
* @param string $path
+ * @return void
+ * @access protected
*/
- function deleteTempFiles($path)
+ protected 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)
+ protected function _checkFlashUploaderPermission(kEvent &$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) {
+ 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...
+ * Remembers, that file should be deleted on item's save from temp table
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnDeleteFile(&$event)
+ protected function OnDeleteFile(kEvent &$event)
{
$event->status = kEvent::erSTOP;
- if (strpos($this->Application->GetVar('file'), '../') !== false) {
- return ;
+ if ( strpos($this->Application->GetVar('file'), '../') !== false ) {
+ return;
}
- $object =& $event->getObject( Array ('skip_autoload' => true) );
- $options = $object->GetFieldOptions( $this->Application->GetVar('field') );
+ $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...
+ * Returns url for viewing uploaded file
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnViewFile(&$event)
+ protected function OnViewFile(kEvent &$event)
{
$event->status = kEvent::erSTOP;
$file = $this->Application->GetVar('file');
- if ((strpos($file, '../') !== false) || (trim($file) !== $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 ;
+ return;
}
- $object =& $event->getObject( Array ('skip_autoload' => true));
+ $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')) {
+ 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')) {
+ 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)) {
+ 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
+ * @return void
+ * @access protected
*/
- function OnValidateMInputFields(&$event)
+ protected function OnValidateMInputFields(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnValidateField(&$event)
+ protected function OnValidateField(kEvent &$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, $this->getRequestProtectedFields($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);
}
$ajax_form_helper =& $this->Application->recallObject('AjaxFormHelper');
/* @var $ajax_form_helper AjaxFormHelper */
$response['other_errors'] = $ajax_form_helper->getErrorMessages($object);
$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
+ * @return void
+ * @access protected
*/
- function OnSuggestValues(&$event)
+ protected function OnSuggestValues(kEvent &$event)
{
- if (!$this->Application->isAdminUser) {
+ if ( !$this->Application->isAdminUser ) {
// very careful here, because this event allows to
// view every object field -> limit only to logged-in admins
- return ;
+ 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 ;
+ if ( !$field || !$cur_value || !$object->isField($field) ) {
+ return;
}
$limit = $this->Application->GetVar('limit');
- if (!$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.'
+ $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
+ * @return void
+ * @access protected
*/
- function OnSaveWidths(&$event)
+ protected function OnSaveWidths(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnBeforeCSVLineImport(&$event)
+ protected function OnBeforeCSVLineImport(kEvent &$event)
{
// abstract, for hooking
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCloneSubItem(&$event)
+ protected function OnCloneSubItem(kEvent &$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)
+ protected function OnGetConstrainInfo(kEvent &$event)
{
$event->setEventParam('constrain_info', Array ('', ''));
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/db/cat_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/cat_event_handler.php (revision 15064)
+++ branches/5.2.x/core/kernel/db/cat_event_handler.php (revision 15065)
@@ -1,2936 +1,2953 @@
<?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 kCatDBEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnSaveSettings' => Array ('self' => 'add|edit|advanced:import'),
'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'),
'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
'OnAfterDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
'OnCopy' => Array ('self' => true),
'OnDownloadFile' => Array ('self' => 'view'),
'OnCancelAction' => Array ('self' => true),
'OnItemBuild' => Array ('self' => true),
'OnMakeVote' => Array ('self' => true),
'OnReviewHelpful' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $this->getPassedID($event);
if ( $object->Load($id) ) {
$actions =& $this->Application->recallObject('kActions');
/* @var $actions Params */
$actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ( $use_pending_editing && $event->Special != 'original' ) {
$this->Application->SetVar($event->Prefix . '.original_id', $object->GetDBField('OrgId'));
}
}
else {
$object->setID($id);
}
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( !$this->Application->isAdmin ) {
if ( $event->Name == 'OnSetSortingDirect' ) {
// allow sorting on front event without view permission
return true;
}
}
if ( $event->Name == 'OnExport' ) {
// save category_id before doing export
$this->Application->LinkVar('m_cat_id');
}
if ( in_array($event->Name, $this->_getMassPermissionEvents()) ) {
$items = $this->_getPermissionCheckInfo($event);
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
if ( ($event->Name == 'OnSave') && array_key_exists(0, $items) ) {
// adding new item (ID = 0)
$perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0;
}
else {
// leave only items, that can be edited
$ids = Array ();
$check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
foreach ($items as $item_id => $item_data) {
if ( $perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0 ) {
$ids[] = $item_id;
}
}
if ( !$ids ) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
$perm_value = true;
$event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
}
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
$export_events = Array ('OnSaveSettings', 'OnResetSettings', 'OnExportBegin');
if ( in_array($event->Name, $export_events) ) {
// when import settings before selecting target import category
return $this->Application->CheckPermission('in-portal:main_import.view');
}
if ( $event->Name == 'OnProcessSelected' ) {
if ( $this->Application->RecallVar('dst_field') == 'ImportCategory' ) {
// when selecting target import category
return $this->Application->CheckPermission('in-portal:main_import.view');
}
}
return parent::CheckPermission($event);
}
/**
* Returns events, that require item-based (not just event-name based) permission check
*
* @return Array
*/
function _getMassPermissionEvents()
{
return Array (
'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
'OnCut',
);
}
/**
* Returns category item IDs, that require permission checking
*
* @param kEvent $event
* @return string
*/
function _getPermissionCheckIDs(&$event)
{
if ($event->Name == 'OnSave') {
$selected_ids = implode(',', $this->getSelectedIDs($event, true));
if (!$selected_ids) {
$selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
}
}
else {
// OnEdit, OnMassDelete events, when items are checked in grid
$selected_ids = implode(',', $this->StoreSelectedIDs($event));
}
return $selected_ids;
}
/**
* Returns information used in permission checking
*
* @param kEvent $event
* @return Array
*/
function _getPermissionCheckInfo(&$event)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
// when saving data from temp table to live table check by data from temp table
$item_ids = $this->_getPermissionCheckIDs($event);
$items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave');
if (!$items) {
// when item not present in temp table, then permission is not checked, because there are no data in db to check
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list ($id, $fields_hash) = each($items_info);
if (array_key_exists('CategoryId', $fields_hash)) {
$item_category = $fields_hash['CategoryId'];
}
else {
$item_category = $this->Application->GetVar('m_cat_id');
}
$items[$id] = Array (
'CreatedById' => $this->Application->RecallVar('use_id'),
'CategoryId' => $item_category,
);
}
return $items;
}
/**
* Add selected items to clipboard with mode = COPY (CLONE)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCopy(&$event)
{
$this->Application->RemoveVar('clipboard');
$clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
/* @var $clipboard_helper kClipboardHelper */
$clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Add selected items to clipboard with mode = CUT
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCut(&$event)
{
$this->Application->RemoveVar('clipboard');
$clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
/* @var $clipboard_helper kClipboardHelper */
$clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Checks permission for OnPaste event
*
* @param kEvent $event
* @return bool
*/
function _checkPastePermission(&$event)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$category_id = $this->Application->GetVar('m_cat_id');
if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
return true;
}
/**
* Performs category item paste
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPaste(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event) ) {
$event->status = kEvent::erFAIL;
return;
}
$clipboard_data = $event->getEventParam('clipboard_data');
if ( !$clipboard_data['cut'] && !$clipboard_data['copy'] ) {
return;
}
if ( $clipboard_data['copy'] ) {
$temp =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
$this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone"
$temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']);
}
if ( $clipboard_data['cut'] ) {
$object =& $this->Application->recallObject($event->getPrefixSpecial() . '.item', $event->Prefix, Array ('skip_autoload' => true));
/* @var $object kCatDBItem */
foreach ($clipboard_data['cut'] as $id) {
$object->Load($id);
$object->MoveToCat();
}
}
}
/**
* 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)
+ protected function OnMassDelete(kEvent &$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
$to_delete = Array ();
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ( $recycle_bin ) {
$rb =& $this->Application->recallObject('c.recycle', null, array ('skip_autoload' => true));
/* @var $rb CategoriesItem */
$rb->Load($recycle_bin);
$object =& $this->Application->recallObject($event->Prefix . '.recycleitem', null, Array ('skip_autoload' => true));
/* @var $object kCatDBItem */
foreach ($ids as $id) {
$object->Load($id);
if ( preg_match('/^' . preg_quote($rb->GetDBField('ParentPath'), '/') . '/', $object->GetDBField('ParentPath')) ) {
$to_delete[] = $id;
continue;
}
$object->MoveToCat($recycle_bin);
}
$ids = $to_delete;
}
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$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);
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function getTypeClauses(&$event)
{
$types = $event->getEventParam('types');
$types = $types ? explode(',', $types) : Array ();
$except_types = $event->getEventParam('except');
$except_types = $except_types ? explode(',', $except_types) : Array ();
$type_clauses = Array();
$user_id = $this->Application->RecallVar('user_id');
$owner_field = $this->getOwnerField($event->Prefix);
$type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id;
$type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id;
$type_clauses['my_items']['having_filter'] = false;
$type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['pick']['having_filter'] = false;
$type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1';
$type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1';
$type_clauses['hot']['having_filter'] = true;
$type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1';
$type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1';
$type_clauses['pop']['having_filter'] = true;
$type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1';
$type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1';
$type_clauses['new']['having_filter'] = true;
$type_clauses['displayed']['include'] = '';
$displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids');
if ($displayed) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')';
}
else {
$type_clauses['displayed']['except'] = '';
}
$type_clauses['displayed']['having_filter'] = false;
if (in_array('search', $types) || in_array('search', $except_types)) {
$event_mapping = Array (
'simple' => 'OnSimpleSearch',
'subsearch' => 'OnSubSearch',
'advanced' => 'OnAdvancedSearch'
);
$keywords = $event->getEventParam('keyword_string');
$type = $this->Application->GetVar('search_type', 'simple');
if ( $keywords ) {
// processing keyword_string param of ListProducts tag
$this->Application->SetVar('keywords', $keywords);
$type = 'simple';
}
$search_event = $event_mapping[$type];
$this->$search_event($event);
$object =& $event->getObject();
/* @var $object kDBList */
$search_sql = ' FROM ' . TABLE_PREFIX . 'ses_' . $this->Application->GetSID() . '_' . TABLE_PREFIX . 'Search
search_result LEFT JOIN %1$s ON %1$s.ResourceId = search_result.ResourceId';
$sql = str_replace('FROM %1$s', $search_sql, $object->GetPlainSelectSQL());
$object->SetSelectSQL($sql);
$object->addCalculatedField('Relevance', 'search_result.Relevance');
$object->AddOrderField('search_result.Relevance', 'desc', true);
$type_clauses['search']['include'] = 'PrimaryCat = 1 AND ('.TABLE_PREFIX.'Categories.Status = '.STATUS_ACTIVE.')';
$type_clauses['search']['except'] = 'PrimaryCat = 1 AND ('.TABLE_PREFIX.'Categories.Status = '.STATUS_ACTIVE.')';
$type_clauses['search']['having_filter'] = false;
}
if (in_array('related', $types) || in_array('related', $except_types)) {
$related_to = $event->getEventParam('related_to');
if (!$related_to) {
$related_prefix = $event->Prefix;
}
else {
$sql = 'SELECT Prefix
FROM '.TABLE_PREFIX.'ItemTypes
WHERE ItemName = '.$this->Conn->qstr($related_to);
$related_prefix = $this->Conn->GetOne($sql);
}
$rel_table = $this->Application->getUnitOption('rel', 'TableName');
$item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
if ($item_type == 0) {
trigger_error('<strong>ItemType</strong> not defined for prefix <strong>' . $event->Prefix . '</strong>', E_USER_WARNING);
}
// process case, then this list is called inside another list
$prefix_special = $event->getEventParam('PrefixSpecial');
if (!$prefix_special) {
$prefix_special = $this->Application->Parser->GetParam('PrefixSpecial');
}
$id = false;
if ($prefix_special !== false) {
$processed_prefix = $this->Application->processPrefix($prefix_special);
if ($processed_prefix['prefix'] == $related_prefix) {
// printing related categories within list of items (not on details page)
$list =& $this->Application->recallObject($prefix_special);
/* @var $list kDBList */
$id = $list->GetID();
}
}
if ($id === false) {
// printing related categories for single item (possibly on details page)
if ($related_prefix == 'c') {
$id = $this->Application->GetVar('m_cat_id');
}
else {
$id = $this->Application->GetVar($related_prefix . '_id');
}
}
$p_item =& $this->Application->recallObject($related_prefix.'.current', null, Array('skip_autoload' => true));
/* @var $p_item kCatDBItem */
$p_item->Load( (int)$id );
$p_resource_id = $p_item->GetDBField('ResourceId');
$sql = 'SELECT SourceId, TargetId FROM '.$rel_table.'
WHERE
(Enabled = 1)
AND (
(Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(Type = 1
AND (
(SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.')
)
)
)';
$related_ids_array = $this->Conn->Query($sql);
$related_ids = Array();
foreach ($related_ids_array as $record) {
$related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ];
}
if (count($related_ids) > 0) {
$type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
$type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
}
else {
$type_clauses['related']['include'] = '0';
$type_clauses['related']['except'] = '1';
}
$type_clauses['related']['having_filter'] = false;
}
if (in_array('favorites', $types) || in_array('favorites', $except_types)) {
$sql = 'SELECT ResourceId
FROM '.$this->Application->getUnitOption('fav', 'TableName').'
WHERE PortalUserId = '.$this->Application->RecallVar('user_id');
$favorite_ids = $this->Conn->GetCol($sql);
if ($favorite_ids) {
$type_clauses['favorites']['include'] = '%1$s.ResourceId IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
$type_clauses['favorites']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
}
else {
$type_clauses['favorites']['include'] = 0;
$type_clauses['favorites']['except'] = 1;
}
$type_clauses['favorites']['having_filter'] = false;
}
return $type_clauses;
}
/**
* Returns SQL clause, that will help to select only data from specified category & it's children
*
* @param int $category_id
* @return string
*/
function getCategoryLimitClause($category_id)
{
if (!$category_id) {
return false;
}
$tree_indexes = $this->Application->getTreeIndex($category_id);
if (!$tree_indexes) {
// id of non-existing category was given
return 'FALSE';
}
return TABLE_PREFIX.'Categories.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight'];
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
// add category filter if needed
if ($event->Special != 'showall' && $event->Special != 'user') {
if ( (string)$event->getEventParam('parent_cat_id') !== '' ) {
$parent_cat_id = $event->getEventParam('parent_cat_id');
}
else {
$parent_cat_id = $this->Application->GetVar('c_id');
if (!$parent_cat_id) {
$parent_cat_id = $this->Application->GetVar('m_cat_id');
}
if (!$parent_cat_id) {
$parent_cat_id = 0;
}
}
if ("$parent_cat_id" == '0') {
// replace "0" category with "Content" category id (this way template
$parent_cat_id = $this->Application->getBaseCategory();
}
if ((string)$parent_cat_id != 'any') {
if ($event->getEventParam('recursive')) {
$filter_clause = $this->getCategoryLimitClause($parent_cat_id);
if ($filter_clause !== false) {
$object->addFilter('category_filter', $filter_clause);
}
$object->addFilter('primary_filter', 'PrimaryCat = 1');
}
else {
$object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id );
}
}
else {
$object->addFilter('primary_filter', 'PrimaryCat = 1');
}
}
else {
$object->addFilter('primary_filter', 'PrimaryCat = 1');
// if using recycle bin don't show items from there
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ($recycle_bin) {
$object->addFilter('recyclebin_filter', TABLE_PREFIX.'CategoryItems.CategoryId <> '.$recycle_bin);
}
}
if ($event->Special == 'user') {
$editable_user = $this->Application->GetVar('u_id');
$object->addFilter('owner_filter', '%1$s.'.$this->getOwnerField($event->Prefix).' = '.$editable_user);
}
// add permission filter
if ($this->Application->RecallVar('user_id') == USER_ROOT) {
// for "root" CATEGORY.VIEW permission is checked for items lists too
$view_perm = 1;
}
else {
// for any real user itemlist view permission is checked instead of CATEGORY.VIEW
$count_helper =& $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
list ($view_perm, $view_filter) = $count_helper->GetPermissionClause($event->Prefix, 'perm');
$object->addFilter('perm_filter2', $view_filter);
}
$object->addFilter('perm_filter', 'perm.PermId = '.$view_perm);
$types = $event->getEventParam('types');
$this->applyItemStatusFilter($object, $types);
$except_types = $event->getEventParam('except');
$type_clauses = $this->getTypeClauses($event);
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->SetComplexFilter($event, $type_clauses, $types, $except_types);
}
/**
* Adds filter that filters out items with non-required statuses
*
* @param kDBList $object
* @param string $types
*/
function applyItemStatusFilter(&$object, $types)
{
// Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID]
$pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing');
if (!$this->Application->isAdminUser) {
$types = explode(',', $types);
if (in_array('my_items', $types)) {
$allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING);
$object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')');
if ($pending_editing) {
$user_id = $this->Application->RecallVar('user_id');
$this->applyPendingEditingFilter($object, $user_id);
}
}
else {
$object->addFilter('status_filter', '(%1$s.Status = ' . STATUS_ACTIVE . ') AND (' . TABLE_PREFIX . 'Categories.Status = ' . STATUS_ACTIVE . ')');
if ($pending_editing) {
// if category item uses pending editing abilities, then in no cases show pending copies on front
$object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL');
}
}
}
else {
if ($pending_editing) {
$this->applyPendingEditingFilter($object);
}
}
}
/**
* Adds filter, that removes live items if they have pending editing copies
*
* @param kDBList $object
* @param int $user_id
*/
function applyPendingEditingFilter(&$object, $user_id = null)
{
$sql = 'SELECT OrgId
FROM '.$object->TableName.'
WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL';
if (isset($user_id)) {
$owner_field = $this->getOwnerField($object->Prefix);
$sql .= ' AND '.$owner_field.' = '.$user_id;
}
$pending_ids = $this->Conn->GetCol($sql);
if ($pending_ids) {
$object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')');
}
}
/**
* Adds calculates fields for item statuses
*
* @param kDBItem|kDBList $object
* @param kEvent $event
* @return void
* @access protected
*/
protected function prepareObject(&$object, kEvent &$event)
{
$this->prepareItemStatuses($event);
$object->addCalculatedField('CachedNavbar', 'l' . $this->Application->GetVar('m_lang') . '_CachedNavbar');
if ( $event->Special == 'export' || $event->Special == 'import' ) {
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->prepareExportColumns($event);
}
}
/**
* Creates calculated fields for all item statuses based on config settings
*
* @param kEvent $event
*/
function prepareItemStatuses(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if (!$property_map) {
return ;
}
// new items
$object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2,
IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
$this->Application->ConfigValue($property_map['NewDays']).
'*3600*24), 1, 0),
%1$s.NewItem
)');
// hot items (cache updated every hour)
if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
$serial_name = $this->Application->incrementCacheSerial($event->Prefix, null, false);
$hot_limit = $this->Application->getCache($property_map['HotLimit'] . '[%' . $serial_name . '%]');
}
else {
$hot_limit = $this->Application->getDBCache($property_map['HotLimit']);
}
if ($hot_limit === false) {
$hot_limit = $this->CalculateHotLimit($event);
}
$object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2,
IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0),
%1$s.HotItem
)');
// popular items
$object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2,
IF(%1$s.CachedVotesQty >= '.
$this->Application->ConfigValue($property_map['MinPopVotes']).
' AND %1$s.CachedRating >= '.
$this->Application->ConfigValue($property_map['MinPopRating']).
', 1, 0),
%1$s.PopItem)');
}
/**
* Calculates hot limit for current item's table
*
* @param kEvent $event
* @return float
* @access protected
*/
protected function CalculateHotLimit(&$event)
{
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if ( !$property_map ) {
return 0.00;
}
$click_field = $property_map['ClickField'];
$last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1;
$sql = 'SELECT ' . $click_field . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
ORDER BY ' . $click_field . ' DESC
LIMIT ' . $last_hot . ', 1';
$res = $this->Conn->GetCol($sql);
$hot_limit = (double)array_shift($res);
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$serial_name = $this->Application->incrementCacheSerial($event->Prefix, null, false);
$this->Application->setCache($property_map['HotLimit'] . '[%' . $serial_name . '%]', $hot_limit);
}
else {
$this->Application->setDBCache($property_map['HotLimit'], $hot_limit, 3600);
}
return $hot_limit;
}
/**
* Moves item to preferred category, updates item hits
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kCatDBItem */
// update hits field
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if ( $property_map ) {
$click_field = $property_map['ClickField'];
if ( $this->Application->isAdminUser && ($this->Application->GetVar($click_field . '_original') !== false) && floor($this->Application->GetVar($click_field . '_original')) != $object->GetDBField($click_field) ) {
$sql = 'SELECT MAX(' . $click_field . ')
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE FLOOR(' . $click_field . ') = ' . $object->GetDBField($click_field);
$hits = ($res = $this->Conn->GetOne($sql)) ? $res + 0.000001 : $object->GetDBField($click_field);
$object->SetDBField($click_field, $hits);
}
}
// change category
$target_category = $object->GetDBField('CategoryId');
if ( $object->GetOriginalField('CategoryId') != $target_category ) {
$object->MoveToCat($target_category);
}
}
/**
* 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)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$special = substr($event->Special, -6);
$object =& $event->getObject();
/* @var $object kCatDBItem */
if ( $special == 'import' || $special == 'export' ) {
$image_data = $object->getPrimaryImageData();
if ( $image_data ) {
$thumbnail_image = $image_data[$image_data['LocalThumb'] ? 'ThumbPath' : 'ThumbUrl'];
if ( $image_data['SameImages'] ) {
$full_image = '';
}
else {
$full_image = $image_data[$image_data['LocalImage'] ? 'LocalPath' : 'Url'];
}
$object->SetDBField('ThumbnailImage', $thumbnail_image);
$object->SetDBField('FullImage', $full_image);
$object->SetDBField('ImageAlt', $image_data['AltName']);
}
}
// substituting pending status value for pending editing
if ( $object->HasField('OrgId') && $object->GetDBField('OrgId') > 0 && $object->GetDBField('Status') == -2 ) {
$new_options = Array ();
$options = $object->GetFieldOption('Status', 'options', false, Array ());
foreach ($options as $key => $val) {
if ( $key == 2 ) {
$key = -2;
}
$new_options[$key] = $val;
}
$object->SetFieldOption('Status', 'options', $new_options);
}
if ( !$this->Application->isAdmin ) {
// linking existing images for item with virtual fields
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$image_helper->LoadItemImages($object);
// linking existing files for item with virtual fields
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->LoadItemFiles($object);
}
if ( $object->isVirtualField('MoreCategories') ) {
// set item's additional categories to virtual field (used in editing)
$item_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
$object->SetDBField('MoreCategories', $item_categories ? '|' . implode('|', $item_categories) . '|' : '');
}
}
/**
* Occurs after updating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
+ parent::OnAfterItemUpdate($event);
+
$this->CalculateHotLimit($event);
if ( substr($event->Special, -6) == 'import' ) {
$this->setCustomExportColumns($event);
}
$object =& $event->getObject();
/* @var $object kCatDBItem */
if ( !$this->Application->isAdmin ) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
// process file upload in virtual fields
$file_helper->SaveItemFiles($object);
if ( $event->Special != '-item' ) {
// don't touch categories during cloning
$this->processAdditionalCategories($object, 'update');
}
}
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ( $this->Application->isAdminUser && $recycle_bin ) {
$sql = 'SELECT CategoryId
FROM ' . $this->Application->getUnitOption('ci', 'TableName') . '
WHERE ItemResourceId = ' . $object->GetDBField('ResourceId') . ' AND PrimaryCat = 1';
$primary_category = $this->Conn->GetOne($sql);
if ( $primary_category == $recycle_bin ) {
$event->CallSubEvent('OnAfterItemDelete');
}
}
if ( $object->GetChangedFields() ) {
$now = adodb_mktime();
$object->SetDBField('Modified_date', $now);
$object->SetDBField('Modified_time', $now);
$object->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
}
}
/**
* Sets values for import process
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object kCatDBItem */
if ( substr($event->Special, -6) == 'import' ) {
$this->setCustomExportColumns($event);
}
$object->assignPrimaryCategory();
if ( !$this->Application->isAdmin ) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
// process file upload in virtual fields
$file_helper->SaveItemFiles($object);
if ( $event->Special != '-item' ) {
// don't touch categories during cloning
$this->processAdditionalCategories($object, 'create');
}
}
}
/**
* Make record to search log
*
* @param string $keywords
* @param int $search_type 0 - simple search, 1 - advanced search
*/
function saveToSearchLog($keywords, $search_type = 0)
{
// don't save keywords for each module separately, just one time
// static variable can't help here, because each module uses it's own class instance !
if (!$this->Application->GetVar('search_logged')) {
$sql = 'UPDATE '.TABLE_PREFIX.'SearchLogs
SET Indices = Indices + 1
WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search
$this->Conn->Query($sql);
if ($this->Conn->getAffectedRows() == 0) {
$fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLogs');
}
$this->Application->SetVar('search_logged', 1);
}
}
/**
* Makes simple search for category items
* based on keywords string
*
* @param kEvent $event
*/
function OnSimpleSearch(&$event)
{
$event->redirect = false;
$search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
$keywords = kUtil::unhtmlentities( trim($this->Application->GetVar('keywords')) );
$query_object =& $this->Application->recallObject('HTTPQuery');
/* @var $query_object kHTTPQuery */
$sql = 'SHOW TABLES LIKE "'.$search_table.'"';
if(!isset($query_object->Get['keywords']) &&
!isset($query_object->Post['keywords']) &&
$this->Conn->Query($sql))
{
return; // used when navigating by pages or changing sorting in search results
}
if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length'))
{
$this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
$this->Application->SetVar('keywords_too_short', 1);
return; // if no or too short keyword entered, doing nothing
}
$this->Application->StoreVar('keywords', $keywords);
$this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search
$event->setPseudoClass('_List');
$object =& $event->getObject();
/* @var $object kDBList */
$this->Application->SetVar($event->getPrefixSpecial().'_Page', 1);
$lang = $this->Application->GetVar('m_lang');
$items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
$sql = 'SELECT *
FROM ' . $this->Application->getUnitOption('confs', 'TableName') . '
WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1';
$search_config = $this->Conn->Query($sql, 'FieldName');
$field_list = array_keys($search_config);
$join_clauses = Array();
// field processing
$weight_sum = 0;
$alias_counter = 0;
$custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if ($custom_fields) {
$custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
}
// what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
$search_config_map = Array();
foreach ($field_list as $key => $field) {
$local_table = TABLE_PREFIX.$search_config[$field]['TableName'];
$weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause
// processing multilingual fields
if ( !$search_config[$field]['CustomFieldId'] && $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage' ) {
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$field_list[$key] = 'l'.$lang.'_'.$field;
if (!isset($search_config[$field]['ForeignField'])) {
$field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary'];
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
}
// processing fields from other tables
$foreign_field = $search_config[$field]['ForeignField'];
if ( $foreign_field ) {
$exploded = explode(':', $foreign_field, 2);
if ($exploded[0] == 'CALC') {
// ignoring having type clauses in simple search
unset($field_list[$key]);
continue;
}
else {
$multi_lingual = false;
if ($exploded[0] == 'MULTI') {
$multi_lingual = true;
$foreign_field = $exploded[1];
}
$exploded = explode('.', $foreign_field); // format: table.field_name
$foreign_table = TABLE_PREFIX.$exploded[0];
$alias_counter++;
$alias = 't'.$alias_counter;
if ($multi_lingual) {
$field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1];
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$search_config_map[ $field_list[$key] ] = $field;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
else {
$field_list[$key] = $alias.'.'.$exploded[1];
$search_config_map[ $field_list[$key] ] = $field;
}
$join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']);
$join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
$join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.'
ON '.$join_clause;
}
}
else {
// processing fields from local table
if ($search_config[$field]['CustomFieldId']) {
$local_table = 'custom_data';
// search by custom field value on current language
$custom_field_id = array_search($field_list[$key], $custom_fields);
$field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id;
// search by custom field value on primary language
$field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
$field_list[$key] = $local_table.'.'.$field_list[$key];
$search_config_map[ $field_list[$key] ] = $field;
}
}
// keyword string processing
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$where_clause = Array ();
foreach ($field_list as $field) {
if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) {
// local real field
$filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false);
if ($filter_data) {
$where_clause[] = $filter_data['value'];
}
}
elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) {
$custom_field_name = 'cust_' . $search_config_map[$field];
$filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false);
if ($filter_data) {
$where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']);
}
}
else {
$where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field));
}
}
$where_clause = '((' . implode(') OR (', $where_clause) . '))'; // 2 braces for next clauses, see below!
$search_scope = $this->Application->GetVar('search_scope');
if ($search_scope == 'category') {
$category_id = $this->Application->GetVar('m_cat_id');
$category_filter = $this->getCategoryLimitClause($category_id);
if ($category_filter !== false) {
$join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON '.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$items_table.'.ResourceId';
$join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'Categories ON '.TABLE_PREFIX.'Categories.CategoryId = '.TABLE_PREFIX.'CategoryItems.CategoryId';
$where_clause = '('.$this->getCategoryLimitClause($category_id).') AND '.$where_clause;
}
}
$where_clause = $where_clause . ' AND (' . $items_table . '.Status = ' . STATUS_ACTIVE . ')';
if ($event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild') {
if ($event->MasterEvent->getEventParam('ResultIds')) {
$where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')';
}
}
// making relevance clause
$positive_words = $search_helper->getPositiveKeywords($keywords);
$this->Application->StoreVar('highlight_keywords', serialize($positive_words));
$revelance_parts = Array();
reset($search_config);
foreach ($positive_words as $keyword_index => $positive_word) {
$positive_word = $search_helper->transformWildcards($positive_word);
$positive_words[$keyword_index] = $this->Conn->escape($positive_word);
}
foreach ($field_list as $field) {
if (!array_key_exists($field, $search_config_map)) {
$map_key = $search_config_map[$items_table . '.' . $field];
}
else {
$map_key = $search_config_map[$field];
}
$config_elem = $search_config[ $map_key ];
$weight = $config_elem['Priority'];
// search by whole words only ([[:<:]] - word boundary)
/*$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.implode(' ', $positive_words).')[[:>:]]", '.$weight.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.$keyword.')[[:>:]]", '.$weight.', 0)';
}*/
// search by partial word matches too
$revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$weight.', 0)';
}
}
$revelance_parts = array_unique($revelance_parts);
$conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
$rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
$rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
$rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
$relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords;
if ($rel_pop && $object->isField('Hits')) {
$relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
}
if ($rel_rating && $object->isField('CachedRating')) {
$relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
}
// building final search query
if (!$this->Application->GetVar('do_not_drop_search_table')) {
$this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event
$this->Application->SetVar('do_not_drop_search_table', true);
}
$search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
if ($search_table_exists) {
$select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
}
else {
$select_intro = 'CREATE TABLE '.$search_table.' AS ';
}
$edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0';
$sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance,
'.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId,
'.$items_table.'.ResourceId,
'.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType,
'.$edpick_clause.' AS EdPick
FROM '.$object->TableName.'
'.implode(' ', $join_clauses).'
WHERE '.$where_clause.'
GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' ORDER BY Relevance DESC';
$this->Conn->Query($sql);
if ( !$search_table_exists ) {
$sql = 'ALTER TABLE ' . $search_table . '
ADD INDEX (ResourceId),
ADD INDEX (Relevance)';
$this->Conn->Query($sql);
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnSubSearch(&$event)
{
$ids = Array ();
$search_table = TABLE_PREFIX . 'ses_' . $this->Application->GetSID() . '_' . TABLE_PREFIX . 'Search';
$sql = 'SHOW TABLES LIKE "' . $search_table . '"';
if ( $this->Conn->Query($sql) ) {
$sql = 'SELECT DISTINCT ResourceId
FROM ' . $search_table;
$ids = $this->Conn->GetCol($sql);
}
$event->setEventParam('ResultIds', $ids);
$event->CallSubEvent('OnSimpleSearch');
}
/**
* Enter description here...
*
* @param kEvent $event
* @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
*/
function OnAdvancedSearch(&$event)
{
$query_object =& $this->Application->recallObject('HTTPQuery');
/* @var $query_object kHTTPQuery */
if ( !isset($query_object->Post['andor']) ) {
// used when navigating by pages or changing sorting in search results
return;
}
$this->Application->RemoveVar('keywords');
$this->Application->RemoveVar('Search_Keywords');
$module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
$sql = 'SELECT *
FROM '.$this->Application->getUnitOption('confs', 'TableName').'
WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)';
$search_config = $this->Conn->Query($sql);
$lang = $this->Application->GetVar('m_lang');
$object =& $event->getObject();
/* @var $object kDBList */
$object->SetPage(1);
$items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$search_keywords = $this->Application->GetVar('value'); // will not be changed
$keywords = $this->Application->GetVar('value'); // will be changed down there
$verbs = $this->Application->GetVar('verb');
$glues = $this->Application->GetVar('andor');
$and_conditions = Array();
$or_conditions = Array();
$and_having_conditions = Array();
$or_having_conditions = Array();
$join_clauses = Array();
$highlight_keywords = Array();
$relevance_parts = Array();
$alias_counter = 0;
$custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if ($custom_fields) {
$custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
}
$search_log = '';
$weight_sum = 0;
// processing fields and preparing conditions
foreach ($search_config as $record) {
$field = $record['FieldName'];
$join_clause = '';
$condition_mode = 'WHERE';
// field processing
$local_table = TABLE_PREFIX.$record['TableName'];
$weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause
// processing multilingual fields
if ( $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage' ) {
$field_name = 'l'.$lang.'_'.$field;
}
else {
$field_name = $field;
}
// processing fields from other tables
$foreign_field = $record['ForeignField'];
if ( $foreign_field ) {
$exploded = explode(':', $foreign_field, 2);
if($exploded[0] == 'CALC')
{
$user_groups = $this->Application->RecallVar('UserGroups');
$field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]);
$join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']);
$join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause);
$join_clause = ' LEFT JOIN '.$join_clause;
$condition_mode = 'HAVING';
}
else {
$exploded = explode('.', $foreign_field);
$foreign_table = TABLE_PREFIX.$exploded[0];
if($record['CustomFieldId']) {
$exploded[1] = 'l'.$lang.'_'.$exploded[1];
}
$alias_counter++;
$alias = 't'.$alias_counter;
$field_name = $alias.'.'.$exploded[1];
$join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']);
$join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
if($record['CustomFieldId'])
{
$join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId'];
}
$join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.'
ON '.$join_clause;
}
}
else
{
// processing fields from local table
if ($record['CustomFieldId']) {
$local_table = 'custom_data';
$field_name = 'l'.$lang.'_cust_'.array_search($field_name, $custom_fields);
}
$field_name = $local_table.'.'.$field_name;
}
$condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
if ($record['CustomFieldId'] && strlen($condition)) {
// search in primary value of custom field + value in current language
$field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields);
$primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
$condition = '('.$condition.' OR '.$primary_condition.')';
}
if ($condition) {
if ($join_clause) {
$join_clauses[] = $join_clause;
}
$relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)';
if ($glues[$field] == 1) { // and
if ($condition_mode == 'WHERE') {
$and_conditions[] = $condition;
}
else {
$and_having_conditions[] = $condition;
}
}
else { // or
if ($condition_mode == 'WHERE') {
$or_conditions[] = $condition;
}
else {
$or_having_conditions[] = $condition;
}
}
// create search log record
$search_log_data = Array('search_config' => $record, 'verb' => getArrayValue($verbs, $field), 'value' => ($record['FieldType'] == 'range') ? $search_keywords[$field.'_from'].'|'.$search_keywords[$field.'_to'] : $search_keywords[$field]);
$search_log[] = $this->Application->Phrase('la_Field').' "'.$this->getHuman('Field', $search_log_data).'" '.$this->getHuman('Verb', $search_log_data).' '.$this->Application->Phrase('la_Value').' '.$this->getHuman('Value', $search_log_data).' '.$this->Application->Phrase($glues[$field] == 1 ? 'lu_And' : 'lu_Or');
}
}
if ($search_log) {
$search_log = implode('<br />', $search_log);
$search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log);
$this->saveToSearchLog($search_log, 1); // advanced search
}
$this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords));
// making relevance clause
if($relevance_parts)
{
$conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
$rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
$rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
$rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
$relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords;
$relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
$relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
}
else
{
$relevance_clause = '0';
}
// building having clause
if($or_having_conditions)
{
$and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')';
}
$having_clause = implode(' AND ', $and_having_conditions);
$having_clause = $having_clause ? ' HAVING '.$having_clause : '';
// building where clause
if($or_conditions)
{
$and_conditions[] = '('.implode(' OR ', $or_conditions).')';
}
// $and_conditions[] = $items_table.'.Status = 1';
$where_clause = implode(' AND ', $and_conditions);
if(!$where_clause)
{
if($having_clause)
{
$where_clause = '1';
}
else
{
$where_clause = '0';
$this->Application->SetVar('adv_search_error', 1);
}
}
$where_clause .= ' AND '.$items_table.'.Status = 1';
// building final search query
$search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
$this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0';
$sql = ' CREATE TABLE '.$search_table.'
SELECT '.$relevance_clause.' AS Relevance,
'.$items_table.'.'.$id_field.' AS ItemId,
'.$items_table.'.ResourceId AS ResourceId,
11 AS ItemType,
'.$pick_field.' AS EdPick
FROM '.$items_table.'
'.implode(' ', $join_clauses).'
WHERE '.$where_clause.'
GROUP BY '.$items_table.'.'.$id_field.
$having_clause;
$res = $this->Conn->Query($sql);
}
function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords)
{
$field = $record['FieldName'];
$condition_patterns = Array (
'any' => '%s LIKE %s',
'contains' => '%s LIKE %s',
'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)',
'is' => '%s = %s',
'isnot' => '(%1$s != %2$s OR %1$s IS NULL)'
);
$condition = '';
switch ($record['FieldType']) {
case 'select':
$keywords[$field] = kUtil::unhtmlentities( $keywords[$field] );
if ($keywords[$field]) {
$condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] ));
}
break;
case 'multiselect':
$keywords[$field] = kUtil::unhtmlentities( $keywords[$field] );
if ($keywords[$field]) {
$condition = Array ();
$values = explode('|', substr($keywords[$field], 1, -1));
foreach ($values as $selected_value) {
$condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%'));
}
$condition = '('.implode(' OR ', $condition).')';
}
break;
case 'text':
$keywords[$field] = kUtil::unhtmlentities( $keywords[$field] );
if (mb_strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) {
$highlight_keywords[] = $keywords[$field];
if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) {
$keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%';
}
$condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] ));
}
break;
case 'boolean':
if ($keywords[$field] != -1) {
$property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
$items_table = $this->Application->getUnitOption($this->Prefix, 'TableName');
switch ($field) {
case 'HotItem':
$hot_limit_var = getArrayValue($property_mappings, 'HotLimit');
if ($hot_limit_var) {
$hot_limit = (int)$this->Application->getDBCache($hot_limit_var);
$condition = 'IF('.$items_table.'.HotItem = 2,
IF('.$items_table.'.Hits >= '.
$hot_limit.
', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field];
}
break;
case 'PopItem':
$votes2pop_var = getArrayValue($property_mappings, 'VotesToPop');
$rating2pop_var = getArrayValue($property_mappings, 'RatingToPop');
if ($votes2pop_var && $rating2pop_var) {
$condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '.
$this->Application->ConfigValue($votes2pop_var).
' AND '.$items_table.'.CachedRating >= '.
$this->Application->ConfigValue($rating2pop_var).
', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field];
}
break;
case 'NewItem':
$new_days_var = getArrayValue($property_mappings, 'NewDays');
if ($new_days_var) {
$condition = 'IF('.$items_table.'.NewItem = 2,
IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '.
$this->Application->ConfigValue($new_days_var).
'*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field];
}
break;
case 'EditorsPick':
$condition = $items_table.'.EditorsPick = '.$keywords[$field];
break;
}
}
break;
case 'range':
$range_conditions = Array();
if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) {
$range_conditions[] = $field_name.' >= '.$keywords[$field.'_from'];
}
if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) {
$range_conditions[] = $field_name.' <= '.$keywords[$field.'_to'];
}
if ($range_conditions) {
$condition = implode(' AND ', $range_conditions);
}
break;
case 'date':
if ($keywords[$field]) {
if (in_array($keywords[$field], Array('today', 'yesterday'))) {
$current_time = getdate();
$day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']);
$time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400));
$min_time = $time_mapping[$keywords[$field]];
}
else {
$time_mapping = Array (
'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000,
'last_6_months' => 15768000, 'last_year' => 31536000,
);
$min_time = adodb_mktime() - $time_mapping[$keywords[$field]];
}
$condition = $field_name.' > '.$min_time;
}
break;
}
return $condition;
}
/**
* Returns human readable representation of searched data to be placed in search log
* @param string $type
* @param Array $search_data
* @return string
* @access protected
*/
protected function getHuman($type, $search_data)
{
// all 3 variables are retrieved from $search_data array
/* @var $search_config Array */
/* @var $verb string */
/* @var $value string */
$type = ucfirst(strtolower($type));
extract($search_data);
switch ($type) {
case 'Field':
return $this->Application->Phrase($search_config['DisplayName']);
break;
case 'Verb':
return $verb ? $this->Application->Phrase('lu_advsearch_'.$verb) : '';
break;
case 'Value':
switch ($search_config['FieldType']) {
case 'date':
$values = Array(0 => 'lu_comm_Any', 'today' => 'lu_comm_Today',
'yesterday' => 'lu_comm_Yesterday', 'last_week' => 'lu_comm_LastWeek',
'last_month' => 'lu_comm_LastMonth', 'last_3_months' => 'lu_comm_Last3Months',
'last_6_months' => 'lu_comm_Last6Months', 'last_year' => 'lu_comm_LastYear');
$ret = $this->Application->Phrase($values[$value]);
break;
case 'range':
$value = explode('|', $value);
return $this->Application->Phrase('lu_comm_From').' "'.$value[0].'" '.$this->Application->Phrase('lu_comm_To').' "'.$value[1].'"';
break;
case 'boolean':
$values = Array(1 => 'lu_comm_Yes', 0 => 'lu_comm_No', -1 => 'lu_comm_Both');
$ret = $this->Application->Phrase($values[$value]);
break;
default:
$ret = $value;
break;
}
return '"'.$ret.'"';
break;
}
return '';
}
/**
* Set's correct page for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetPagination(kEvent &$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 ) {
if ( $this->Application->RewriteURLs() ) {
// when page not found by prefix+special, then try to search it without special at all
$page = $this->Application->GetVar($event->Prefix . '_Page');
if ( !$page ) {
// page not found in request -> get from session
$page = $this->Application->RecallVar($event->Prefix . '_Page');
}
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');
}
}
else {
// page found in request -> store in session
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', $page, true); //true for optional
}
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);
}
/* === RELATED TO IMPORT/EXPORT: BEGIN === */
/**
* Shows export dialog
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnExport(&$event)
+ protected function OnExport(kEvent &$event)
{
$selected_ids = $this->StoreSelectedIDs($event);
- if (implode(',', $selected_ids) == '') {
+ if ( implode(',', $selected_ids) == '' ) {
// K4 fix when no ids found bad selected ids array is formed
$selected_ids = false;
}
$selected_cats_ids = $this->Application->GetVar('export_categories');
- $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
- $this->Application->StoreVar($event->Prefix.'_export_cats_ids', $selected_cats_ids);
+ $this->Application->StoreVar($event->Prefix . '_export_ids', $selected_ids ? implode(',', $selected_ids) : '');
+ $this->Application->StoreVar($event->Prefix . '_export_cats_ids', $selected_cats_ids);
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$redirect_params = Array (
- $this->Prefix.'.export_event' => 'OnNew',
- 'pass' => 'all,'.$this->Prefix.'.export'
+ $this->Prefix . '.export_event' => 'OnNew',
+ 'pass' => 'all,' . $this->Prefix . '.export'
);
$event->setRedirectParams($redirect_params);
}
/**
* Performs each export step & displays progress percent
*
* @param kEvent $event
*/
function OnExportProgress(&$event)
{
$export_object =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_object kCatDBItemExportHelper */
$event = new kEvent($event->getPrefixSpecial().':OnDummy');
$action_method = 'perform'.ucfirst($event->Special);
$field_values = $export_object->$action_method($event);
// finish code is done from JS now
if ($field_values['start_from'] == $field_values['total_records']) {
if ($event->Special == 'import') {
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$event->SetRedirectParam('m_cat_id', $this->Application->RecallVar('ImportCategory'));
$event->SetRedirectParam('anchor', 'tab-' . $event->Prefix);
$event->redirect = 'catalog/catalog';
}
elseif ($event->Special == 'export') {
$event->redirect = $export_object->getModuleName($event) . '/' . $event->Special . '_finish';
$event->SetRedirectParam('pass', 'all');
}
return ;
}
$export_options = $export_object->loadOptions($event);
echo $export_options['start_from'] * 100 / $export_options['total_records'];
$event->status = kEvent::erSTOP;
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
+ * @access protected
*/
- function getCustomExportColumns(&$event)
+ public function getCustomExportColumns(kEvent &$event)
{
- return Array( '__VIRTUAL__ThumbnailImage' => 'ThumbnailImage',
- '__VIRTUAL__FullImage' => 'FullImage',
- '__VIRTUAL__ImageAlt' => 'ImageAlt');
+ return Array (
+ '__VIRTUAL__ThumbnailImage' => 'ThumbnailImage',
+ '__VIRTUAL__FullImage' => 'FullImage',
+ '__VIRTUAL__ImageAlt' => 'ImageAlt'
+ );
}
/**
* Sets non standart virtual fields (e.g. to other tables)
*
* @param kEvent $event
*/
function setCustomExportColumns(&$event)
{
$this->restorePrimaryImage($event);
}
/**
* Create/Update primary image record in info found in imported data
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function restorePrimaryImage(&$event)
{
$object =& $event->getObject();
/* @var $object kCatDBItem */
$has_image_info = $object->GetDBField('ImageAlt') && ($object->GetDBField('ThumbnailImage') || $object->GetDBField('FullImage'));
if ( !$has_image_info ) {
return ;
}
$image_data = $object->getPrimaryImageData();
$image =& $this->Application->recallObject('img', null, Array ('skip_autoload' => true));
/* @var $image kDBItem */
if ( $image_data ) {
$image->Load($image_data['ImageId']);
}
else {
$image->Clear();
$image->SetDBField('Name', 'main');
$image->SetDBField('DefaultImg', 1);
$image->SetDBField('ResourceId', $object->GetDBField('ResourceId'));
}
$image->SetDBField('AltName', $object->GetDBField('ImageAlt'));
if ( $object->GetDBField('ThumbnailImage') ) {
$thumbnail_field = $this->isURL($object->GetDBField('ThumbnailImage')) ? 'ThumbUrl' : 'ThumbPath';
$image->SetDBField($thumbnail_field, $object->GetDBField('ThumbnailImage'));
$image->SetDBField('LocalThumb', $thumbnail_field == 'ThumbPath' ? 1 : 0);
}
if ( !$object->GetDBField('FullImage') ) {
$image->SetDBField('SameImages', 1);
}
else {
$image->SetDBField('SameImages', 0);
$full_field = $this->isURL($object->GetDBField('FullImage')) ? 'Url' : 'LocalPath';
$image->SetDBField($full_field, $object->GetDBField('FullImage'));
$image->SetDBField('LocalImage', $full_field == 'LocalPath' ? 1 : 0);
}
if ( $image->isLoaded() ) {
$image->Update();
}
else {
$image->Create();
}
}
/**
* Detects if image url is specified in a given path (instead of path on disk)
*
* @param string $path
* @return bool
* @access protected
*/
protected function isURL($path)
{
return preg_match('#(http|https)://(.*)#', $path);
}
/**
* Prepares item for import/export operations
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
if ( $event->Special == 'import' || $event->Special == 'export' ) {
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->setRequiredFields($event);
}
}
/**
* Process items selected in item_selector
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$dst_field = $this->Application->RecallVar('dst_field');
$selected_ids = $this->Application->GetVar('selected_ids');
if ( $dst_field == 'ItemCategory' ) {
// Item Edit -> Categories Tab -> New Categories
$object =& $event->getObject();
/* @var $object kCatDBItem */
$category_ids = explode(',', $selected_ids['c']);
foreach ($category_ids as $category_id) {
$object->assignToCategory($category_id);
}
}
if ($dst_field == 'ImportCategory') {
// Tools -> Import -> Item Import -> Select Import Category
$this->Application->StoreVar('ImportCategory', $selected_ids['c']);
$event->SetRedirectParam($event->getPrefixSpecial() . '_id', 0);
$event->SetRedirectParam($event->getPrefixSpecial() . '_event', 'OnExportBegin');
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function OnSaveSettings(&$event)
{
$event->redirect = false;
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ( $items_info ) {
list($id, $field_values) = each($items_info);
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
$field_values['ImportSource'] = 2;
$field_values['ImportLocalFilename'] = $object->GetDBField('ImportFilename');
$items_info[$id] = $field_values;
$this->Application->StoreVar($event->getPrefixSpecial() . '_ItemsInfo', serialize($items_info));
}
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function OnResetSettings(&$event)
{
$this->Application->StoreVar('ImportCategory', $this->Application->getBaseCategory());
}
/**
* Cancels item editing
* @param kEvent $event
* @return void
* @todo Used?
*/
function OnCancelAction(&$event)
{
- $event->setRedirectParams(Array ('pass' => 'all,' . $event->getPrefixSpecial()), true);
$event->redirect = $this->Application->GetVar('cancel_template');
+ $event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
}
/* === RELATED TO IMPORT/EXPORT: END === */
/**
* Stores item's owner login into separate field together with id
*
* @param kEvent $event
* @param string $id_field
* @param string $cached_field
*/
function cacheItemOwner(&$event, $id_field, $cached_field)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$user_id = $object->GetDBField($id_field);
$options = $object->GetFieldOptions($id_field);
if ( isset($options['options'][$user_id]) ) {
$object->SetDBField($cached_field, $options['options'][$user_id]);
}
else {
$id_field = $this->Application->getUnitOption('u', 'IDField');
$table_name = $this->Application->getUnitOption('u', 'TableName');
$sql = 'SELECT Username
FROM ' . $table_name . '
WHERE ' . $id_field . ' = ' . $user_id;
$object->SetDBField($cached_field, $this->Conn->GetOne($sql));
}
}
/**
* 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)
+ protected function OnPreSave(kEvent &$event)
{
parent::OnPreSave($event);
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ( $event->status == kEvent::erSUCCESS && $use_pending_editing ) {
// decision: clone or not clone
$object =& $event->getObject();
/* @var $object kCatDBItem */
if ( $object->GetID() == 0 || $object->GetDBField('OrgId') > 0 ) {
// new items or cloned items shouldn't be cloned again
return ;
}
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$owner_field = $this->getOwnerField($event->Prefix);
if ( $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix) == 2 ) {
// 1. clone original item
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array ($object->GetID()), null, null, null, true);
$ci_table = $this->Application->GetTempName(TABLE_PREFIX . 'CategoryItems');
// 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$sql = 'SELECT ResourceId
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $cloned_ids[0];
$clone_resource_id = $this->Conn->GetOne($sql);
$sql = 'DELETE FROM ' . $ci_table . '
WHERE ItemResourceId = ' . $clone_resource_id . ' AND PrimaryCat = 1';
$this->Conn->Query($sql);
// 3. copy main item categoryitems to cloned item
$sql = ' INSERT INTO ' . $ci_table . ' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, ' . $clone_resource_id . ' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM ' . $ci_table . '
WHERE ItemResourceId = ' . $object->GetDBField('ResourceId');
$this->Conn->Query($sql);
// 4. put cloned id to OrgId field of item being cloned
$sql = 'UPDATE ' . $object->TableName . '
SET OrgId = ' . $object->GetID() . '
WHERE ' . $object->IDField . ' = ' . $cloned_ids[0];
$this->Conn->Query($sql);
// 5. substitute id of item being cloned with clone id
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $cloned_ids[0]);
$selected_ids = $this->getSelectedIDs($event, true);
$selected_ids[ array_search($object->GetID(), $selected_ids) ] = $cloned_ids[0];
$this->StoreSelectedIDs($event, $selected_ids);
// 6. delete original item from temp table
$temp_handler->DeleteItems($event->Prefix, $event->Special, Array ($object->GetID()));
}
}
}
/**
* Sets item's owner field
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnPreCreate(&$event)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
if ( $event->status != kEvent::erSUCCESS ) {
return ;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$owner_field = $this->getOwnerField($event->Prefix);
$object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
}
/**
* Occurs before original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeDeleteOriginal(kEvent &$event)
{
}
/**
* Occurs after original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterDeleteOriginal(kEvent &$event)
{
}
/**
* 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)
+ protected function OnBeforeClone(kEvent &$event)
{
parent::OnBeforeClone($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('ResourceId', 0); // this will reset it
if ( $this->Application->GetVar('ResetCatBeforeClone') ) {
$object->SetDBField('CategoryId', null);
}
}
/**
* Set status for new category item based on user permission in category
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kCatDBItem */
$is_admin = $this->Application->isAdminUser;
$owner_field = $this->getOwnerField($event->Prefix);
if ( (!$object->IsTempTable() && !$is_admin) || ($is_admin && !$object->GetDBField($owner_field)) ) {
// Front-end OR owner not specified -> set to currently logged-in user
$object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
}
if ( !$this->Application->isAdmin ) {
$this->setItemStatusByPermission($event);
}
}
/**
* Sets category item status based on user permissions (only on Front-end)
*
* @param kEvent $event
*/
function setItemStatusByPermission(&$event)
{
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if (!$use_pending_editing) {
return ;
}
$object =& $event->getObject();
/* @var $object kCatDBItem */
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
$item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix);
if ($item_status == STATUS_DISABLED) {
$event->status = kEvent::erFAIL;
}
else {
$object->SetDBField('Status', $item_status);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
parent::OnCreate($event);
+
$this->SetFrontRedirectTemplate($event, 'suggest');
}
/**
* Returns item's categories (allows to exclude primary category)
*
* @param int $resource_id
* @param bool $with_primary
* @return Array
*/
function getItemCategories($resource_id, $with_primary = false)
{
$sql = 'SELECT CategoryId
FROM '.TABLE_PREFIX.'CategoryItems
WHERE (ItemResourceId = '.$resource_id.')';
if (!$with_primary) {
$sql .= ' AND (PrimaryCat = 0)';
}
return $this->Conn->GetCol($sql);
}
/**
* Adds new and removes old additional categories from category item
*
* @param kCatDBItem $object
* @param int $mode
*/
function processAdditionalCategories(&$object, $mode)
{
if ( !$object->isVirtualField('MoreCategories') ) {
// given category item doesn't require such type of processing
return ;
}
$process_categories = $object->GetDBField('MoreCategories');
if ($process_categories === '') {
// field was not in submit & have default value (when no categories submitted, then value is null)
return ;
}
if ($mode == 'create') {
// prevents first additional category to become primary
$object->assignPrimaryCategory();
}
$process_categories = $process_categories ? explode('|', substr($process_categories, 1, -1)) : Array ();
$existing_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
$add_categories = array_diff($process_categories, $existing_categories);
foreach ($add_categories as $category_id) {
$object->assignToCategory($category_id);
}
$remove_categories = array_diff($existing_categories, $process_categories);
foreach ($remove_categories as $category_id) {
$object->removeFromCategory($category_id);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
$use_pending = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ($this->Application->isAdminUser || !$use_pending) {
parent::OnUpdate($event);
$this->SetFrontRedirectTemplate($event, 'modify');
return ;
}
$object =& $event->getObject(Array('skip_autoload' => true));
/* @var $object kCatDBItem */
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($items_info) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$owner_field = $this->getOwnerField($event->Prefix);
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
foreach ($items_info as $id => $field_values) {
$object->Load($id);
$edit_perm = $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix);
if ($use_pending && !$object->GetDBField('OrgId') && ($edit_perm == STATUS_PENDING)) {
// pending editing enabled + not pending copy -> get/create pending copy & save changes to it
$original_id = $object->GetID();
$original_resource_id = $object->GetDBField('ResourceId');
$file_helper->PreserveItemFiles($field_values);
$object->Load($original_id, 'OrgId');
if (!$object->isLoaded()) {
// 1. user has no pending copy of live item -> clone live item
$cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($original_id), null, null, null, true);
$object->Load($cloned_ids[0]);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
// 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$ci_table = $this->Application->getUnitOption('ci', 'TableName');
$sql = 'DELETE FROM '.$ci_table.'
WHERE ItemResourceId = '.$object->GetDBField('ResourceId').' AND PrimaryCat = 1';
$this->Conn->Query($sql);
// 1b. copy main item categoryitems to cloned item
$sql = 'INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, '.$object->GetDBField('ResourceId').' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM '.$ci_table.'
WHERE ItemResourceId = '.$original_resource_id;
$this->Conn->Query($sql);
// 1c. put cloned id to OrgId field of item being cloned
$object->SetDBField('Status', STATUS_PENDING_EDITING);
$object->SetDBField('OrgId', $original_id);
}
else {
// 2. user has pending copy of live item -> just update field values
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
}
// update id in request (used for redirect in mod-rewrite mode)
$this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetID());
}
else {
// 3. already editing pending copy -> just update field values
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
}
if ($object->Update()) {
$event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$this->SetFrontRedirectTemplate($event, 'modify');
}
/**
* Sets next template to one required for front-end after adding/modifying item
*
* @param kEvent $event
* @param string $template_key - {suggest,modify}
*/
function SetFrontRedirectTemplate(&$event, $template_key)
{
- if ( $this->Application->isAdminUser || $event->status != kEvent::erSUCCESS ) {
+ if ( $this->Application->isAdmin || $event->status != kEvent::erSUCCESS ) {
return;
}
// prepare redirect template
$object =& $event->getObject();
/* @var $object kDBItem */
$is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
$next_template = $is_active ? 'confirm_template' : 'pending_confirm_template';
$event->redirect = $this->Application->GetVar($template_key . '_' . $next_template);
$event->SetRedirectParam('opener', 's');
// send email events
$perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix');
$owner_field = $this->getOwnerField($event->Prefix);
$owner_id = $object->GetDBField($owner_field);
switch ( $event->Name ) {
case 'OnCreate':
$event_suffix = $is_active ? 'ADD' : 'ADD.PENDING';
$this->Application->EmailEventAdmin($perm_prefix . '.' . $event_suffix); // there are no ADD.PENDING event for admin :(
$this->Application->EmailEventUser($perm_prefix . '.' . $event_suffix, $owner_id);
break;
case 'OnUpdate':
$event_suffix = $is_active ? 'MODIFY' : 'MODIFY.PENDING';
$user_id = is_numeric($object->GetDBField('ModifiedById')) ? $object->GetDBField('ModifiedById') : $owner_id;
$this->Application->EmailEventAdmin($perm_prefix . '.' . $event_suffix); // there are no ADD.PENDING event for admin :(
$this->Application->EmailEventUser($perm_prefix . '.' . $event_suffix, $user_id);
break;
}
}
/**
* Apply same processing to each item being selected in grid
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function iterateItems(&$event)
+ protected function iterateItems(kEvent &$event)
{
if ( $event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline' ) {
parent::iterateItems($event);
}
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return ;
}
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kCatDBItem */
$ids = $this->StoreSelectedIDs($event);
if ( $ids ) {
foreach ($ids as $id) {
$ret = true;
$object->Load($id);
switch ( $event->Name ) {
case 'OnMassApprove':
$ret = $object->ApproveChanges();
break;
case 'OnMassDecline':
$ret = $object->DeclineChanges();
break;
}
if ( !$ret ) {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$this->clearSelectedIDs($event);
}
/**
* Deletes items & preserves clean env
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnDelete(&$event)
+ protected function OnDelete(kEvent &$event)
{
parent::OnDelete($event);
- if ($event->status == kEvent::erSUCCESS && !$this->Application->isAdmin) {
+ if ( $event->status == kEvent::erSUCCESS && !$this->Application->isAdmin ) {
$event->SetRedirectParam('pass', 'm');
$event->SetRedirectParam('m_cat_id', 0);
}
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
* @access protected
*/
protected function checkItemStatus(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->isLoaded() ) {
if ( $event->Special != 'previous' && $event->Special != 'next' ) {
$this->_errorNotFound($event);
}
return true;
}
$status = $object->GetDBField('Status');
$user_id = $this->Application->RecallVar('user_id');
$owner_field = $this->getOwnerField($event->Prefix);
if ( ($status == STATUS_PENDING_EDITING || $status == STATUS_PENDING) && ($object->GetDBField($owner_field) == $user_id) ) {
return true;
}
return $status == STATUS_ACTIVE;
}
/**
* Set's correct sorting for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetSorting(kEvent &$event)
{
if ( !$this->Application->isAdmin ) {
$event->setEventParam('same_special', true);
}
parent::SetSorting($event);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
* @access protected
*/
protected function getPerPage(kEvent &$event)
{
if ( !$this->Application->isAdmin ) {
$event->setEventParam('same_special', true);
}
return parent::getPerPage($event);
}
/**
* Returns owner field for given prefix
*
* @param $prefix
* @return string
* @access protected
*/
protected function getOwnerField($prefix)
{
return $this->Application->getUnitOption($prefix, 'OwnerField', 'CreatedById');
}
/**
* Creates virtual image fields for item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
if (defined('IS_INSTALL') && IS_INSTALL) {
return ;
}
if ( !$this->Application->isAdmin ) {
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->createItemFiles($event->Prefix, true); // create image fields
$file_helper->createItemFiles($event->Prefix, false); // create file fields
}
$this->changeSortings($event);
// add grids for advanced view (with primary category column)
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$process_grids = Array ('Default', 'Radio');
foreach ($process_grids as $process_grid) {
$grid_data = $grids[$process_grid];
$grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_primary_category_td', 'filter_block' => 'grid_like_filter');
$grids[$process_grid . 'ShowAll'] = $grid_data;
}
$this->Application->setUnitOption($this->Prefix, 'Grids', $grids);
// add options for CategoryId field (quick way to select item's primary category)
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$virtual_fields['CategoryId']['default'] = (int)$this->Application->GetVar('m_cat_id');
$virtual_fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions();
$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
}
function changeSortings(&$event)
{
$remove_sortings = Array ();
if ( !$this->Application->isAdmin ) {
// remove Pick sorting on Front-end, when not required
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping', Array ());
if ( !isset($config_mapping['ForceEditorPick']) || !$this->Application->ConfigValue($config_mapping['ForceEditorPick']) ) {
$remove_sortings[] = 'EditorsPick';
}
}
else {
// remove all forced sortings in Admin Console
$remove_sortings = array_merge($remove_sortings, Array ('Priority', 'EditorsPick'));
}
if ( !$remove_sortings ) {
return;
}
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings', Array ());
/* @var $list_sortings Array */
foreach ($list_sortings as $special => $sorting_fields) {
foreach ($remove_sortings as $sorting_field) {
unset($list_sortings[$special]['ForcedSorting'][$sorting_field]);
}
}
$this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
}
/**
* Returns file contents associated with item
*
* @param kEvent $event
*/
function OnDownloadFile(&$event)
{
$object =& $event->getObject();
/* @var $object kCatDBItem */
$event->status = kEvent::erSTOP;
$field = $this->Application->GetVar('field');
if (!preg_match('/^File([\d]+)/', $field)) {
return ;
}
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$filename = $object->GetField($field, 'full_path');
$file_helper->DownloadFile($filename);
}
/**
* Saves user's vote
*
* @param kEvent $event
*/
function OnMakeVote(&$event)
{
$event->status = kEvent::erSTOP;
if ($this->Application->GetVar('ajax') != 'yes') {
// this is supposed to call from AJAX only
return ;
}
$rating_helper =& $this->Application->recallObject('RatingHelper');
/* @var $rating_helper RatingHelper */
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kCatDBItem */
$object->Load( $this->Application->GetVar('id') );
echo $rating_helper->makeVote($object);
}
/**
* Marks review as useful
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnReviewHelpful(&$event)
{
if ( $this->Application->GetVar('ajax') == 'yes' ) {
$event->status = kEvent::erSTOP;
}
$review_id = (int)$this->Application->GetVar('review_id');
if ( !$review_id ) {
return;
}
$spam_helper =& $this->Application->recallObject('SpamHelper');
/* @var $spam_helper SpamHelper */
$spam_helper->InitHelper($review_id, 'ReviewHelpful', strtotime('+1 month') - strtotime('now'));
$field = (int)$this->Application->GetVar('helpful') ? 'HelpfulCount' : 'NotHelpfulCount';
$sql = 'SELECT ' . $field . '
FROM ' . $this->Application->getUnitOption('rev', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('rev', 'IDField') . ' = ' . $review_id;
$count = $this->Conn->GetOne($sql);
if ( $spam_helper->InSpamControl() ) {
if ( $this->Application->GetVar('ajax') == 'yes' ) {
echo $count;
}
return;
}
$sql = 'UPDATE ' . $this->Application->getUnitOption('rev', 'TableName') . '
SET ' . $field . ' = ' . $field . ' + 1
WHERE ' . $this->Application->getUnitOption('rev', 'IDField') . ' = ' . $review_id;
$this->Conn->Query($sql);
if ( $this->Conn->getAffectedRows() ) {
// db was changed -> review with such ID exists
$spam_helper->AddToSpamControl();
}
if ( $this->Application->GetVar('ajax') == 'yes' ) {
echo $count + 1;
}
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCloneSubItem(&$event)
+ protected function OnCloneSubItem(kEvent &$event)
{
parent::OnCloneSubItem($event);
- if ($event->MasterEvent->Prefix == 'fav') {
+ if ( $event->MasterEvent->Prefix == 'fav' ) {
$clones = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'Clones');
$subitem_prefix = $event->Prefix . '-' . $event->MasterEvent->Prefix;
$clones[$subitem_prefix]['ParentTableKey'] = 'ResourceId';
$clones[$subitem_prefix]['ForeignKey'] = 'ResourceId';
$this->Application->setUnitOption($event->MasterEvent->Prefix, 'Clones', $clones);
}
}
/**
* 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());
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/event.php
===================================================================
--- branches/5.2.x/core/kernel/utility/event.php (revision 15064)
+++ branches/5.2.x/core/kernel/utility/event.php (revision 15065)
@@ -1,447 +1,440 @@
<?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!');
final class kEvent extends kBase {
/**
* Event finished working succsessfully
*
*/
const erSUCCESS = 0;
/**
* Event finished working, but result is unsuccsessfull
*
*/
const erFAIL = -1;
/**
* Event experienced FATAL error - no hooks should continue!
*
*/
const erFATAL = -2;
/**
* Event failed on internal permission checking (user has no permission)
*
*/
const erPERM_FAIL = -3;
/**
* Event requested to stop processing (don't parse templates)
*
*/
const erSTOP = -4;
/**
* Reference to event, that created given event
*
* @var kEvent
* @access public
*/
public $MasterEvent;
/**
* Event name
*
* @var string
* @access public
*/
public $Name;
/**
* Don't execute hooks, before event processing
*
* @var bool
* @access public
*/
public $SkipBeforeHooks = false;
/**
* Don't execute hooks, after event processing
*
* @var bool
* @access public
*/
public $SkipAfterHooks = false;
/**
* Perform redirect after event processing.
* Redirect after event processing allows to prevent same event being present in resulting url.
* Also could contain template name, that needs to be shown after redirect.
*
* @var mixed
* @access public
*/
public $redirect = true;
/**
* Params, used during redirect url building after event successful processing
*
* @var bool
* @access private
*/
private $redirectParams = Array ();
/**
* PHP file to redirect to. Defaults to "index.php"
*
* @var string
* @access public
*/
public $redirectScript = null;
/**
* Event processing status
*
* @var int
* @access public
*/
public $status = kEvent::erSUCCESS;
/**
* Event parameters
* Usually indicate, how particular event should be processed.
*
* @var Array
* @access private
*/
private $specificParams = Array ();
/**
* Pseudo class used, to create object, based on event contents
*
* @var string
* @access private
*/
private $pseudoClass = '';
/**
* Create event from given prefix, special, name and specific params.
* Parameter $params could be be an an array with following keys: "prefix", "special" (optional), "name".
* Parameter $params could be a string in format: "prefix:name" or "prefix.special:name".
*
* @param mixed $params
* @param Array $specific_params event specific params (none by default)
* @return kEvent
* @access public
*/
public function __construct($params = Array(), $specific_params = null)
{
parent::__construct();
if ($params) {
if ( is_array($params) ) {
$prefix = isset($params['prefix']) ? $params['prefix'] : false;
$special = isset($params['special']) ? $params['special'] : false;
if ($prefix) {
$this->Init($prefix, $special);
}
$this->Name = isset($params['name']) ? $params['name'] : '';
}
elseif ( is_string($params) ) {
if (preg_match('/([^.:]*)[.]{0,1}([^:]*):(.*)/', $params, $regs)) {
$prefix = $regs[1];
$special = $regs[2];
if ($prefix) {
$this->Init($prefix, $special);
}
$this->Name = $regs[3];
}
else {
throw new Exception('Invalid event string: <strong>' . $params . '</strong>. $params should be "prefix[.special]:OnEvent" format');
}
}
}
if ( isset($specific_params) ) {
$this->specificParams = $specific_params;
}
}
/**
* Returns joined prefix and special if any
*
* @param bool $from_submit if true, then joins prefix & special by "_", uses "." otherwise
* @return string
* @access public
*/
public function getPrefixSpecial($from_submit = false)
{
if (!$from_submit) {
return parent::getPrefixSpecial();
}
return rtrim($this->Prefix . '_' . $this->Special, '_');
}
/**
* Sets event parameter
*
* @param string $name
* @param mixed $value
* @access public
*/
public function setEventParam($name,$value)
{
$this->specificParams[$name] = $value;
}
/**
* Returns event parameter by name (supports digging)
*
* @param string $name
* @return mixed
* @access public
*/
public function getEventParam($name)
{
$args = func_get_args();
if (count($args) > 1) {
kUtil::array_unshift_ref($args, $this->specificParams);
return call_user_func_array('getArrayValue', $args); // getArrayValue($this->specificParams, $name);
}
return array_key_exists($name, $this->specificParams) ? $this->specificParams[$name] : false;
}
/**
* Returns all event parameters
*
* @return Array
* @access public
*/
public function getEventParams()
{
return $this->specificParams;
}
/**
* Set's pseudo class that differs from
* the one specified in $Prefix
*
* @param string $appendix
* @access public
*/
public function setPseudoClass($appendix)
{
$this->pseudoClass = $this->Prefix . $appendix;
}
/**
* Performs event initialization
* Also sets pseudo class same $prefix
*
* @param string $prefix
* @param string $special
* @access public
*/
public function Init($prefix, $special)
{
$this->pseudoClass = $prefix;
parent::Init($prefix, $special);
}
/**
* Returns object used in event
*
* @param Array $params
* @return kDBBase
* @access public
*/
public function &getObject(array $params = Array())
{
if ( !$this->Application->hasObject($this->prefixSpecial) ) {
$top_event =& $this;
// when OnSave calls OnPreSave in first line, then this would make sure OnSave is used
while ( is_object($top_event->MasterEvent) ) {
$top_event =& $top_event->MasterEvent;
}
$params['parent_event'] =& $top_event;
}
$object =& $this->Application->recallObject($this->prefixSpecial, $this->pseudoClass, $params);
return $object;
}
/**
* Executes given event in context of current event
* Sub-event gets this event in "kEvent::MasterEvent" attribute.
* Sub-event execution results (status and redirect* properties) are copied back to current event.
*
* @param string $name name of callable event (optionally could contain prefix_special as well)
* @see kEvent::MasterEvent
*/
public function CallSubEvent($name)
{
if ( strpos($name, ':') === false ) {
// PrefixSpecial not specified -> use from current event
$name = $this->getPrefixSpecial() . ':' . $name;
}
$child_event = new kEvent($name);
$child_event->copyFrom($this, true);
$this->Application->HandleEvent($child_event);
$this->copyFrom($child_event);
$this->specificParams = $child_event->specificParams;
}
/**
* Allows to copy data between events
*
* @param kEvent $source_event
* @param bool $inherit
* @access public
*/
public function copyFrom(&$source_event, $inherit = false)
{
if ($inherit) {
$this->MasterEvent =& $source_event;
}
else {
$this->status = $source_event->status;
}
$this->redirect = $source_event->redirect;
$this->redirectParams = $source_event->redirectParams;
$this->redirectScript = $source_event->redirectScript;
$this->specificParams = $source_event->specificParams;
}
/**
* Returns all redirect parameters
*
* @return Array
* @access public
*/
public function getRedirectParams()
{
return $this->redirectParams;
}
/**
* Returns redirect parameter
*
* @param string $name
* @return mixed
* @access public
*/
public function getRedirectParam($name)
{
return array_key_exists($name, $this->redirectParams) ? $this->redirectParams[$name] : false;
}
/**
* Set's redirect param for event
*
* @param string $name
* @param string $value
* @access public
*/
public function SetRedirectParam($name, $value)
{
$this->redirectParams[$name] = $value;
}
/**
* Allows to merge passed redirect params hash with existing ones
*
* @param Array $params
- * @param bool $overwrite
* @access public
*/
- public function setRedirectParams($params, $overwrite = false)
+ public function setRedirectParams($params)
{
- if ($overwrite) {
- $this->redirectParams = $params;
-
- return ;
- }
-
// append new parameters to parameters set before
$this->redirectParams = kUtil::array_merge_recursive($this->redirectParams, $params);
}
/**
* Allows to tell if this event was called some how (e.g. subevent, hook) from event requested
*
* @param string $event_key event key in format [prefix[.special]:]event_name
* @return bool
* @access public
*/
public function hasAncestor($event_key)
{
if ( strpos($event_key, ':') === false ) {
$event_key = $this->getPrefixSpecial() . ':' . $event_key;
}
return $this->Application->EventManager->eventRunning($event_key);
}
/**
* Returns permission section associated with event
*
* @return string
* @access public
*/
public function getSection()
{
$perm_section = $this->getEventParam('PermSection');
if ($perm_section) {
return $perm_section;
}
// 1. get section by current top_prefix
$top_prefix = $this->getEventParam('top_prefix');
if ($top_prefix == false) {
$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix, true);
$this->setEventParam('top_prefix', $top_prefix);
}
$section = $this->Application->getUnitOption($top_prefix.'.main', 'PermSection');
// 2. check if this section has perm_prefix mapping to other prefix
$sections_helper =& $this->Application->recallObject('SectionsHelper');
/* @var $sections_helper kSectionsHelper */
$section_data =& $sections_helper->getSectionData($section);
if ($section_data && isset($section_data['perm_prefix']) && $section_data['perm_prefix'] != $top_prefix) {
$this->setEventParam('top_prefix', $section_data['perm_prefix']);
$section = $this->Application->getUnitOption($section_data['perm_prefix'].'.main', 'PermSection');
}
if (!$section) {
throw new Exception('Permission <strong>section</strong> not specified for prefix <strong>' . $top_prefix . '</strong>');
}
return $section;
}
public function __toString()
{
return $this->getPrefixSpecial() . ':' . $this->Name;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/theme_files/theme_file_eh.php
===================================================================
--- branches/5.2.x/core/units/theme_files/theme_file_eh.php (revision 15064)
+++ branches/5.2.x/core/units/theme_files/theme_file_eh.php (revision 15065)
@@ -1,231 +1,233 @@
<?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 ThemeFileEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnLoadBlock' => Array ('subitem' => true),
'OnSaveBlock' => Array ('subitem' => true),
'OnSaveLayout' => Array ('subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnLoadBlock' || $event->Name == 'OnSaveBlock' ) {
return $this->Application->isAdminUser;
}
return parent::CheckPermission($event);
}
/**
* Loads template contents into virtual field
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$filename = $this->_getTemplatePath($object);
if ( file_exists($filename) ) {
$object->SetDBField('FileContents', file_get_contents($filename));
}
else {
$object->SetError('FileContents', 'template_file_missing', 'la_error_TemplateFileMissing');
}
}
/**
* Trim contents of edited template
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$file_data = $object->GetDBField('FileContents');
$file_data = str_replace("\r\n", "\n", $file_data);
$file_data = str_replace("\r", "\n", $file_data);
$object->SetDBField('FileContents', trim($file_data));
}
/**
* Saves updated content to template
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$filename = $this->_getTemplatePath($object);
- if (file_exists($filename) && is_writable($filename)) {
+ if ( file_exists($filename) && is_writable($filename) ) {
$fp = fopen($filename, 'w');
fwrite($fp, $object->GetDBField('FileContents'));
fclose($fp);
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$meta_info = $themes_helper->parseTemplateMetaInfo($filename);
$file_description = array_key_exists('desc', $meta_info) ? $meta_info['desc'] : '';
$object->SetDBField('Description', $file_description);
$object->SetDBField('FileMetaInfo', serialize($meta_info));
$object->Update();
}
}
/**
* Returns full path to template file
*
* @param kDBItem $object
* @return string
*/
function _getTemplatePath(&$object)
{
$theme =& $this->Application->recallObject('theme');
/* @var $theme kDBItem */
$path = FULL_PATH . '/themes/' . $theme->GetDBField('Name');
$path .= $object->GetDBField('FilePath') . '/' . $object->GetDBField('FileName');
return $path;
}
/**
* Loads block data based on it's name in request
*
* @param kEvent $event
*/
function OnLoadBlock(&$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$template_helper =& $this->Application->recallObject('TemplateHelper');
/* @var $template_helper TemplateHelper */
$template_helper->InitHelper($object);
$object->SetDBField('FileName', $template_helper->blockInfo('template_file'));
$object->SetDBField('BlockPosition', $template_helper->blockInfo('start_pos') . ' - ' . $template_helper->blockInfo('end_pos'));
$object->SetDBField('FileContents', $template_helper->blockInfo('content'));
}
/**
* Saves changed template block
*
* @param kEvent $event
*/
function OnSaveBlock(&$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->getRequestProtectedFields($field_values));
$object->setID($id);
}
$status = $object->Validate();
$template_helper =& $this->Application->recallObject('TemplateHelper');
/* @var $template_helper TemplateHelper */
$template_helper->InitHelper($object);
$status = $status && $template_helper->saveBlock($object);
if ($status) {
$event->SetRedirectParam('opener', 'u');
}
else {
$event->status = kEvent::erFAIL;
}
}
/**
* Saves layout on given template
*
* @param kEvent $event
*/
function OnSaveLayout(&$event)
{
$event->status = kEvent::erSTOP;
if (($this->Application->GetVar('ajax') != 'yes') || (EDITING_MODE != EDITING_MODE_DESIGN)) {
return ;
}
$target_order = $this->Application->GetVar('target_order');
$template_helper =& $this->Application->recallObject('TemplateHelper');
/* @var $template_helper TemplateHelper */
if ($template_helper->moveTemplateElements($target_order)) {
echo 'OK';
return ;
}
echo 'FAILED';
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/categories/categories_event_handler.php
===================================================================
--- branches/5.2.x/core/units/categories/categories_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/categories/categories_event_handler.php (revision 15065)
@@ -1,2880 +1,2893 @@
<?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 CategoriesEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnRebuildCache' => Array ('self' => 'add|edit'),
'OnCopy' => Array ('self' => true),
'OnCut' => Array ('self' => 'edit'),
'OnPasteClipboard' => Array ('self' => true),
'OnPaste' => Array ('self' => 'add|edit', 'subitem' => 'edit'),
'OnRecalculatePriorities' => Array ('self' => 'add|edit'), // category ordering
'OnItemBuild' => Array ('self' => true), // always allow to view individual categories (regardless of CATEGORY.VIEW right)
'OnUpdatePreviewBlock' => Array ('self' => true), // for FCKEditor integration
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Categories are sorted using special sorting event
*
*/
function mapEvents()
{
parent::mapEvents();
$events_map = Array (
'OnMassMoveUp' => 'OnChangePriority',
'OnMassMoveDown' => 'OnChangePriority',
);
$this->eventMethods = array_merge($this->eventMethods, $events_map);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnResetCMSMenuCache' ) {
// events from "Tools -> System Tools" section are controlled via that section "edit" permission
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_value = $this->Application->CheckPermission('in-portal:service.edit');
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
if ( !$this->Application->isAdmin ) {
if ( $event->Name == 'OnSetSortingDirect' ) {
// allow sorting on front event without view permission
return true;
}
if ( $event->Name == 'OnItemBuild' ) {
$category_id = $this->getPassedID($event);
if ( $category_id == 0 ) {
return true;
}
}
}
if ( in_array($event->Name, $this->_getMassPermissionEvents()) ) {
$items = $this->_getPermissionCheckInfo($event);
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
if ( ($event->Name == 'OnSave') && array_key_exists(0, $items) ) {
// adding new item (ID = 0)
$perm_value = $perm_helper->AddCheckPermission($items[0]['ParentId'], $event->Prefix) > 0;
}
else {
// leave only items, that can be edited
$ids = Array ();
$check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
foreach ($items as $item_id => $item_data) {
if ( $perm_helper->$check_method($item_data['CreatedById'], $item_data['ParentId'], $event->Prefix) > 0 ) {
$ids[] = $item_id;
}
}
if ( !$ids ) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
$perm_value = true;
$event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
}
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
if ( $event->Name == 'OnRecalculatePriorities' ) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$category_id = $this->Application->GetVar('m_cat_id');
return $perm_helper->AddCheckPermission($category_id, $event->Prefix) || $perm_helper->ModifyCheckPermission(0, $category_id, $event->Prefix);
}
if ( $event->Name == 'OnPasteClipboard' ) {
// forces permission check to work by current category for "Paste In Category" operation
$category_id = $this->Application->GetVar('m_cat_id');
$this->Application->SetVar('c_id', $category_id);
}
return parent::CheckPermission($event);
}
/**
* Returns events, that require item-based (not just event-name based) permission check
*
* @return Array
*/
function _getMassPermissionEvents()
{
return Array (
'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
'OnCut',
);
}
/**
* Returns category item IDs, that require permission checking
*
* @param kEvent $event
* @return string
*/
function _getPermissionCheckIDs(&$event)
{
if ($event->Name == 'OnSave') {
$selected_ids = implode(',', $this->getSelectedIDs($event, true));
if (!$selected_ids) {
$selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
}
}
else {
// OnEdit, OnMassDelete events, when items are checked in grid
$selected_ids = implode(',', $this->StoreSelectedIDs($event));
}
return $selected_ids;
}
/**
* Returns information used in permission checking
*
* @param kEvent $event
* @return Array
*/
function _getPermissionCheckInfo(&$event)
{
// when saving data from temp table to live table check by data from temp table
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
if ($event->Name == 'OnSave') {
$table_name = $this->Application->GetTempName($table_name, 'prefix:' . $event->Prefix);
}
$sql = 'SELECT ' . $id_field . ', CreatedById, ParentId
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . $this->_getPermissionCheckIDs($event) . ')';
$items = $this->Conn->Query($sql, $id_field);
if (!$items) {
// when creating new category, then no IDs are stored in session
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list ($id, $fields_hash) = each($items_info);
if (array_key_exists('ParentId', $fields_hash)) {
$item_category = $fields_hash['ParentId'];
}
else {
$item_category = $this->Application->RecallVar('m_cat_id'); // saved in c:OnPreCreate event permission checking
}
$items[$id] = Array (
'CreatedById' => $this->Application->RecallVar('user_id'),
'ParentId' => $item_category,
);
}
return $items;
}
/**
* Set's mark, that root category is edited
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnEdit(&$event)
+ protected function OnEdit(kEvent &$event)
{
$category_id = $this->Application->GetVar($event->getPrefixSpecial() . '_id');
$home_category = $this->Application->getBaseCategory();
- $this->Application->StoreVar('IsRootCategory_'.$this->Application->GetVar('m_wid'), ($category_id === '0') || ($category_id == $home_category));
+ $this->Application->StoreVar('IsRootCategory_' . $this->Application->GetVar('m_wid'), ($category_id === '0') || ($category_id == $home_category));
parent::OnEdit($event);
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
// keep "Section Properties" link (in browse modes) clean
$this->Application->DeleteVar('admin');
}
}
/**
* Adds selected link to listing
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$selected_ids = $this->Application->GetVar('selected_ids');
$this->RemoveRequiredFields($object);
$object->SetDBField($this->Application->RecallVar('dst_field'), $selected_ids['c']);
$object->Update();
$event->SetRedirectParam('opener', 'u');
}
/**
* Apply system filter to categories list
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
// don't show "Content" category in advanced view
$object->addFilter('system_categories', '%1$s.Status <> 4');
// show system templates from current theme only + all virtual templates
$object->addFilter('theme_filter', '%1$s.ThemeId = ' . $this->_getCurrentThemeId() . ' OR %1$s.ThemeId = 0');
if ($event->Special == 'showall') {
// if using recycle bin don't show categories from there
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ($recycle_bin) {
$sql = 'SELECT TreeLeft, TreeRight
FROM '.TABLE_PREFIX.'Categories
WHERE CategoryId = '.$recycle_bin;
$tree_indexes = $this->Conn->GetRow($sql);
$object->addFilter('recyclebin_filter', '%1$s.TreeLeft < '.$tree_indexes['TreeLeft'].' OR %1$s.TreeLeft > '.$tree_indexes['TreeRight']);
}
}
if ( (string)$event->getEventParam('parent_cat_id') !== '' ) {
$parent_cat_id = $event->getEventParam('parent_cat_id');
if ("$parent_cat_id" == 'Root') {
$module_name = $event->getEventParam('module') ? $event->getEventParam('module') : 'In-Commerce';
$parent_cat_id = $this->Application->findModule('Name', $module_name, 'RootCat');
}
}
else {
$parent_cat_id = $this->Application->GetVar('c_id');
if (!$parent_cat_id) {
$parent_cat_id = $this->Application->GetVar('m_cat_id');
}
if (!$parent_cat_id) {
$parent_cat_id = 0;
}
}
if ("$parent_cat_id" == '0') {
// replace "0" category with "Content" category id (this way template
$parent_cat_id = $this->Application->getBaseCategory();
}
if ("$parent_cat_id" != 'any') {
if ($event->getEventParam('recursive')) {
if ($parent_cat_id > 0) {
// not "Home" category
$tree_indexes = $this->Application->getTreeIndex($parent_cat_id);
$object->addFilter('parent_filter', '%1$s.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight']);
}
}
else {
$object->addFilter('parent_filter', '%1$s.ParentId = '.$parent_cat_id);
}
}
$object->addFilter('perm_filter', TABLE_PREFIX . 'CategoryPermissionsCache.PermId = 1'); // check for CATEGORY.VIEW permission
if ($this->Application->RecallVar('user_id') != USER_ROOT) {
// apply permission filters to all users except "root"
$view_filters = Array ();
$groups = explode(',',$this->Application->RecallVar('UserGroups'));
foreach ($groups as $group) {
$view_filters[] = 'FIND_IN_SET('.$group.', ' . TABLE_PREFIX . 'CategoryPermissionsCache.ACL)';
}
$view_filter = implode(' OR ', $view_filters);
$object->addFilter('perm_filter2', $view_filter);
}
if (!$this->Application->isAdminUser) {
// apply status filter only on front
$object->addFilter('status_filter', $object->TableName.'.Status = 1');
}
// process "types" and "except" parameters
$type_clauses = Array();
$types = $event->getEventParam('types');
$types = $types ? explode(',', $types) : Array ();
$except_types = $event->getEventParam('except');
$except_types = $except_types ? explode(',', $except_types) : Array ();
if (in_array('related', $types) || in_array('related', $except_types)) {
$related_to = $event->getEventParam('related_to');
if (!$related_to) {
$related_prefix = $event->Prefix;
}
else {
$sql = 'SELECT Prefix
FROM '.TABLE_PREFIX.'ItemTypes
WHERE ItemName = '.$this->Conn->qstr($related_to);
$related_prefix = $this->Conn->GetOne($sql);
}
$rel_table = $this->Application->getUnitOption('rel', 'TableName');
$item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
if ($item_type == 0) {
trigger_error('<strong>ItemType</strong> not defined for prefix <strong>' . $event->Prefix . '</strong>', E_USER_WARNING);
}
// process case, then this list is called inside another list
$prefix_special = $event->getEventParam('PrefixSpecial');
if (!$prefix_special) {
$prefix_special = $this->Application->Parser->GetParam('PrefixSpecial');
}
$id = false;
if ($prefix_special !== false) {
$processed_prefix = $this->Application->processPrefix($prefix_special);
if ($processed_prefix['prefix'] == $related_prefix) {
// printing related categories within list of items (not on details page)
$list =& $this->Application->recallObject($prefix_special);
/* @var $list kDBList */
$id = $list->GetID();
}
}
if ($id === false) {
// printing related categories for single item (possibly on details page)
if ($related_prefix == 'c') {
$id = $this->Application->GetVar('m_cat_id');
}
else {
$id = $this->Application->GetVar($related_prefix . '_id');
}
}
$p_item =& $this->Application->recallObject($related_prefix . '.current', null, Array('skip_autoload' => true));
/* @var $p_item kCatDBItem */
$p_item->Load( (int)$id );
$p_resource_id = $p_item->GetDBField('ResourceId');
$sql = 'SELECT SourceId, TargetId FROM '.$rel_table.'
WHERE
(Enabled = 1)
AND (
(Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(Type = 1
AND (
(SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.')
)
)
)';
$related_ids_array = $this->Conn->Query($sql);
$related_ids = Array();
foreach ($related_ids_array as $key => $record) {
$related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ];
}
if (count($related_ids) > 0) {
$type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).')';
$type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).')';
}
else {
$type_clauses['related']['include'] = '0';
$type_clauses['related']['except'] = '1';
}
$type_clauses['related']['having_filter'] = false;
}
if (in_array('category_related', $type_clauses)) {
$object->removeFilter('parent_filter');
$resource_id = $this->Conn->GetOne('
SELECT ResourceId FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
WHERE CategoryId = '.$parent_cat_id
);
$sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'CatalogRelationships
WHERE SourceId = '.$resource_id.' AND SourceType = 1';
$related_cats = $this->Conn->GetCol($sql);
$related_cats = is_array($related_cats) ? $related_cats : Array();
$sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'CatalogRelationships
WHERE TargetId = '.$resource_id.' AND TargetType = 1 AND Type = 1';
$related_cats2 = $this->Conn->GetCol($sql);
$related_cats2 = is_array($related_cats2) ? $related_cats2 : Array();
$related_cats = array_unique( array_merge( $related_cats2, $related_cats ) );
if ($related_cats) {
$type_clauses['category_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')';
$type_clauses['category_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')';
}
else
{
$type_clauses['category_related']['include'] = '0';
$type_clauses['category_related']['except'] = '1';
}
$type_clauses['category_related']['having_filter'] = false;
}
if (in_array('product_related', $types)) {
$object->removeFilter('parent_filter');
$product_id = $event->getEventParam('product_id') ? $event->getEventParam('product_id') : $this->Application->GetVar('p_id');
$resource_id = $this->Conn->GetOne('
SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').'
WHERE ProductId = '.$product_id
);
$sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'CatalogRelationships
WHERE SourceId = '.$resource_id.' AND TargetType = 1';
$related_cats = $this->Conn->GetCol($sql);
$related_cats = is_array($related_cats) ? $related_cats : Array();
$sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'CatalogRelationships
WHERE TargetId = '.$resource_id.' AND SourceType = 1 AND Type = 1';
$related_cats2 = $this->Conn->GetCol($sql);
$related_cats2 = is_array($related_cats2) ? $related_cats2 : Array();
$related_cats = array_unique( array_merge( $related_cats2, $related_cats ) );
if ($related_cats) {
$type_clauses['product_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')';
$type_clauses['product_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')';
}
else {
$type_clauses['product_related']['include'] = '0';
$type_clauses['product_related']['except'] = '1';
}
$type_clauses['product_related']['having_filter'] = false;
}
$type_clauses['menu']['include'] = '%1$s.IsMenu = 1';
$type_clauses['menu']['except'] = '%1$s.IsMenu = 0';
$type_clauses['menu']['having_filter'] = false;
if (in_array('search', $types) || in_array('search', $except_types)) {
$event_mapping = Array (
'simple' => 'OnSimpleSearch',
'subsearch' => 'OnSubSearch',
'advanced' => 'OnAdvancedSearch'
);
$keywords = $event->getEventParam('keyword_string');
$type = $this->Application->GetVar('search_type', 'simple');
if ( $keywords ) {
// processing keyword_string param of ListProducts tag
$this->Application->SetVar('keywords', $keywords);
$type = 'simple';
}
$search_event = $event_mapping[$type];
$this->$search_event($event);
$object =& $event->getObject();
/* @var $object kDBList */
$search_sql = ' FROM ' . TABLE_PREFIX . 'ses_' . $this->Application->GetSID() . '_' . TABLE_PREFIX . 'Search
search_result LEFT JOIN %1$s ON %1$s.ResourceId = search_result.ResourceId';
$sql = str_replace('FROM %1$s', $search_sql, $object->GetPlainSelectSQL());
$object->SetSelectSQL($sql);
$object->addCalculatedField('Relevance', 'search_result.Relevance');
$object->AddOrderField('search_result.Relevance', 'desc', true);
$type_clauses['search']['include'] = '1';
$type_clauses['search']['except'] = '0';
$type_clauses['search']['having_filter'] = false;
}
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->SetComplexFilter($event, $type_clauses, implode(',', $types), implode(',', $except_types));
}
/**
* Returns current theme id
*
* @return int
*/
function _getCurrentThemeId()
{
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
return (int)$themes_helper->getCurrentThemeId();
}
/**
* 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
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( ($event->Special == 'page') || ($event->Special == '-virtual') || ($event->Prefix == 'st') ) {
return $this->_getPassedStructureID($event);
}
if ( $this->Application->isAdmin ) {
return parent::getPassedID($event);
}
return $this->Application->GetVar('m_cat_id');
}
/**
* Enter description here...
*
* @param kEvent $event
* @return int
*/
function _getPassedStructureID(&$event)
{
static $page_by_template = Array ();
if ($event->Special == 'current') {
return $this->Application->GetVar('m_cat_id');
}
$event->setEventParam('raise_warnings', 0);
$page_id = parent::getPassedID($event);
if ($page_id === false) {
$template = $event->getEventParam('page');
if (!$template) {
$template = $this->Application->GetVar('t');
}
// bug: when template contains "-" symbols (or others, that stripDisallowed will replace) it's not found
if (!array_key_exists($template, $page_by_template)) {
$sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE
(
(NamedParentPath = ' . $this->Conn->qstr($template) . ') OR
(NamedParentPath = ' . $this->Conn->qstr('Content/' . $template) . ') OR
(`Type` = ' . PAGE_TYPE_TEMPLATE . ' AND CachedTemplate = ' . $this->Conn->qstr($template) . ')
) AND (ThemeId = ' . $this->_getCurrentThemeId() . ' OR ThemeId = 0)';
$page_id = $this->Conn->GetOne($sql);
}
else {
$page_id = $page_by_template[$template];
}
if ($page_id === false && EDITING_MODE) {
// create missing pages, when in editing mode
$object =& $this->Application->recallObject($this->Prefix . '.rebuild', null, Array('skip_autoload' => true));
/* @var $object CategoriesItem */
$created = $this->_prepareAutoPage($object, $template, null, SMS_MODE_AUTO); // create virtual (not system!) page
if ($created) {
if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild') || !$this->Application->isAdmin) {
$updater =& $this->Application->makeClass('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
}
$this->_resetMenuCache();
$this->Application->RemoveVar('PermCache_UpdateRequired');
$page_id = $object->GetID();
$this->Application->SetVar('m_cat_id', $page_id);
}
}
if ($page_id) {
$page_by_template[$template] = $page_id;
}
}
if (!$page_id && !$this->Application->isAdmin) {
$page_id = $this->Application->GetVar('m_cat_id');
}
return $page_id;
}
function ParentGetPassedID(&$event)
{
return parent::getPassedID($event);
}
/**
* Adds calculates fields for item statuses
*
* @param kCatDBItem $object
* @param kEvent $event
* @return void
* @access protected
*/
protected function prepareObject(&$object, kEvent &$event)
{
if ( $event->Special == '-virtual' ) {
return;
}
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->addCalculatedField(
'IsNew',
' IF(%1$s.NewItem = 2,
IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
$this->Application->ConfigValue('Category_DaysNew').
'*3600*24), 1, 0),
%1$s.NewItem
)');
}
/**
* Set correct parent path for newly created categories
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterCopyToLive(&$event)
+ protected function OnAfterCopyToLive(kEvent &$event)
{
+ parent::OnAfterCopyToLive($event);
+
$object =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true, 'live_table' => true));
/* @var $object CategoriesItem */
$parent_path = false;
- $object->Load( $event->getEventParam('id') );
+ $object->Load($event->getEventParam('id'));
if ( $event->getEventParam('temp_id') == 0 ) {
if ( $object->isLoaded() ) {
// update path only for real categories (not including "Home" root category)
$fields_hash = Array ('ParentPath' => $object->buildParentPath());
$this->Conn->doUpdate($fields_hash, $object->TableName, 'CategoryId = ' . $object->GetID());
$parent_path = $fields_hash['ParentPath'];
}
}
else {
$parent_path = $object->GetDBField('ParentPath');
}
if ( $parent_path ) {
$cache_updater =& $this->Application->makeClass('kPermCacheUpdater', Array (null, $parent_path));
/* @var $cache_updater kPermCacheUpdater */
$cache_updater->OneStepRun();
}
}
/**
* Set cache modification mark if needed
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(kEvent &$event)
{
parent::OnBeforeDeleteFromLive($event);
$id = $event->getEventParam('id');
// loading anyway, because this object is needed by "c-perm:OnBeforeDeleteFromLive" event
$temp_object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $temp_object CategoriesItem */
$temp_object->Load($id);
if ( $id == 0 ) {
if ( $temp_object->isLoaded() ) {
// new category -> update cache (not loaded when "Home" category)
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
}
return ;
}
// existing category was edited, check if in-cache fields are modified
$live_object =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('live_table' => true, 'skip_autoload' => true));
/* @var $live_object CategoriesItem */
$live_object->Load($id);
$cached_fields = Array ('l' . $this->Application->GetDefaultLanguageId() . '_Name', 'Filename', 'Template', 'ParentId', 'Priority');
foreach ($cached_fields as $cached_field) {
if ( $live_object->GetDBField($cached_field) != $temp_object->GetDBField($cached_field) ) {
// use session instead of REQUEST because of permission editing in category can contain
// multiple submits, that changes data before OnSave event occurs
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
break;
}
}
// remember category filename change between temp and live records
if ( $temp_object->GetDBField('Filename') != $live_object->GetDBField('Filename') ) {
$filename_changes = $this->Application->GetVar($event->Prefix . '_filename_changes', Array ());
$filename_changes[ $live_object->GetID() ] = Array (
'from' => $live_object->GetDBField('Filename'),
'to' => $temp_object->GetDBField('Filename')
);
$this->Application->SetVar($event->Prefix . '_filename_changes', $filename_changes);
}
}
/**
* Calls kDBEventHandler::OnSave original event
* Used in proj-cms:StructureEventHandler->OnSave
*
* @param kEvent $event
*/
function parentOnSave(&$event)
{
parent::OnSave($event);
}
/**
* Reset root-category flag when new category is created
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnPreCreate(&$event)
+ protected function OnPreCreate(kEvent &$event)
{
// 1. for permission editing of Home category
$this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid'));
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// 2. preset template
$category_id = $this->Application->GetVar('m_cat_id');
$root_category = $this->Application->getBaseCategory();
if ( $category_id == $root_category ) {
$object->SetDBField('Template', $this->_getDefaultDesign());
}
// 3. set default owner
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
}
/**
* Checks cache update mark and redirect to cache if needed
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
// get data from live table before it is overwritten by parent OnSave method call
$ids = $this->getSelectedIDs($event, true);
$is_editing = implode('', $ids);
$old_statuses = $is_editing ? $this->_getCategoryStatus($ids) : Array ();
$object =& $event->getObject();
/* @var $object CategoriesItem */
parent::OnSave($event);
if ( $event->status != kEvent::erSUCCESS ) {
return;
}
if ( $this->Application->RecallVar('PermCache_UpdateRequired') ) {
$this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid'));
}
$this->Application->StoreVar('RefreshStructureTree', 1);
$this->_resetMenuCache();
if ( $is_editing ) {
// send email event to category owner, when it's status is changed (from admin)
$object->SwitchToLive();
$new_statuses = $this->_getCategoryStatus($ids);
$process_statuses = Array (STATUS_ACTIVE, STATUS_DISABLED);
foreach ($new_statuses as $category_id => $new_status) {
if ( $new_status != $old_statuses[$category_id] && in_array($new_status, $process_statuses) ) {
$object->Load($category_id);
$email_event = $new_status == STATUS_ACTIVE ? 'CATEGORY.APPROVE' : 'CATEGORY.DENY';
$this->Application->EmailEventUser($email_event, $object->GetDBField('CreatedById'));
}
}
}
// change opener stack in case if edited category filename was changed
$filename_changes = $this->Application->GetVar($event->Prefix . '_filename_changes', Array ());
if ( $filename_changes ) {
$opener_stack =& $this->Application->makeClass('kOpenerStack');
/* @var $opener_stack kOpenerStack */
list ($template, $params, $index_file) = $opener_stack->pop();
foreach ($filename_changes as $change_info) {
$template = str_ireplace($change_info['from'], $change_info['to'], $template);
}
$opener_stack->push($template, $params, $index_file);
$opener_stack->save();
}
}
/**
* Returns statuses of given categories
*
* @param Array $category_ids
* @return Array
*/
function _getCategoryStatus($category_ids)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT Status, ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $category_ids) . ')';
return $this->Conn->GetCol($sql, $id_field);
}
/**
* 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)
+ protected function OnPreSaveCreated(kEvent &$event)
{
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object CategoriesItem */
if ( $object->IsRoot() ) {
// don't create root category while saving permissions
return;
}
parent::OnPreSaveCreated($event);
}
/**
* Deletes sym link to other category
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
- $sql = 'UPDATE '.$object->TableName.'
+ $sql = 'UPDATE ' . $object->TableName . '
SET SymLinkCategoryId = NULL
- WHERE SymLinkCategoryId = '.$object->GetID();
-
+ WHERE SymLinkCategoryId = ' . $object->GetID();
$this->Conn->Query($sql);
}
/**
* Exclude root categories from deleting
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
if ( !$ids || $this->Application->ConfigValue('AllowDeleteRootCats') ) {
return;
}
$root_categories = Array ();
// get module root categories and exclude them
foreach ($this->Application->ModuleInfo as $module_info) {
$root_categories[] = $module_info['RootCat'];
}
$root_categories = array_unique($root_categories);
if ( $root_categories && array_intersect($ids, $root_categories) ) {
$event->setEventParam('ids', array_diff($ids, $root_categories));
$this->Application->StoreVar('root_delete_error', 1);
}
}
}
/**
* Checks, that given template exists (physically) in given theme
*
* @param string $template
* @param int $theme_id
* @return bool
*/
function _templateFound($template, $theme_id = null)
{
static $init_made = false;
if (!$init_made) {
$this->Application->InitParser(true);
$init_made = true;
}
if (!isset($theme_id)) {
$theme_id = $this->_getCurrentThemeId();
}
$theme_name = $this->_getThemeName($theme_id);
return $this->Application->TemplatesCache->TemplateExists('theme:' . $theme_name . '/' . $template);
}
/**
* Removes ".tpl" in template path
*
* @param string $template
* @return string
*/
function _stripTemplateExtension($template)
{
// return preg_replace('/\.[^.\\\\\\/]*$/', '', $template);
return preg_replace('/^[\\/]{0,1}(.*)\.tpl$/', "$1", $template);
}
/**
* Deletes all selected items.
* Automatically recourse 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)
+ protected function OnMassDelete(kEvent &$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return ;
}
$to_delete = Array ();
$ids = $this->StoreSelectedIDs($event);
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ( $recycle_bin ) {
$rb =& $this->Application->recallObject('c.recycle', null, Array ('skip_autoload' => true));
/* @var $rb CategoriesItem */
$rb->Load($recycle_bin);
$cat =& $event->getObject(Array ('skip_autoload' => true));
/* @var $cat CategoriesItem */
foreach ($ids as $id) {
$cat->Load($id);
if ( preg_match('/^' . preg_quote($rb->GetDBField('ParentPath'), '/') . '/', $cat->GetDBField('ParentPath')) ) {
$to_delete[] = $id;
continue;
}
$cat->SetDBField('ParentId', $recycle_bin);
$cat->Update();
}
$ids = $to_delete;
$event->redirect = 'categories/cache_updater';
}
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('ids');
if ( $ids ) {
$recursive_helper =& $this->Application->recallObject('RecursiveHelper');
/* @var $recursive_helper kRecursiveHelper */
foreach ($ids as $id) {
$recursive_helper->DeleteCategory($id, $event->Prefix);
}
}
$this->clearSelectedIDs($event);
$this->Application->StoreVar('RefreshStructureTree', 1);
$this->_resetMenuCache();
}
/**
* Add selected items to clipboard with mode = COPY (CLONE)
*
* @param kEvent $event
*/
function OnCopy(&$event)
{
$this->Application->RemoveVar('clipboard');
$clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
/* @var $clipboard_helper kClipboardHelper */
$clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Add selected items to clipboard with mode = CUT
*
* @param kEvent $event
*/
function OnCut(&$event)
{
$this->Application->RemoveVar('clipboard');
$clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
/* @var $clipboard_helper kClipboardHelper */
$clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Controls all item paste operations. Can occur only with filled clipboard.
*
* @param kEvent $event
*/
function OnPasteClipboard(&$event)
{
$clipboard = unserialize( $this->Application->RecallVar('clipboard') );
foreach ($clipboard as $prefix => $clipboard_data) {
$paste_event = new kEvent($prefix.':OnPaste', Array('clipboard_data' => $clipboard_data));
$this->Application->HandleEvent($paste_event);
$event->copyFrom($paste_event);
}
}
/**
* Checks permission for OnPaste event
*
* @param kEvent $event
* @return bool
*/
function _checkPastePermission(&$event)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$category_id = $this->Application->GetVar('m_cat_id');
if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
return true;
}
/**
* Paste categories with sub-items from clipboard
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPaste(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event) ) {
$event->status = kEvent::erFAIL;
return;
}
$clipboard_data = $event->getEventParam('clipboard_data');
if ( !$clipboard_data['cut'] && !$clipboard_data['copy'] ) {
return;
}
// 1. get ParentId of moved category(-es) before it gets updated!!!)
$source_category_id = 0;
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
if ( $clipboard_data['cut'] ) {
$sql = 'SELECT ParentId
FROM ' . $table_name . '
WHERE ' . $id_field . ' = ' . $clipboard_data['cut'][0];
$source_category_id = $this->Conn->GetOne($sql);
}
$recursive_helper =& $this->Application->recallObject('RecursiveHelper');
/* @var $recursive_helper kRecursiveHelper */
if ( $clipboard_data['cut'] ) {
$recursive_helper->MoveCategories($clipboard_data['cut'], $this->Application->GetVar('m_cat_id'));
}
if ( $clipboard_data['copy'] ) {
// don't allow to copy/paste system OR theme-linked virtual pages
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $clipboard_data['copy']) . ') AND (`Type` = ' . PAGE_TYPE_VIRTUAL . ') AND (ThemeId = 0)';
$allowed_ids = $this->Conn->GetCol($sql);
if ( !$allowed_ids ) {
return;
}
foreach ($allowed_ids as $id) {
$recursive_helper->PasteCategory($id, $event->Prefix);
}
}
$priority_helper =& $this->Application->recallObject('PriorityHelper');
/* @var $priority_helper kPriorityHelper */
if ( $clipboard_data['cut'] ) {
$ids = $priority_helper->recalculatePriorities($event, 'ParentId = ' . $source_category_id);
if ( $ids ) {
$priority_helper->massUpdateChanged($event->Prefix, $ids);
}
}
// recalculate priorities of newly pasted categories in destination category
$parent_id = $this->Application->GetVar('m_cat_id');
$ids = $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id);
if ( $ids ) {
$priority_helper->massUpdateChanged($event->Prefix, $ids);
}
if ( $clipboard_data['cut'] || $clipboard_data['copy'] ) {
// rebuild with progress bar
if ( $this->Application->ConfigValue('QuickCategoryPermissionRebuild') ) {
$updater =& $this->Application->makeClass('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
}
else {
$event->redirect = 'categories/cache_updater';
}
$this->_resetMenuCache();
$this->Application->StoreVar('RefreshStructureTree', 1);
}
}
/**
* Occurs when pasting category
*
* @param kEvent $event
*/
/*function OnCatPaste(&$event)
{
$inp_clipboard = $this->Application->RecallVar('ClipBoard');
$inp_clipboard = explode('-', $inp_clipboard, 2);
if($inp_clipboard[0] == 'COPY')
{
$saved_cat_id = $this->Application->GetVar('m_cat_id');
$cat_ids = $event->getEventParam('cat_ids');
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$ids_sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE ResourceId IN (%s)';
$resource_ids_sql = 'SELECT ItemResourceId FROM '.TABLE_PREFIX.'CategoryItems WHERE CategoryId = %s AND PrimaryCat = 1';
$object =& $this->Application->recallObject($event->Prefix.'.item', $event->Prefix, Array('skip_autoload' => true));
foreach($cat_ids as $source_cat => $dest_cat)
{
$item_resource_ids = $this->Conn->GetCol( sprintf($resource_ids_sql, $source_cat) );
if(!$item_resource_ids) continue;
$this->Application->SetVar('m_cat_id', $dest_cat);
$item_ids = $this->Conn->GetCol( sprintf($ids_sql, implode(',', $item_resource_ids) ) );
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
if($item_ids) $temp->CloneItems($event->Prefix, $event->Special, $item_ids);
}
$this->Application->SetVar('m_cat_id', $saved_cat_id);
}
}*/
/**
* Clears clipboard content
*
* @param kEvent $event
*/
function OnClearClipboard(&$event)
{
$this->Application->RemoveVar('clipboard');
}
/**
* Sets correct status for new categories created on front-end
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object CategoriesItem */
if ( $object->GetDBField('ParentId') <= 0 ) {
// no parent category - use current (happens during import)
$object->SetDBField('ParentId', $this->Application->GetVar('m_cat_id'));
}
$this->_beforeItemChange($event);
- if ( $this->Application->isAdminUser || $event->Prefix == 'st' ) {
+ if ( $this->Application->isAdmin || $event->Prefix == 'st' ) {
// don't check category permissions when auto-creating structure pages
return ;
}
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$new_status = false;
$category_id = $this->Application->GetVar('m_cat_id');
if ( $perm_helper->CheckPermission('CATEGORY.ADD', 0, $category_id) ) {
$new_status = STATUS_ACTIVE;
}
else {
if ( $perm_helper->CheckPermission('CATEGORY.ADD.PENDING', 0, $category_id) ) {
$new_status = STATUS_PENDING;
}
}
if ( $new_status ) {
$object->SetDBField('Status', $new_status);
// don't forget to set Priority for suggested from Front-End categories
$min_priority = $this->_getNextPriority($object->GetDBField('ParentId'), $object->TableName);
$object->SetDBField('Priority', $min_priority);
}
else {
$event->status = kEvent::erPERM_FAIL;
return ;
}
}
/**
* Returns next available priority for given category from given table
*
* @param int $category_id
* @param string $table_name
* @return int
*/
function _getNextPriority($category_id, $table_name)
{
$sql = 'SELECT MIN(Priority)
FROM ' . $table_name . '
WHERE ParentId = ' . $category_id;
return (int)$this->Conn->GetOne($sql) - 1;
}
/**
* Sets correct status for new categories created on front-end
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_beforeItemChange($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetChangedFields() ) {
$object->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
}
}
/**
* Performs redirect to correct suggest confirmation template
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
parent::OnCreate($event);
- if ($this->Application->isAdminUser || $event->status != kEvent::erSUCCESS) {
+ if ( $this->Application->isAdmin || $event->status != kEvent::erSUCCESS ) {
// don't sent email or rebuild cache directly after category is created by admin
- return ;
+ return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$cache_updater =& $this->Application->makeClass('kPermCacheUpdater', Array (null, $object->GetDBField('ParentPath')));
/* @var $cache_updater kPermCacheUpdater */
$cache_updater->OneStepRun();
$is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
$next_template = $is_active ? 'suggest_confirm_template' : 'suggest_pending_confirm_template';
$event->redirect = $this->Application->GetVar($next_template);
$event->SetRedirectParam('opener', 's');
// send email events
$perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix');
$event_suffix = $is_active ? 'ADD' : 'ADD.PENDING';
- $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix);
- $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('CreatedById'));
+ $this->Application->EmailEventAdmin($perm_prefix . '.' . $event_suffix);
+ $this->Application->EmailEventUser($perm_prefix . '.' . $event_suffix, $object->GetDBField('CreatedById'));
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
* @access protected
*/
protected function getPerPage(kEvent &$event)
{
if ( !$this->Application->isAdmin ) {
$event->setEventParam('same_special', true);
}
return parent::getPerPage($event);
}
/**
* Set's correct page for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetPagination(kEvent &$event)
{
parent::SetPagination($event);
if ( !$this->Application->isAdmin ) {
$page_var = $event->getEventParam('page_var');
if ( $page_var !== false ) {
$page = $this->Application->GetVar($page_var);
if ( is_numeric($page) ) {
$object =& $event->getObject();
/* @var $object kDBList */
$object->SetPage($page);
}
}
}
}
/**
* Apply same processing to each item being selected in grid
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function iterateItems(&$event)
+ protected function iterateItems(kEvent &$event)
{
if ( $event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline' ) {
parent::iterateItems($event);
}
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object CategoriesItem */
$ids = $this->StoreSelectedIDs($event);
if ( $ids ) {
$propagate_category_status = $this->Application->GetVar('propagate_category_status');
$status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
foreach ($ids as $id) {
$object->Load($id);
$object->SetDBField($status_field, $event->Name == 'OnMassApprove' ? 1 : 0);
if ( $object->Update() ) {
if ( $propagate_category_status ) {
$sql = 'UPDATE ' . $object->TableName . '
SET ' . $status_field . ' = ' . $object->GetDBField($status_field) . '
WHERE TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight');
$this->Conn->Query($sql);
}
$event->status = kEvent::erSUCCESS;
$email_event = $event->Name == 'OnMassApprove' ? 'CATEGORY.APPROVE' : 'CATEGORY.DENY';
$this->Application->EmailEventUser($email_event, $object->GetDBField('CreatedById'));
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$this->clearSelectedIDs($event);
$this->Application->StoreVar('RefreshStructureTree', 1);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
* @access protected
*/
protected function checkItemStatus(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->isLoaded() ) {
return true;
}
if ( $object->GetDBField('Status') != STATUS_ACTIVE && $object->GetDBField('Status') != 4 ) {
if ( !$object->GetDBField('DirectLinkEnabled') || !$object->GetDBField('DirectLinkAuthKey') ) {
return false;
}
return $this->Application->GetVar('authkey') == $object->GetDBField('DirectLinkAuthKey');
}
return true;
}
// ============= for cms page processing =======================
/**
* Returns default design template
*
* @return string
*/
function _getDefaultDesign()
{
$default_design = trim($this->Application->ConfigValue('cms_DefaultDesign'), '/');
if (!$default_design) {
// theme-based alias for default design
return '#default_design#';
}
if (strpos($default_design, '#') === false) {
// real template, not alias, so prefix with "/"
return '/' . $default_design;
}
// alias
return $default_design;
}
/**
* Returns default design based on given virtual template (used from kApplication::Run)
*
* @param string $t
* @return string
* @access public
*/
public function GetDesignTemplate($t = null)
{
if ( !isset($t) ) {
$t = $this->Application->GetVar('t');
}
$page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, Array ('page' => $t));
/* @var $page CategoriesItem */
if ( $page->isLoaded() ) {
$real_t = $page->GetDBField('CachedTemplate');
$this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId'));
if ( $page->GetDBField('FormId') ) {
$this->Application->SetVar('form_id', $page->GetDBField('FormId'));
}
}
else {
$not_found = $this->Application->ConfigValue('ErrorTemplate');
$real_t = $not_found ? $not_found : 'error_notfound';
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$theme_id = $this->Application->GetVar('m_theme');
$category_id = $themes_helper->getPageByTemplate($real_t, $theme_id);
$this->Application->SetVar('m_cat_id', $category_id);
header('HTTP/1.0 404 Not Found');
}
// replace alias in form #alias_name# to actual template used in this theme
$theme =& $this->Application->recallObject('theme.current');
/* @var $theme kDBItem */
$template = $theme->GetField('TemplateAliases', $real_t);
if ( $template ) {
return $template;
}
return $real_t;
}
/**
* Sets category id based on found template (used from kApplication::Run)
*
* @deprecated
*/
/*function SetCatByTemplate()
{
$t = $this->Application->GetVar('t');
$page =& $this->Application->recallObject($this->Prefix . '.-virtual');
if ($page->isLoaded()) {
$this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId') );
}
}*/
/**
* Prepares template paths
*
* @param kEvent $event
*/
function _beforeItemChange(&$event)
{
$object =& $event->getObject();
/* @var $object CategoriesItem */
$object->checkFilename();
$object->generateFilename();
$now = adodb_mktime();
if ( !$this->Application->isDebugMode() && strpos($event->Special, 'rebuild') === false ) {
$object->SetDBField('Type', $object->GetOriginalField('Type'));
$object->SetDBField('Protected', $object->GetOriginalField('Protected'));
if ( $object->GetDBField('Protected') ) {
// some fields are read-only for protected pages, when debug mode is off
$object->SetDBField('AutomaticFilename', $object->GetOriginalField('AutomaticFilename'));
$object->SetDBField('Filename', $object->GetOriginalField('Filename'));
$object->SetDBField('Status', $object->GetOriginalField('Status'));
}
}
$is_admin = $this->Application->isAdminUser;
if ( (!$object->IsTempTable() && !$is_admin) || ($is_admin && !$object->GetDBField('CreatedById')) ) {
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
}
if ($object->GetChangedFields()) {
$object->SetDBField('Modified_date', $now);
$object->SetDBField('Modified_time', $now);
}
$object->setRequired('PageCacheKey', $object->GetDBField('OverridePageCacheKey'));
$object->SetDBField('Template', $this->_stripTemplateExtension( $object->GetDBField('Template') ));
if ($object->GetDBField('Type') == PAGE_TYPE_TEMPLATE) {
if (!$this->_templateFound($object->GetDBField('Template'), $object->GetDBField('ThemeId'))) {
$object->SetError('Template', 'template_file_missing', 'la_error_TemplateFileMissing');
}
}
$this->_saveTitleField($object, 'Title');
$this->_saveTitleField($object, 'MenuTitle');
$root_category = $this->Application->getBaseCategory();
if ( file_exists(FULL_PATH . '/themes') && ($object->GetDBField('ParentId') == $root_category) && ($object->GetDBField('Template') == CATEGORY_TEMPLATE_INHERIT) ) {
// there are themes + creating top level category
$object->SetError('Template', 'no_inherit');
}
if ( !$this->Application->isAdminUser && $object->isVirtualField('cust_RssSource') ) {
// only administrator can set/change "cust_RssSource" field
if ($object->GetDBField('cust_RssSource') != $object->GetOriginalField('cust_RssSource')) {
$object->SetError('cust_RssSource', 'not_allowed', 'la_error_OperationNotAllowed');
}
}
if ( !$object->GetDBField('DirectLinkAuthKey') ) {
$key_parts = Array (
$object->GetID(),
$object->GetDBField('ParentId'),
$object->GetField('Name'),
'b38'
);
$object->SetDBField('DirectLinkAuthKey', substr( md5( implode(':', $key_parts) ), 0, 20 ));
}
}
/**
* Sets page name to requested field in case when:
* 1. page was auto created (through theme file rebuild)
* 2. requested field is empty
*
* @param kDBItem $object
* @param string $field
* @author Alex
*/
function _saveTitleField(&$object, $field)
{
$value = $object->GetField($field, 'no_default'); // current value of target field
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
/* @var $ml_formatter kMultiLanguage */
$src_field = $ml_formatter->LangFieldName('Name');
$dst_field = $ml_formatter->LangFieldName($field);
$dst_field_not_changed = $object->GetOriginalField($dst_field) == $value;
if ($value == '' || preg_match('/^_Auto: (.*)/', $value) || (($object->GetOriginalField($src_field) == $value) && $dst_field_not_changed)) {
// target field is empty OR target field value starts with "_Auto: " OR (source field value
// before change was equals to current target field value AND target field value wasn't changed)
$object->SetField($dst_field, $object->GetField($src_field));
}
}
/**
* Don't allow to delete system pages, when not in debug mode
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
+ parent::OnBeforeItemDelete($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('Protected') && !$this->Application->isDebugMode(false) ) {
$event->status = kEvent::erFAIL;
}
}
/**
* Creates category based on given TPL file
*
* @param CategoriesItem $object
* @param string $template
* @param int $theme_id
* @param int $system_mode
* @param array $template_info
* @return bool
*/
function _prepareAutoPage(&$object, $template, $theme_id = null, $system_mode = SMS_MODE_AUTO, $template_info = Array ())
{
$template = $this->_stripTemplateExtension($template);
if ($system_mode == SMS_MODE_AUTO) {
$page_type = $this->_templateFound($template, $theme_id) ? PAGE_TYPE_TEMPLATE : PAGE_TYPE_VIRTUAL;
}
else {
$page_type = $system_mode == SMS_MODE_FORCE ? PAGE_TYPE_TEMPLATE : PAGE_TYPE_VIRTUAL;
}
if (($page_type == PAGE_TYPE_TEMPLATE) && ($template_info === false)) {
// do not auto-create system pages, when browsing through site
return false;
}
if (!isset($theme_id)) {
$theme_id = $this->_getCurrentThemeId();
}
$root_category = $this->Application->getBaseCategory();
$page_category = $this->Application->GetVar('m_cat_id');
if (!$page_category) {
$page_category = $root_category;
$this->Application->SetVar('m_cat_id', $page_category);
}
if (($page_type == PAGE_TYPE_VIRTUAL) && (strpos($template, '/') !== false)) {
// virtual page, but have "/" in template path -> create it's path
$category_path = explode('/', $template);
$template = array_pop($category_path);
$page_category = $this->_getParentCategoryFromPath($category_path, $root_category, $theme_id);
}
$page_name = ($page_type == PAGE_TYPE_TEMPLATE) ? '_Auto: ' . $template : $template;
$page_description = '';
if ($page_type == PAGE_TYPE_TEMPLATE) {
$design_template = strtolower($template); // leading "/" not added !
if ($template_info) {
if (array_key_exists('name', $template_info) && $template_info['name']) {
$page_name = $template_info['name'];
}
if (array_key_exists('desc', $template_info) && $template_info['desc']) {
$page_description = $template_info['desc'];
}
if (array_key_exists('section', $template_info) && $template_info['section']) {
// this will override any global "m_cat_id"
$page_category = $this->_getParentCategoryFromPath(explode('||', $template_info['section']), $root_category, $theme_id);
}
}
}
else {
$design_template = $this->_getDefaultDesign(); // leading "/" added !
}
$object->Clear();
$object->SetDBField('ParentId', $page_category);
$object->SetDBField('Type', $page_type);
$object->SetDBField('Protected', 1); // $page_type == PAGE_TYPE_TEMPLATE
$object->SetDBField('IsMenu', 0);
$object->SetDBField('ThemeId', $theme_id);
// put all templates to then end of list (in their category)
$min_priority = $this->_getNextPriority($page_category, $object->TableName);
$object->SetDBField('Priority', $min_priority);
$object->SetDBField('Template', $design_template);
$object->SetDBField('CachedTemplate', $design_template);
$primary_language = $this->Application->GetDefaultLanguageId();
$current_language = $this->Application->GetVar('m_lang');
$object->SetDBField('l' . $primary_language . '_Name', $page_name);
$object->SetDBField('l' . $current_language . '_Name', $page_name);
$object->SetDBField('l' . $primary_language . '_Description', $page_description);
$object->SetDBField('l' . $current_language . '_Description', $page_description);
return $object->Create();
}
function _getParentCategoryFromPath($category_path, $base_category, $theme_id = null)
{
static $category_ids = Array ();
if (!$category_path) {
return $base_category;
}
if (array_key_exists(implode('||', $category_path), $category_ids)) {
return $category_ids[ implode('||', $category_path) ];
}
$backup_category_id = $this->Application->GetVar('m_cat_id');
$object =& $this->Application->recallObject($this->Prefix . '.rebuild-path', null, Array ('skip_autoload' => true));
/* @var $object CategoriesItem */
$parent_id = $base_category;
$filenames_helper =& $this->Application->recallObject('FilenamesHelper');
/* @var $filenames_helper kFilenamesHelper */
$safe_category_path = array_map(Array (&$filenames_helper, 'replaceSequences'), $category_path);
foreach ($category_path as $category_order => $category_name) {
$this->Application->SetVar('m_cat_id', $parent_id);
// get virtual category first, when possible
$sql = 'SELECT ' . $object->IDField . '
FROM ' . $object->TableName . '
WHERE
(
Filename = ' . $this->Conn->qstr($safe_category_path[$category_order]) . ' OR
Filename = ' . $this->Conn->qstr( $filenames_helper->replaceSequences('_Auto: ' . $category_name) ) . '
) AND
(ParentId = ' . $parent_id . ') AND
(ThemeId = 0 OR ThemeId = ' . $theme_id . ')
ORDER BY ThemeId ASC';
$parent_id = $this->Conn->GetOne($sql);
if ($parent_id === false) {
// page not found
$template = implode('/', array_slice($safe_category_path, 0, $category_order + 1));
// don't process system templates in sub-categories
$system = $this->_templateFound($template, $theme_id) && (strpos($template, '/') === false);
if (!$this->_prepareAutoPage($object, $category_name, $theme_id, $system ? SMS_MODE_FORCE : false)) {
// page was not created
break;
}
$parent_id = $object->GetID();
}
}
$this->Application->SetVar('m_cat_id', $backup_category_id);
$category_ids[ implode('||', $category_path) ] = $parent_id;
return $parent_id;
}
/**
* Returns theme name by it's id. Used in structure page creation.
*
* @param int $theme_id
* @return string
*/
function _getThemeName($theme_id)
{
static $themes = null;
if (!isset($themes)) {
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
$sql = 'SELECT Name, ' . $id_field . '
FROM ' . $table_name . '
WHERE Enabled = 1';
$themes = $this->Conn->GetCol($sql, $id_field);
}
return array_key_exists($theme_id, $themes) ? $themes[$theme_id] : false;
}
/**
* Resets SMS-menu cache
*
* @param kEvent $event
*/
function OnResetCMSMenuCache(&$event)
{
if ($this->Application->GetVar('ajax') == 'yes') {
$event->status = kEvent::erSTOP;
}
$this->_resetMenuCache();
$event->SetRedirectParam('action_completed', 1);
}
/**
* Performs reset of category-related caches (menu, structure dropdown, template mapping)
*
* @return void
* @access protected
*/
protected function _resetMenuCache()
{
// reset cms menu cache (all variables are automatically rebuild, when missing)
if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
$this->Application->rebuildCache('master:cms_menu', kCache::REBUILD_LATER, CacheSettings::$cmsMenuRebuildTime);
$this->Application->rebuildCache('master:StructureTree', kCache::REBUILD_LATER, CacheSettings::$structureTreeRebuildTime);
$this->Application->rebuildCache('master:template_mapping', kCache::REBUILD_LATER, CacheSettings::$templateMappingRebuildTime);
}
else {
$this->Application->rebuildDBCache('cms_menu', kCache::REBUILD_LATER, CacheSettings::$cmsMenuRebuildTime);
$this->Application->rebuildDBCache('StructureTree', kCache::REBUILD_LATER, CacheSettings::$structureTreeRebuildTime);
$this->Application->rebuildDBCache('template_mapping', kCache::REBUILD_LATER, CacheSettings::$templateMappingRebuildTime);
}
}
/**
* Updates structure config
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
if (defined('IS_INSTALL') && IS_INSTALL) {
// skip any processing, because Categories table doesn't exists until install is finished
return ;
}
$site_config_helper =& $this->Application->recallObject('SiteConfigHelper');
/* @var $site_config_helper SiteConfigHelper */
$settings = $site_config_helper->getSettings();
$root_category = $this->Application->getBaseCategory();
// set root category
$section_adjustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments');
$section_adjustments['in-portal:browse'] = Array (
'url' => Array ('m_cat_id' => $root_category),
'late_load' => Array ('m_cat_id' => $root_category),
'onclick' => 'checkCatalog(' . $root_category . ')',
);
$section_adjustments['in-portal:browse_site'] = Array (
'url' => Array ('editing_mode' => $settings['default_editing_mode']),
);
$this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_adjustments);
// prepare structure dropdown
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['ParentId']['default'] = (int)$this->Application->GetVar('m_cat_id');
$fields['ParentId']['options'] = $category_helper->getStructureTreeAsOptions();
// limit design list by theme
$theme_id = $this->_getCurrentThemeId();
$design_sql = $fields['Template']['options_sql'];
$design_sql = str_replace('(tf.FilePath = "/designs")', '(' . implode(' OR ', $this->getDesignFolders()) . ')' . ' AND (t.ThemeId = ' . $theme_id . ')', $design_sql);
$fields['Template']['options_sql'] = $design_sql;
// adds "Inherit From Parent" option to "Template" field
$fields['Template']['options'] = Array (CATEGORY_TEMPLATE_INHERIT => $this->Application->Phrase('la_opt_InheritFromParent'));
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
if ($this->Application->isAdmin) {
// don't sort by Front-End sorting fields
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
$remove_keys = Array ('DefaultSorting1Field', 'DefaultSorting2Field', 'DefaultSorting1Dir', 'DefaultSorting2Dir');
foreach ($remove_keys as $remove_key) {
unset($config_mapping[$remove_key]);
}
$this->Application->setUnitOption($event->Prefix, 'ConfigMapping', $config_mapping);
}
else {
// sort by parent path on Front-End only
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings', Array ());
$list_sortings['']['ForcedSorting'] = Array ("CurrentSort" => 'asc');
$this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
}
// add grids for advanced view (with primary category column)
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$process_grids = Array ('Default', 'Radio');
foreach ($process_grids as $process_grid) {
$grid_data = $grids[$process_grid];
$grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_parent_category_td', 'filter_block' => 'grid_like_filter');
$grids[$process_grid . 'ShowAll'] = $grid_data;
}
$this->Application->setUnitOption($this->Prefix, 'Grids', $grids);
}
/**
* Returns folders, that can contain design templates
*
* @return array
* @access protected
*/
protected function getDesignFolders()
{
$ret = Array ('tf.FilePath = "/designs"', 'tf.FilePath = "/platform/designs"');
foreach ($this->Application->ModuleInfo as $module_info) {
$ret[] = 'tf.FilePath = "/' . $module_info['TemplatePath'] . 'designs"';
}
return array_unique($ret);
}
/**
* Removes this item and it's children (recursive) from structure dropdown
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
if ( !$this->Application->isAdmin ) {
// calculate priorities dropdown only for admin
return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
// remove this category & it's children from dropdown
$sql = 'SELECT ' . $object->IDField . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE ParentPath LIKE "' . $object->GetDBField('ParentPath') . '%"';
$remove_categories = $this->Conn->GetCol($sql);
$options = $object->GetFieldOption('ParentId', 'options');
foreach ($remove_categories as $remove_category) {
unset($options[$remove_category]);
}
$object->SetFieldOption('ParentId', 'options', $options);
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object CategoriesItem */
// need to update path after category is created, so category is included in that path
$parent_path = $object->buildParentPath();
$sql = 'UPDATE ' . $object->TableName . '
SET ParentPath = ' . $this->Conn->qstr($parent_path) . '
WHERE CategoryId = ' . $object->GetID();
$this->Conn->Query($sql);
$object->SetDBField('ParentPath', $parent_path);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnAfterRebuildThemes(&$event)
{
$sql = 'SELECT t.ThemeId, CONCAT( tf.FilePath, \'/\', tf.FileName ) AS Path, tf.FileMetaInfo
FROM '.TABLE_PREFIX.'ThemeFiles AS tf
LEFT JOIN '.TABLE_PREFIX.'Themes AS t ON t.ThemeId = tf.ThemeId
WHERE t.Enabled = 1 AND tf.FileType = 1
AND (
SELECT COUNT(CategoryId)
FROM ' . TABLE_PREFIX . 'Categories c
WHERE CONCAT(\'/\', c.Template, \'.tpl\') = CONCAT( tf.FilePath, \'/\', tf.FileName ) AND (c.ThemeId = t.ThemeId)
) = 0 ';
$files = $this->Conn->Query($sql, 'Path');
if (!$files) {
// all possible pages are already created
return ;
}
set_time_limit(0);
ini_set('memory_limit', -1);
$dummy =& $this->Application->recallObject($event->Prefix . '.rebuild', null, Array ('skip_autoload' => true));
/* @var $dummy CategoriesItem */
$error_count = 0;
foreach ($files as $a_file => $file_info) {
$status = $this->_prepareAutoPage($dummy, $a_file, $file_info['ThemeId'], SMS_MODE_FORCE, unserialize($file_info['FileMetaInfo'])); // create system page
if (!$status) {
$error_count++;
}
}
if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) {
$updater =& $this->Application->makeClass('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
}
$this->_resetMenuCache();
if ($error_count) {
// allow user to review error after structure page creation
$event->MasterEvent->redirect = false;
}
}
/**
* Processes OnMassMoveUp, OnMassMoveDown events
*
* @param kEvent $event
*/
function OnChangePriority(&$event)
{
$this->Application->SetVar('priority_prefix', $event->getPrefixSpecial());
$event->CallSubEvent('priority:' . $event->Name);
$this->Application->StoreVar('RefreshStructureTree', 1);
$this->_resetMenuCache();
}
/**
* Completely recalculates priorities in current category
*
* @param kEvent $event
*/
function OnRecalculatePriorities(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$this->Application->SetVar('priority_prefix', $event->getPrefixSpecial());
$event->CallSubEvent('priority:' . $event->Name);
$this->_resetMenuCache();
}
/**
* Update Preview Block for FCKEditor
*
* @param kEvent $event
*/
function OnUpdatePreviewBlock(&$event)
{
$event->status = kEvent::erSTOP;
$string = kUtil::unhtmlentities($this->Application->GetVar('preview_content'));
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$string = $category_helper->replacePageIds($string);
$this->Application->StoreVar('_editor_preview_content_', $string);
}
/**
* Makes simple search for categories
* based on keywords string
*
* @param kEvent $event
*/
function OnSimpleSearch(&$event)
{
$event->redirect = false;
$search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
$keywords = kUtil::unhtmlentities( trim($this->Application->GetVar('keywords')) );
$query_object =& $this->Application->recallObject('HTTPQuery');
/* @var $query_object kHTTPQuery */
$sql = 'SHOW TABLES LIKE "'.$search_table.'"';
if ( !isset($query_object->Get['keywords']) && !isset($query_object->Post['keywords']) && $this->Conn->Query($sql) ) {
// used when navigating by pages or changing sorting in search results
return;
}
if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length'))
{
$this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
$this->Application->SetVar('keywords_too_short', 1);
return; // if no or too short keyword entered, doing nothing
}
$this->Application->StoreVar('keywords', $keywords);
$this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search
$keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_'));
$event->setPseudoClass('_List');
$object =& $event->getObject();
/* @var $object kDBList */
$this->Application->SetVar($event->getPrefixSpecial().'_Page', 1);
$lang = $this->Application->GetVar('m_lang');
$items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$module_name = 'In-Portal';
$sql = 'SELECT *
FROM ' . $this->Application->getUnitOption('confs', 'TableName') . '
WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1';
$search_config = $this->Conn->Query($sql, 'FieldName');
$field_list = array_keys($search_config);
$join_clauses = Array();
// field processing
$weight_sum = 0;
$alias_counter = 0;
$custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if ($custom_fields) {
$custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
}
// what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
$search_config_map = Array();
foreach ($field_list as $key => $field) {
$local_table = TABLE_PREFIX.$search_config[$field]['TableName'];
$weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause
// processing multilingual fields
if ( !$search_config[$field]['CustomFieldId'] && $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage' ) {
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$field_list[$key] = 'l'.$lang.'_'.$field;
if (!isset($search_config[$field]['ForeignField'])) {
$field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary'];
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
}
// processing fields from other tables
$foreign_field = $search_config[$field]['ForeignField'];
if ( $foreign_field ) {
$exploded = explode(':', $foreign_field, 2);
if ($exploded[0] == 'CALC') {
// ignoring having type clauses in simple search
unset($field_list[$key]);
continue;
}
else {
$multi_lingual = false;
if ($exploded[0] == 'MULTI') {
$multi_lingual = true;
$foreign_field = $exploded[1];
}
$exploded = explode('.', $foreign_field); // format: table.field_name
$foreign_table = TABLE_PREFIX.$exploded[0];
$alias_counter++;
$alias = 't'.$alias_counter;
if ($multi_lingual) {
$field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1];
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$search_config_map[ $field_list[$key] ] = $field;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
else {
$field_list[$key] = $alias.'.'.$exploded[1];
$search_config_map[ $field_list[$key] ] = $field;
}
$join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']);
$join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
$join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.'
ON '.$join_clause;
}
}
else {
// processing fields from local table
if ($search_config[$field]['CustomFieldId']) {
$local_table = 'custom_data';
// search by custom field value on current language
$custom_field_id = array_search($field_list[$key], $custom_fields);
$field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id;
// search by custom field value on primary language
$field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
$field_list[$key] = $local_table.'.'.$field_list[$key];
$search_config_map[ $field_list[$key] ] = $field;
}
}
// keyword string processing
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$where_clause = Array ();
foreach ($field_list as $field) {
if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) {
// local real field
$filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false);
if ($filter_data) {
$where_clause[] = $filter_data['value'];
}
}
elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) {
$custom_field_name = 'cust_' . $search_config_map[$field];
$filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false);
if ($filter_data) {
$where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']);
}
}
else {
$where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field));
}
}
$where_clause = '((' . implode(') OR (', $where_clause) . '))'; // 2 braces for next clauses, see below!
$where_clause = $where_clause . ' AND (' . $items_table . '.Status = ' . STATUS_ACTIVE . ')';
if ($event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild') {
if ($event->MasterEvent->getEventParam('ResultIds')) {
$where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')';
}
}
// exclude template based sections from search results (ie. registration)
if ( $this->Application->ConfigValue('ExcludeTemplateSectionsFromSearch') ) {
$where_clause .= ' AND ' . $items_table . '.ThemeId = 0';
}
// making relevance clause
$positive_words = $search_helper->getPositiveKeywords($keywords);
$this->Application->StoreVar('highlight_keywords', serialize($positive_words));
$revelance_parts = Array();
reset($search_config);
foreach ($positive_words as $keyword_index => $positive_word) {
$positive_word = $search_helper->transformWildcards($positive_word);
$positive_words[$keyword_index] = $this->Conn->escape($positive_word);
}
foreach ($field_list as $field) {
if (!array_key_exists($field, $search_config_map)) {
$map_key = $search_config_map[$items_table . '.' . $field];
}
else {
$map_key = $search_config_map[$field];
}
$config_elem = $search_config[ $map_key ];
$weight = $config_elem['Priority'];
// search by whole words only ([[:<:]] - word boundary)
/*$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.implode(' ', $positive_words).')[[:>:]]", '.$weight.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.$keyword.')[[:>:]]", '.$weight.', 0)';
}*/
// search by partial word matches too
$revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$weight.', 0)';
}
}
$revelance_parts = array_unique($revelance_parts);
$conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
$rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
$rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
$rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
$relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords;
if ($rel_pop && $object->isField('Hits')) {
$relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
}
if ($rel_rating && $object->isField('CachedRating')) {
$relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
}
// building final search query
if (!$this->Application->GetVar('do_not_drop_search_table')) {
$this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event
$this->Application->SetVar('do_not_drop_search_table', true);
}
$search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
if ($search_table_exists) {
$select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
}
else {
$select_intro = 'CREATE TABLE '.$search_table.' AS ';
}
$edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0';
$sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance,
'.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId,
'.$items_table.'.ResourceId,
'.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType,
'.$edpick_clause.' AS EdPick
FROM '.$object->TableName.'
'.implode(' ', $join_clauses).'
WHERE '.$where_clause.'
GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' ORDER BY Relevance DESC';
$this->Conn->Query($sql);
if ( !$search_table_exists ) {
$sql = 'ALTER TABLE ' . $search_table . '
ADD INDEX (ResourceId),
ADD INDEX (Relevance)';
$this->Conn->Query($sql);
}
}
/**
* Make record to search log
*
* @param string $keywords
* @param int $search_type 0 - simple search, 1 - advanced search
*/
function saveToSearchLog($keywords, $search_type = 0)
{
// don't save keywords for each module separately, just one time
// static variable can't help here, because each module uses it's own class instance !
if (!$this->Application->GetVar('search_logged')) {
$sql = 'UPDATE '.TABLE_PREFIX.'SearchLogs
SET Indices = Indices + 1
WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search
$this->Conn->Query($sql);
if ($this->Conn->getAffectedRows() == 0) {
$fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLogs');
}
$this->Application->SetVar('search_logged', 1);
}
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(kEvent &$event)
{
if ( $event->Special != '-virtual' ) {
parent::LoadItem($event);
return;
}
$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, null, true) ) {
$actions =& $this->Application->recallObject('kActions');
/* @var $actions Params */
$actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$object->setID($id);
}
}
/**
* Returns constrain for priority calculations
*
* @param kEvent $event
* @return void
* @see PriorityEventHandler
* @access protected
*/
- protected function OnGetConstrainInfo(&$event)
+ protected function OnGetConstrainInfo(kEvent &$event)
{
$constrain = ''; // for OnSave
$event_name = $event->getEventParam('original_event');
$actual_event_name = $event->getEventParam('actual_event');
if ( $actual_event_name == 'OnSavePriorityChanges' || $event_name == 'OnAfterItemLoad' || $event_name == 'OnAfterItemDelete' ) {
$object =& $event->getObject();
/* @var $object kDBItem */
$constrain = 'ParentId = ' . $object->GetDBField('ParentId');
}
elseif ( $actual_event_name == 'OnPreparePriorities' ) {
$constrain = 'ParentId = ' . $this->Application->GetVar('m_cat_id');
}
elseif ( $event_name == 'OnSave' ) {
$constrain = '';
}
else {
$constrain = 'ParentId = ' . $this->Application->GetVar('m_cat_id');
}
$event->setEventParam('constrain_info', Array ($constrain, ''));
}
/**
* Parses category part of url, build main part of url
*
* @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE.
* @param string $prefix Prefix, that listener uses for system integration
* @param Array $params Params, that are used for url building or created during url parsing.
* @param Array $url_parts Url parts to parse (only for parsing).
* @param bool $keep_events Keep event names in resulting url (only for building).
* @return bool|string|Array Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener.
*/
public function CategoryRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false)
{
if ($rewrite_mode == REWRITE_MODE_BUILD) {
return $this->_buildMainUrl($prefix, $params, $keep_events);
}
if ( $this->_parseFriendlyUrl($url_parts, $params) ) {
// friendly urls work like exact match only!
return false;
}
$this->_parseCategory($url_parts, $params);
return true;
}
/**
* Build main part of every url
*
* @param string $prefix_special
* @param Array $params
* @param bool $keep_events
* @return string
*/
protected function _buildMainUrl($prefix_special, &$params, $keep_events)
{
$ret = '';
list ($prefix) = explode('.', $prefix_special);
$rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor');
/* @var $rewrite_processor kRewriteUrlProcessor */
$processed_params = $rewrite_processor->getProcessedParams($prefix_special, $params, $keep_events);
if ($processed_params === false) {
return '';
}
// add language
if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $rewrite_processor->primaryLanguageId)) {
$language_name = $this->Application->getCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]');
if ($language_name === false) {
$sql = 'SELECT PackName
FROM ' . TABLE_PREFIX . 'Languages
WHERE LanguageId = ' . $processed_params['m_lang'];
$language_name = $this->Conn->GetOne($sql);
$this->Application->setCache('language_names[%LangIDSerial:' . $processed_params['m_lang'] . '%]', $language_name);
}
$ret .= $language_name . '/';
}
// add theme
if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $rewrite_processor->primaryThemeId)) {
$theme_name = $this->Application->getCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]');
if ($theme_name === false) {
$sql = 'SELECT Name
FROM ' . TABLE_PREFIX . 'Themes
WHERE ThemeId = ' . $processed_params['m_theme'];
$theme_name = $this->Conn->GetOne($sql);
$this->Application->setCache('theme_names[%ThemeIDSerial:' . $processed_params['m_theme'] . '%]', $theme_name);
}
$ret .= $theme_name . '/';
}
// inject custom url parts made by other rewrite listeners just after language/theme url parts
if ($params['inject_parts']) {
$ret .= implode('/', $params['inject_parts']) . '/';
}
// add category
if ($processed_params['m_cat_id'] > 0 && $params['pass_category']) {
$category_filename = $this->Application->getCategoryCache($processed_params['m_cat_id'], 'filenames');
preg_match('/^Content\/(.*)/i', $category_filename, $regs);
if ($regs) {
$template = array_key_exists('t', $params) ? $params['t'] : false;
if (strtolower($regs[1]) == strtolower($template)) {
// we could have category path like "Content/<template_path>" in this case remove template
$params['pass_template'] = false;
}
$ret .= $regs[1] . '/';
}
$params['category_processed'] = true;
}
// reset category page
$force_page_adding = false;
if (array_key_exists('reset', $params) && $params['reset']) {
unset($params['reset']);
if ($processed_params['m_cat_id']) {
$processed_params['m_cat_page'] = 1;
$force_page_adding = true;
}
}
if ((array_key_exists('category_processed', $params) && $params['category_processed'] && ($processed_params['m_cat_page'] > 1)) || $force_page_adding) {
// category name was added before AND category page number found
$ret = rtrim($ret, '/') . '_' . $processed_params['m_cat_page'] . '/';
}
$template = array_key_exists('t', $params) ? $params['t'] : false;
$category_template = ($processed_params['m_cat_id'] > 0) && $params['pass_category'] ? $this->Application->getCategoryCache($processed_params['m_cat_id'], 'category_designs') : '';
if ((strtolower($template) == '__default__') && ($processed_params['m_cat_id'] == 0)) {
// for "Home" category set template to index when not set
$template = 'index';
}
// remove template from url if it is category index cached template OR site homepage
if (($template == $category_template) || (mb_strtolower($template) == '__default__') || ($template == 'index')) {
// given template is also default template for this category OR '__default__' given OR site homepage
$params['pass_template'] = false;
}
if ($template && $params['pass_template']) {
$ret .= $template . '/';
}
return mb_strtolower( rtrim($ret, '/') );
}
/**
* Checks if whole url_parts matches a whole In-CMS page
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
protected function _parseFriendlyUrl($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE FriendlyURL = ' . $this->Conn->qstr(implode('/', $url_parts));
$friendly = $this->Conn->GetRow($sql);
$rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor');
/* @var $rewrite_processor kRewriteUrlProcessor */
if ($friendly) {
$vars['m_cat_id'] = $friendly['CategoryId'];
$vars['t'] = preg_replace('/^Content\//i', '', $friendly['NamedParentPath']);
while ($url_parts) {
$rewrite_processor->partParsed( array_shift($url_parts) );
}
return true;
}
return false;
}
/**
* Extracts category part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
protected function _parseCategory($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$res = false;
$url_part = array_shift($url_parts);
$category_id = 0;
$last_category_info = false;
$category_path = $url_part == 'content' ? '' : 'content';
$rewrite_processor =& $this->Application->recallObject('kRewriteUrlProcessor');
/* @var $rewrite_processor kRewriteUrlProcessor */
do {
$category_path = trim($category_path . '/' . $url_part, '/');
// bb_<topic_id> -> forums/bb_2
if ( !preg_match('/^bb_[\d]+$/', $url_part) && preg_match('/(.*)_([\d]+)$/', $category_path, $rets) ) {
$category_path = $rets[1];
$vars['m_cat_page'] = $rets[2];
}
$sql = 'SELECT CategoryId, SymLinkCategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ') AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
$category_info = $this->Conn->GetRow($sql);
if ($category_info !== false) {
$last_category_info = $category_info;
$rewrite_processor->partParsed($url_part);
$url_part = array_shift($url_parts);
$res = true;
}
} while ($category_info !== false && $url_part);
if ($last_category_info) {
// this category is symlink to other category, so use it's url instead
// (used in case if url prior to symlink adding was indexed by spider or was bookmarked)
if ($last_category_info['SymLinkCategoryId']) {
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE (CategoryId = ' . $last_category_info['SymLinkCategoryId'] . ')';
$category_info = $this->Conn->GetRow($sql);
if ($category_info) {
// web symlinked category was found use it
// TODO: maybe 302 redirect should be made to symlinked category url (all other url parts should stay)
$last_category_info = $category_info;
}
}
// 1. Set virtual page as template, this will be replaced to physical template later in kApplication::Run.
// 2. Don't set CachedTemplate field as template here, because we will loose original page associated with it's cms blocks!
$vars['t'] = mb_strtolower( preg_replace('/^Content\//i', '', $last_category_info['NamedParentPath']), 'UTF-8' );
$vars['m_cat_id'] = $last_category_info['CategoryId'];
$vars['is_virtual'] = true; // for template from POST, strange code there!
}
else {
$vars['m_cat_id'] = 0;
}
return $res;
}
/**
* 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());
}
}
/**
* 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)
+ protected function OnBeforeClone(kEvent &$event)
{
parent::OnBeforeClone($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('ResourceId', 0); // this will reset it
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/themes/themes_eh.php
===================================================================
--- branches/5.2.x/core/units/themes/themes_eh.php (revision 15064)
+++ branches/5.2.x/core/units/themes/themes_eh.php (revision 15065)
@@ -1,199 +1,203 @@
<?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 ThemesEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnChangeTheme' => Array('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnItemBuild' ) {
// check permission without using $event->getSection(),
// so first cache rebuild won't lead to "ldefault_Name" field being used
return true;
}
return parent::CheckPermission($event);
}
/**
* Allows to set selected theme as primary
*
* @param kEvent $event
*/
function OnSetPrimary(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$id = array_shift($ids);
$this->setPrimary($id);
$rebuild_event = new kEvent('adm:OnRebuildThemes');
$this->Application->HandleEvent($rebuild_event);
}
$this->clearSelectedIDs($event);
}
function setPrimary($id)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'UPDATE '.$table_name.'
SET PrimaryTheme = 0';
$this->Conn->Query($sql);
$sql = 'UPDATE '.$table_name.'
SET PrimaryTheme = 1, Enabled = 1
WHERE '.$id_field.' = '.$id;
$this->Conn->Query($sql);
}
/**
* Set's primary theme (when checkbox used on editing form)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterCopyToLive(&$event)
+ protected function OnAfterCopyToLive(kEvent &$event)
{
- $object =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true, 'live_table' => true));
+ parent::OnAfterCopyToLive($event);
+
+ $object =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true, 'live_table' => true));
/* @var $object kDBItem */
$object->Load($event->getEventParam('id'));
- if ($object->GetDBField('PrimaryTheme')) {
+ if ( $object->GetDBField('PrimaryTheme') ) {
$this->setPrimary($event->getEventParam('id'));
}
}
/**
* Also rebuilds theme files, when enabled theme is saved
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
if ( ($event->status != kEvent::erSUCCESS) || !$event->getEventParam('ids') ) {
return ;
}
$ids = $event->getEventParam('ids');
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT COUNT(*)
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . $ids . ') AND (Enabled = 1)';
$enabled_themes = $this->Conn->GetOne($sql);
if ( $enabled_themes ) {
$rebuild_event = new kEvent('adm:OnRebuildThemes');
$this->Application->HandleEvent($rebuild_event);
}
}
/**
* Allows to change the theme
*
* @param kEvent $event
*/
function OnChangeTheme(&$event)
{
if ($this->Application->isAdminUser) {
// for structure theme dropdown
$this->Application->StoreVar('theme_id', $this->Application->GetVar('theme'));
$this->Application->StoreVar('RefreshStructureTree', 1);
return ;
}
$this->Application->SetVar('t', 'index');
$this->Application->SetVar('m_cat_id', 0);
$this->Application->SetVar('m_theme', $this->Application->GetVar('theme'));
}
/**
* Apply system filter to themes list
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( in_array($event->Special, Array ('enabled', 'selected', 'available')) || !$this->Application->isAdminUser ) {
// "enabled" special or Front-End
$object->addFilter('enabled_filter', '%1$s.Enabled = ' . STATUS_ACTIVE);
}
// site domain theme picker
if ( $event->Special == 'selected' || $event->Special == 'available' ) {
$edit_picker_helper =& $this->Application->recallObject('EditPickerHelper');
/* @var $edit_picker_helper EditPickerHelper */
$edit_picker_helper->applyFilter($event, 'Themes');
}
// apply domain-based theme filtering
$themes = $this->Application->siteDomainField('Themes');
if ( strlen($themes) ) {
$themes = explode('|', substr($themes, 1, -1));
$object->addFilter('domain_filter', '%1$s.ThemeId IN (' . implode(',', $themes) . ')');
}
}
}
Index: branches/5.2.x/core/units/country_states/country_state_eh.php
===================================================================
--- branches/5.2.x/core/units/country_states/country_state_eh.php (revision 15064)
+++ branches/5.2.x/core/units/country_states/country_state_eh.php (revision 15065)
@@ -1,153 +1,155 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2010 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 CountryStateEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnGetStatesJSON' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Applies edit picker filters
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( ($event->Special == 'selected') || ($event->Special == 'available') ) {
$edit_picker_helper =& $this->Application->recallObject('EditPickerHelper');
/* @var $edit_picker_helper EditPickerHelper */
$edit_picker_helper->applyFilter($event, 'Countries');
// only countries
$object->addFilter('type_filter', '%1$s.Type = ' . DESTINATION_TYPE_COUNTRY);
}
}
/**
* Makes sure, that state country is always specified
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->_setRequired($event);
}
/**
* Makes sure, that state country is always specified
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_setRequired($event);
}
/**
* Makes sure, that state country is always specified
*
* @param kEvent $event
*/
function _setRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$field_options = $object->GetFieldOptions('IsoCode');
if ($object->GetDBField('Type') == DESTINATION_TYPE_STATE) {
$object->setRequired('StateCountryId');
$field_options['unique'] = Array ('Type', 'StateCountryId');
}
else {
$object->setRequired('StateCountryId', false);
$field_options['unique'] = Array ('Type');
}
$object->SetFieldOptions('IsoCode', $field_options);
}
/**
* Don't allow to delete countries, that have states
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
parent::OnBeforeItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
- if ($cs_helper->CountryHasStates( $object->GetDBField('IsoCode') )) {
+ if ( $cs_helper->CountryHasStates($object->GetDBField('IsoCode')) ) {
$event->status = kEvent::erFAIL;
- return ;
+ return;
}
}
/**
* Returns given country states in JSON format
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnGetStatesJSON(kEvent &$event)
{
$event->status = kEvent::erSTOP;
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$states = $cs_helper->getStates( (string)$this->Application->GetVar('country_iso') );
echo json_encode($states);
}
}
Index: branches/5.2.x/core/units/skins/skin_eh.php
===================================================================
--- branches/5.2.x/core/units/skins/skin_eh.php (revision 15064)
+++ branches/5.2.x/core/units/skins/skin_eh.php (revision 15065)
@@ -1,158 +1,160 @@
<?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 SkinEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* With "primary" special loads primary skin
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'primary' ) {
return Array ('IsPrimary' => 1);
}
return parent::getPassedID($event);
}
/**
* Allows to set selected theme as primary
*
* @param kEvent $event
*/
function OnSetPrimary(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$id = array_shift($ids);
$this->setPrimary($id);
}
$this->clearSelectedIDs($event);
}
function setPrimary($id)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'UPDATE '.$table_name.'
SET IsPrimary = 0';
$this->Conn->Query($sql);
$sql = 'UPDATE '.$table_name.'
SET IsPrimary = 1
WHERE '.$id_field.' = '.$id;
$this->Conn->Query($sql);
}
/**
* Don't make cloned skin primary
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeClone(&$event)
+ protected function OnBeforeClone(kEvent &$event)
{
parent::OnBeforeClone($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('IsPrimary', 0);
}
/**
* Re-compile skin, after it's changed (live table only)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
- if (!$object->IsTempTable()) {
+ if ( !$object->IsTempTable() ) {
$skin_helper =& $this->Application->recallObject('SkinHelper');
/* @var $skin_helper SkinHelper */
$skin_helper->compile($object);
}
}
/**
* [HOOK] Compile stylesheet file based on theme definitions
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCompileStylesheet(&$event)
{
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$object->SwitchToLive();
$ids = $event->MasterEvent->getEventParam('ids');
if ( !is_array($ids) ) {
$ids = explode(',', $ids);
}
if ( !$ids ) {
return ;
}
$skin_helper =& $this->Application->recallObject('SkinHelper');
/* @var $skin_helper SkinHelper */
foreach ($ids as $id) {
$object->Load($id);
$skin_helper->compile($object);
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/promo_blocks/promo_block_eh.php
===================================================================
--- branches/5.2.x/core/units/promo_blocks/promo_block_eh.php (revision 15064)
+++ branches/5.2.x/core/units/promo_blocks/promo_block_eh.php (revision 15065)
@@ -1,349 +1,349 @@
<?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 PromoBlockEventHandler extends kDBEventHandler {
/**
* Define alternative event processing method names
*
* @return void
* @see kEventHandler::$eventMethods
* @access protected
*/
protected function mapEvents()
{
parent::mapEvents();
$events_map = Array (
'OnMassMoveUp' => 'OnChangePriority',
'OnMassMoveDown' => 'OnChangePriority',
);
$this->eventMethods = array_merge($this->eventMethods, $events_map);
}
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array ('self' => true),
'OnSetSticky' => Array ('self' => 'view'),
'OnRegisterView' => Array ('self' => true),
'OnFollowLink' => Array ('self' => true),
'OnResetCounters' => Array ('self' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Sets default value for promo block group
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnPreCreate(&$event)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$promo_block_group =& $this->Application->recallObject('promo-block-group');
/* @var $promo_block_group kDBItem */
$object->SetDBField('PromoBlockGroupId', $promo_block_group->GetID());
}
/**
* Processes OnMassMoveUp, OnMassMoveDown events
*
* @param kEvent $event
*/
function OnChangePriority(&$event)
{
$this->Application->SetVar('priority_prefix', $event->getPrefixSpecial());
$event->CallSubEvent('priority:' . $event->Name);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( $this->Application->isAdmin ) {
$promo_block_group =& $this->Application->recallObject('promo-block-group');
/* @var $promo_block_group kDBItem */
$object->addFilter('promo_group_filter', '%1$s.PromoBlockGroupId = ' . $promo_block_group->GetID());
return;
}
$group_id = $event->getEventParam('group_id');
if ( !$group_id ) {
$page =& $this->Application->recallObject('st');
/* @var $page CategoriesItem */
$group_id = $page->GetDBField('PromoBlockGroupId');
}
$object->addFilter('status_filter', '%1$s.Status = ' . STATUS_ACTIVE);
$object->addFilter('scheduled_from_filter', '%1$s.ScheduleFromDate IS NULL OR %1$s.ScheduleFromDate <= ' . TIMENOW);
$object->addFilter('scheduled_to_filter', '%1$s.ScheduleToDate IS NULL OR %1$s.ScheduleToDate >= ' . TIMENOW);
$object->addFilter('promo_group_filter', $group_id ? '%1$s.PromoBlockGroupId = ' . $group_id : 'FALSE');
}
/**
* Set's block as sticky
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetSticky(kEvent &$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$ids = $this->StoreSelectedIDs($event);
if ( $ids ) {
$id = array_shift($ids);
$sql = 'UPDATE ' . $object->TableName . '
SET Sticky = 0';
$this->Conn->Query($sql);
$sql = 'UPDATE ' . $object->TableName . '
SET Sticky = 1, Status = ' . STATUS_ACTIVE . '
WHERE BlockId = ' . $id;
$this->Conn->Query($sql);
}
$this->clearSelectedIDs($event);
}
/**
* Set Required fields
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->_itemChanged($event);
}
/**
* Set Required fields
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_itemChanged($event);
}
/**
* Schedule dates
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function _itemChanged(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$date_from = $object->GetDBField('ScheduleFromDate_date');
$date_to = $object->GetDBField('ScheduleToDate_date');
if ( $date_from && $date_to && $date_from >= $date_to ) {
$object->SetError('ScheduleFromDate_date', 'wrong_date_interval');
}
$object->setRequired('CategoryId', $object->GetDBField('LinkType') == PromoBlockType::INTERNAL);
$object->setRequired('ExternalLink', $object->GetDBField('LinkType') == PromoBlockType::EXTERNAL);
}
/**
* Registers view of the promo block
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnRegisterView(kEvent &$event)
{
$this->_incrementField($event, 'NumberOfViews');
}
/**
* Registers click on the promo block
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnFollowLink(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$this->_incrementField($event, 'NumberOfClicks', false);
if ( $object->GetDBField('LinkType') == 1 ) { // Internal
$sql = 'SELECT NamedParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE CategoryId = ' . $object->GetDBField('CategoryId');
$event->redirect = $this->Conn->GetOne($sql);
$event->SetRedirectParam('pass', 'm');
}
else {
$ext_url = $object->GetDBField('ExternalLink');
$event->redirect = 'external:' . (preg_match('/^(http|ftp):\\/\\/.*/', $ext_url) ? $ext_url : $this->Application->BaseURL() . $ext_url);
}
}
/**
* Increment given promo block counters
*
* @param kEvent $event
* @param string $field
* @param bool $is_ajax
* @return void
* @access protected
*/
protected function _incrementField(kEvent &$event, $field, $is_ajax = true)
{
if ( $is_ajax ) {
$event->status = kEvent::erSTOP;
if ( $this->Application->GetVar('ajax') != 'yes' ) {
return ;
}
}
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->isLoaded() ) {
echo 'FAILED';
return ;
}
// don't use kDBItem::Update to support concurrent view updates from different visitors
$sql = 'UPDATE ' . $object->TableName . '
SET ' . $field . ' = ' . $field . ' + 1
WHERE ' . $object->IDField . ' = ' . $object->GetID();
$this->Conn->Query($sql);
echo 'OK';
}
/**
* Resets promo block counters
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnResetCounters(kEvent &$event)
{
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$ids = $this->StoreSelectedIDs($event);
foreach ($ids as $id) {
$object->Load($id);
$object->SetDBField('NumberOfViews', 0);
$object->SetDBField('NumberOfClicks', 0);
$object->Update();
}
$this->clearSelectedIDs($event);
}
/**
* Occurs, when config was parsed, allows to change config data dynamically
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions();
// images multilang fields
$a_image = Array(
'type' => 'string', 'max_len' => 255,
'formatter' => 'kUploadFormatter', 'upload_dir' => IMAGES_PATH . 'promo_blocks/',
'multiple' => 1, 'thumb_format' => 'resize:100x100',
'file_types' => '*.jpg;*.gif;*.png', 'files_description' => '!la_hint_ImageFiles!',
'required' => 1, 'not_null' => 1, 'default' => '',
);
// get active languages
$sql = 'SELECT LanguageId
FROM ' . TABLE_PREFIX . 'Languages';
$languages = $this->Conn->GetCol($sql);
foreach ($languages AS $lang_id) {
$fields['l' . $lang_id . '_Image'] = $a_image;
}
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
}
Index: branches/5.2.x/core/units/translator/translator_event_handler.php
===================================================================
--- branches/5.2.x/core/units/translator/translator_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/translator/translator_event_handler.php (revision 15065)
@@ -1,181 +1,181 @@
<?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 TranslatorEventHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnChangeLanguage' => Array('subitem' => 'add|edit'),
'OnSaveAndClose' => Array('subitem' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Check permission of item, that being translated
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
list($prefix, ) = $this->getPrefixAndField($event);
$top_prefix = $this->Application->GetTopmostPrefix($prefix, true);
$event->setEventParam('top_prefix', $top_prefix);
return parent::CheckPermission($event);
}
/**
* Returns prefix and field being translated
*
* @param kEvent $event
*/
function getPrefixAndField(&$event)
{
$field = $this->Application->GetVar($event->getPrefixSpecial(true).'_field');
if (strpos($field,':') !== false) {
list($prefix, $field) = explode(':', $field);
}
else {
$prefix = $this->Application->GetVar($event->getPrefixSpecial(true).'_prefix');
}
return Array($prefix, $field);
}
/**
* Loads record to be translated
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnLoad(&$event)
{
list($obj_prefix, $field) = $this->getPrefixAndField($event);
$object =& $this->Application->recallObject($obj_prefix);
/* @var $object kDBItem */
$translator =& $event->getObject();
/* @var $translator kDBItem */
$def_lang = $this->Application->GetDefaultLanguageId();
$current_lang = $translator->GetDBField('Language');
if (!$current_lang) $current_lang = $this->Application->RecallVar('trans_lang');
if (!$current_lang) $current_lang = $this->Application->GetVar('m_lang');
/*if ($current_lang == $def_lang) {
$current_lang = $def_lang + 1;
}*/
$this->Application->StoreVar('trans_lang', $current_lang); //remember translation language for user friendlyness
$translator->SetID(1);
$translator->SetDBField('Original', $object->GetDBField('l'.$this->Application->GetVar('m_lang').'_'.$field));
$translator->SetDBField('Language', $current_lang);
$translator->SetDBField('SwitchLanguage', $current_lang);
$translator->SetDBField('Translation', $object->GetDBField('l'.$current_lang.'_'.$field));
$cur_lang =& $this->Application->recallObject('lang.current');
/* @var $cur_lang LanguagesItem */
$cur_lang->Load($current_lang);
$translator->SetDBField('Charset', $cur_lang->GetDBField('Charset'));
$event->redirect = false;
}
/**
* Saves changes into temporary table and closes editing window
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSaveAndClose(&$event)
{
$event->CallSubEvent('OnPreSave');
$event->SetRedirectParam('opener', 'u');
}
/**
* 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)
+ protected function OnPreSave(kEvent &$event)
{
$translator =& $event->getObject();
/* @var $translator kDBItem */
$field_values = $this->getSubmittedFields($event);
$translator->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
list($obj_prefix, $field) = $this->getPrefixAndField($event);
$object =& $this->Application->recallObject($obj_prefix);
/* @var $object kDBItem */
$lang = $translator->GetDBField('Language');
$object->SetFieldOptions('l' . $lang . '_' . $field, Array ());
$object->SetDBField('l' . $lang . '_' . $field, $translator->GetDBField('Translation'));
$this->RemoveRequiredFields($object);
$object->Update();
}
/**
* Changes current language in translation popup
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnChangeLanguage(&$event)
{
$event->CallSubEvent('OnPreSave');
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('Language', $object->GetDBField('SwitchLanguage'));
$event->CallSubEvent('OnLoad');
$event->redirect = false;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/related_searches/related_searches_event_handler.php
===================================================================
--- branches/5.2.x/core/units/related_searches/related_searches_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/related_searches/related_searches_event_handler.php (revision 15065)
@@ -1,37 +1,39 @@
<?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 RelatedSearchEventHandler extends kDBEventHandler
{
/**
- * Initializes new relation
+ * Prepares new kDBItem object
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$table_info = $object->getLinkedInfo();
$source_itemtype = $this->Application->getUnitOption($table_info['ParentPrefix'], 'ItemType');
$object->SetDBField('ItemType', $source_itemtype);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php
===================================================================
--- branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php (revision 15064)
+++ branches/5.2.x/core/units/mailing_lists/mailing_list_eh.php (revision 15065)
@@ -1,333 +1,340 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class MailingListEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnCancelMailing' => Array ('self' => 'edit'),
'OnGenerateEmailQueue' => Array ('self' => true),
'OnProcessEmailQueue' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Prepare recipient list
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$recipient_type = $this->Application->GetVar('mailing_recipient_type');
- if (!$recipient_type) {
- return ;
+ if ( !$recipient_type ) {
+ return;
}
$recipients = $this->Application->GetVar($recipient_type);
- if ($recipients) {
+ if ( $recipients ) {
$object =& $event->getObject();
/* @var $object kDBItem */
$to = $recipient_type . '_' . implode(';' . $recipient_type . '_', array_keys($recipients));
$object->SetDBField('To', $to);
}
}
/**
* Don't allow to delete mailings in progress
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
- if ($event->Name == 'OnMassDelete' && $type == 'before') {
+ if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
- if ($ids) {
+
+ if ( $ids ) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $ids) . ') AND Status <> ' . MailingList::PARTIALLY_PROCESSED;
$allowed_ids = $this->Conn->GetCol($sql);
$event->setEventParam('ids', $allowed_ids);
}
}
}
/**
- * Delete all realted mails in email queue
+ * Delete all related mails in email queue
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$this->_deleteQueue($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// delete mailing attachments after mailing is deleted
$attachments = $object->GetField('Attachments', 'file_paths');
- if ($attachments) {
+ if ( $attachments ) {
$attachments = explode('|', $attachments);
foreach ($attachments as $attachment_file) {
- if (file_exists($attachment_file)) {
+ if ( file_exists($attachment_file) ) {
unlink($attachment_file);
}
}
}
}
/**
* Cancels given mailing and deletes all it's email queue
*
* @param kEvent $event
*/
function OnCancelMailing(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
foreach ($ids as $id) {
$object->Load($id);
$object->SetDBField('Status', MailingList::CANCELLED);
$object->Update();
}
}
$this->clearSelectedIDs($event);
}
/**
* Checks, that at least one message text field is filled
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$this->Application->GetVar('mailing_recipient_type') ) {
// user manually typed email addresses -> normalize
$recipients = str_replace(',', ';', $object->GetDBField('To'));
$recipients = array_map('trim', explode(';', $recipients));
$object->SetDBField('To', implode(';', $recipients));
}
if ( !$object->GetDBField('MessageText') ) {
$object->setRequired('MessageHtml');
}
// remember user, who created mailing, because of his name
// is needed for "From" field, but mailing occurs from cron
$user_id = $this->Application->RecallVar('user_id');
$object->SetDBField('PortalUserId', $user_id);
}
/**
* Deletes mailing list email queue, when it becomes cancelled
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$status = $object->GetDBField('Status');
- if (($status != $object->GetOriginalField('Status')) && ($status == MailingList::CANCELLED)) {
+ if ( ($status != $object->GetOriginalField('Status')) && ($status == MailingList::CANCELLED) ) {
$this->_deleteQueue($event);
}
}
/**
* Deletes email queue records related with given mailing list
*
* @param kEvent $event
*/
function _deleteQueue(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'DELETE FROM ' . $this->Application->getUnitOption('email-queue', 'TableName') . '
WHERE MailingId = ' . $object->GetID();
$this->Conn->Query($sql);
}
/**
* Allows to safely get mailing configuration variables
*
* @param string $variable_name
* @return int
*/
function _ensureDefault($variable_name)
{
$value = $this->Application->ConfigValue($variable_name);
if ($value === false) {
// ensure default value, when configuration variable is missing
return 10;
}
if (!$value) {
// configuration variable found, but it's value is empty or zero
return false;
}
return $value;
}
/**
* Generates email queue for active mailing lists
*
* @param kEvent $event
*/
function OnGenerateEmailQueue(&$event)
{
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$where_clause = Array (
'Status NOT IN (' . MailingList::CANCELLED . ',' . MailingList::PROCESSED . ')',
'(EmailsQueued < EmailsTotal) OR (EmailsTotal = 0)',
'`To` <> ""',
);
$sql = 'SELECT *
FROM ' . $table_name . '
WHERE (' . implode(') AND (', $where_clause) . ')
ORDER BY ' . $id_field . ' ASC';
$mailing_lists = $this->Conn->Query($sql, $id_field);
if (!$mailing_lists) {
return ;
}
// queue 10 emails per step summary from all mailing lists (FIFO logic)
$to_queue = $this->_ensureDefault('MailingListQueuePerStep');
if ($to_queue === false) {
return ;
}
$mailing_list_helper =& $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
foreach ($mailing_lists as $mailing_id => $mailing_data) {
if ($mailing_data['EmailsTotal'] == 0) {
// no work performed on this mailing list -> calculate totals
$updated_fields = $mailing_list_helper->generateRecipients($mailing_id, $mailing_data);
$updated_fields['Status'] = MailingList::PARTIALLY_PROCESSED;
$mailing_data = array_merge($mailing_data, $updated_fields);
$this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id);
}
$emails = unserialize( $mailing_data['ToParsed'] );
if (!$emails) {
continue;
}
// queue allowed count of emails
$i = 0;
$process_count = count($emails) >= $to_queue ? $to_queue : count($emails);
while ($i < $process_count) {
$mailing_list_helper->queueEmail($emails[$i], $mailing_id, $mailing_data);
$i++;
}
// remove processed emails from array
$to_queue -= $process_count; // decrement available for processing email count
array_splice($emails, 0, $process_count);
$updated_fields = Array (
'ToParsed' => serialize($emails),
'EmailsQueued' => $mailing_data['EmailsQueued'] + $process_count,
);
$mailing_data = array_merge($mailing_data, $updated_fields);
$this->Conn->doUpdate($updated_fields, $table_name, $id_field . ' = ' . $mailing_id);
if (!$to_queue) {
// emails to be queued per step reached -> leave
break;
}
}
}
/**
* Process email queue from cron
*
* @param kEvent $event
*/
function OnProcessEmailQueue(&$event)
{
$deliver_count = $this->_ensureDefault('MailingListSendPerStep');
if ($deliver_count === false) {
return ;
}
$queue_table = $this->Application->getUnitOption('email-queue', 'TableName');
// get queue part to send
$sql = 'SELECT *
FROM ' . $queue_table . '
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')
LIMIT 0,' . $deliver_count;
$messages = $this->Conn->Query($sql);
if (!$messages) {
// no more messages left in queue
return ;
}
$mailing_list_helper =& $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
$mailing_list_helper->processQueue($messages);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/custom_fields/custom_fields_event_handler.php
===================================================================
--- branches/5.2.x/core/units/custom_fields/custom_fields_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/custom_fields/custom_fields_event_handler.php (revision 15065)
@@ -1,349 +1,352 @@
<?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 CustomFieldsEventHandler extends kDBEventHandler {
/**
* Changes permission section to one from REQUEST, not from config
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
$sql = 'SELECT Prefix
FROM '.TABLE_PREFIX.'ItemTypes
WHERE ItemType = '.$this->Conn->qstr( $this->Application->GetVar('cf_type') );
$main_prefix = $this->Conn->GetOne($sql);
$section = $this->Application->getUnitOption($main_prefix.'.custom', 'PermSection');
$event->setEventParam('PermSection', $section);
return parent::CheckPermission($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
$item_type = $this->Application->GetVar('cf_type');
if ( !$item_type ) {
$prefix = $event->getEventParam('SourcePrefix');
$item_type = $this->Application->getUnitOption($prefix, 'ItemType');
}
if ( $event->Special == 'general' ) {
$object->addFilter('generaltab_filter', '%1$s.OnGeneralTab = 1');
}
if ( $item_type ) {
$hidden_fields = $this->Conn->qstrArray($this->_getHiddenFields($event));
if ( $hidden_fields ) {
$object->addFilter('hidden_filter', '%1$s.FieldName NOT IN (' . implode(',', $hidden_fields) . ')');
}
$object->addFilter('itemtype_filter', '%1$s.Type = ' . $item_type);
}
if ( !($this->Application->isDebugMode() && $this->Application->isAdminUser) ) {
$object->addFilter('user_filter', '%1$s.IsSystem = 0');
}
}
/**
* Returns prefix, that custom fields are printed for
*
* @param kEvent $event
* @return string
*/
function _getSourcePrefix(&$event)
{
$prefix = $event->getEventParam('SourcePrefix');
if (!$prefix) {
$sql = 'SELECT Prefix
FROM ' . TABLE_PREFIX . 'ItemTypes
WHERE ItemType = ' . $this->Conn->qstr( $this->Application->GetVar('cf_type') );
$prefix = $this->Conn->GetOne($sql);
}
return $prefix;
}
/**
* Get custom fields, that should no be shown anywhere
*
* @param kEvent $event
* @return Array
* @access protected
*/
protected function _getHiddenFields(&$event)
{
$prefix = $this->_getSourcePrefix($event);
$hidden_fields = Array ();
$virtual_fields = $this->Application->getUnitOption($prefix, 'VirtualFields', Array ());
$custom_fields = $this->Application->getUnitOption($prefix, 'CustomFields', Array ());
/* @var $custom_fields Array */
foreach ($custom_fields as $custom_field) {
$check_field = 'cust_' . $custom_field;
$show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true;
if ( ($show_mode === false) || (($show_mode === smDEBUG) && !(defined('DEBUG_MODE') && DEBUG_MODE)) ) {
$hidden_fields[] = $custom_field;
}
}
return $hidden_fields;
}
/**
* Prevents from duplicate item creation
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'SELECT COUNT(*)
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE FieldName = ' . $this->Conn->qstr($object->GetDBField('FieldName')) . ' AND Type = ' . $object->GetDBField('Type');
$found = $this->Conn->GetOne($sql);
if ( $found ) {
$event->status = kEvent::erFAIL;
$object->SetError('FieldName', 'duplicate', 'la_error_CustomExists');
}
}
/**
* Occurs after deleting item, id of deleted item
* is stored as 'id' param of event
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
+ parent::OnAfterItemDelete($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
- $main_prefix = $this->getPrefixByItemType( $object->GetDBField('Type') );
+ $main_prefix = $this->getPrefixByItemType($object->GetDBField('Type'));
$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
// call main item config to clone cdata table
$this->Application->getUnitOption($main_prefix, 'TableName');
$ml_helper->deleteField($main_prefix . '-cdata', $event->getEventParam('id'));
}
/**
* Get config prefix based on item type
*
* @param int $item_type
* @return string
* @access protected
*/
protected function getPrefixByItemType($item_type)
{
$sql = 'SELECT Prefix
FROM ' . TABLE_PREFIX . 'ItemTypes
WHERE ItemType = ' . $item_type;
return $this->Conn->GetOne($sql);
}
/**
* Creates new database columns, once custom field is successfully created
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSaveCustomField(&$event)
{
if ( $event->MasterEvent->status != kEvent::erSUCCESS ) {
return ;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$main_prefix = $this->getPrefixByItemType($object->GetDBField('Type'));
$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
// call main item config to clone cdata table
define('CUSTOM_FIELD_ADDED', 1); // used in cdata::scanCustomFields method
$this->Application->getUnitOption($main_prefix, 'TableName');
$ml_helper->createFields($main_prefix . '-cdata');
}
/**
* 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)
+ protected function OnMassDelete(kEvent &$event)
{
parent::OnMassDelete($event);
$event->SetRedirectParam('opener', 's');
}
/**
* 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)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('Type', $this->Application->GetVar('cf_type'));
}
/**
* Prepares ValueList field's value as xml for editing
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !in_array($object->GetDBField('ElementType'), $this->_getMultiElementTypes()) ) {
return ;
}
$custom_field_helper =& $this->Application->recallObject('InpCustomFieldsHelper');
/* @var $custom_field_helper InpCustomFieldsHelper */
$options = $custom_field_helper->GetValuesHash($object->GetDBField('ValueList'), VALUE_LIST_SEPARATOR, false);
$records = Array ();
$option_key = key($options);
if ( $option_key === '' || $option_key == 0 ) {
// remove 1st empty option, and add it later, when options will be saved, but allow string option keys
unset($options[$option_key]); // keep index, don't use array_unshift!
}
foreach ($options as $option_key => $option_title) {
$records[] = Array ('OptionKey' => $option_key, 'OptionTitle' => $option_title);
}
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$xml = $minput_helper->prepareMInputXML($records, Array ('OptionKey', 'OptionTitle'));
$object->SetDBField('Options', $xml);
}
/**
* Returns custom field element types, that will use minput control
*
* @return Array
* @access protected
*/
protected function _getMultiElementTypes()
{
return Array ('select', 'multiselect', 'radio');
}
/**
* Saves minput content to ValueList field
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !in_array($object->GetDBField('ElementType'), $this->_getMultiElementTypes()) ) {
return ;
}
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$ret = $object->GetDBField('ElementType') == 'select' ? Array ('' => '=+') : Array ();
$records = $minput_helper->parseMInputXML($object->GetDBField('Options'));
if ( $object->GetDBField('SortValues') ) {
usort($records, Array (&$this, '_sortValues'));
ksort($records);
}
foreach ($records as $record) {
if ( substr($record['OptionKey'], 0, 3) == 'SQL' ) {
$ret[] = $record['OptionTitle'];
}
else {
$ret[] = $record['OptionKey'] . '=' . $record['OptionTitle'];
}
}
$object->SetDBField('ValueList', implode(VALUE_LIST_SEPARATOR, $ret));
}
function _sortValues($record_a, $record_b)
{
return strcasecmp($record_a['OptionTitle'], $record_b['OptionTitle']);
}
}
\ 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 15064)
+++ branches/5.2.x/core/units/users/users_event_handler.php (revision 15065)
@@ -1,1942 +1,1948 @@
<?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
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected 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);
}
/**
* Returns fields, that are not allowed to be changed from request
*
* @param Array $hash
* @return Array
* @access protected
*/
protected function getRequestProtectedFields($hash)
{
$fields = parent::getRequestProtectedFields($hash);
$fields = array_merge($fields, Array ('PrevEmails', 'ResourceId', 'IPAddress', 'IsBanned', 'PwResetConfirm', 'PwRequestTime', 'UserType', 'OldStyleLogin'));
if ( !$this->Application->isAdmin ) {
$fields = array_merge($fields, Array ('Status', 'EmailVerified', 'IsBanned'));
}
return $fields;
}
/**
* Builds item (loads if needed)
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
protected function OnItemBuild(kEvent &$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(kEvent &$event)
{
parent::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 . 'UserGroupRelations', '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(kEvent &$event)
{
if ( $event->Name == 'OnLogin' || $event->Name == 'OnLoginAjax' || $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' || $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('UserSessions');
// 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);
}
/**
* [SCHEDULED TASK] 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 */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$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');
}
if ( is_object($event->MasterEvent) && ($event->MasterEvent->Name == 'OnLoginAjax') ) {
// used to insert just logged-in user e-mail on "One Step Checkout" form in "Modern Store" theme
$user =& $user_helper->getUserObject();
$event->SetRedirectParam('user_email', $user->GetDBField('Email'));
}
}
/**
* Performs user login from ajax request
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnLoginAjax(&$event)
{
$ajax_form_helper =& $this->Application->recallObject('AjaxFormHelper');
/* @var $ajax_form_helper AjaxFormHelper */
$ajax_form_helper->transitEvent($event, 'OnLogin'); //, Array ('do_refresh' => 1));
}
/**
* [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)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$this->afterItemChanged($event);
$this->assignToPrimaryGroup($event);
}
/**
* Performs user registration
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$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, $this->getRequestProtectedFields($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', Array ('do_refresh' => 1));
}
/**
* 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 */
if ( $object->GetDBField('Status') == STATUS_ACTIVE ) {
$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() );
}
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$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 check state-to-country relations for subscribers
$cs_helper->CheckStateField($event, 'State', 'Country');
}
if ( $object->getFormName() != 'login' ) {
$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']);
if ( !$this->Application->isAdmin ) {
$object->SetDBField('FrontLanguage', $this->Application->GetVar('m_lang'));
}
}
/**
* 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 . 'UserGroups
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 . 'UserGroupRelations';
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 */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
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, $this->getRequestProtectedFields($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 */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
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 . 'UserGroupRelations');
}
$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 . 'UserGroupRelations
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 */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$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
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$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)
+ protected function OnBeforeItemUpdate(kEvent &$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());
}
if ( !$this->Application->isAdmin && in_array('Email', $changed_fields) && ($event->Special != 'email-restore') ) {
$object->SetDBField('EmailVerified', 0);
}
}
/**
* 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.'UserGroupRelations
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.'UserGroupRelations
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.'UserGroupRelations
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.'UserGroupRelations
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, $field_values) = each($item_info);
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$object->setID($id);
$object->IgnoreValidation = true;
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
}
/**
* 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
* @access public
*/
public function getPassedID(kEvent &$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, $this->getRequestProtectedFields($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, $this->getRequestProtectedFields($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 . 'UserPersistentSessionData 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
* @access protected
*/
protected function checkItemStatus(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$this->afterItemChanged($event);
$object =& $event->getObject();
/* @var $object UsersItem */
if ( !$this->Application->isAdmin && ($event->Special != 'email-restore') ) {
$this->sendEmailChangeEvent($event);
}
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)
+ protected function OnBeforeDeleteFromLive(kEvent &$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
+ * @return void
+ * @access protected
*/
- function OnAfterCopyToLive(&$event)
+ protected function OnAfterCopyToLive(kEvent &$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 . 'UserSessions
WHERE PortalUserId = ' . $user_id;
$session_ids = $this->Conn->GetCol($sql);
$this->Application->Session->DeleteSessions($session_ids);
}
}
/**
* Sends restore/validation email event on user email change
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function sendEmailChangeEvent(kEvent &$event)
{
$object =& $event->getObject();
/* @var $object UsersItem */
$new_email = $object->GetDBField('Email');
$prev_email = $object->GetOriginalField('Email');
if ( !$new_email || ($prev_email == $new_email) ) {
return;
}
$prev_emails = $object->GetDBField('PrevEmails');
$prev_emails = $prev_emails ? unserialize($prev_emails) : Array ();
$fields_hash = Array (
'PrevEmails' => serialize($prev_emails),
'EmailVerified' => 0,
);
$user_id = $object->GetID();
if ( $prev_email ) {
$hash = md5(TIMENOW + $user_id);
$prev_emails[$hash] = $prev_email;
$fields_hash['PrevEmails'] = serialize($prev_emails);
$send_params = Array (
'hash' => $hash,
'to_email' => $prev_email,
'to_name' => trim($object->GetDBField('FirstName') . ' ' . $object->GetDBField('LastName')),
);
$this->Application->EmailEventUser('USER.EMAIL.CHANGE.UNDO', null, $send_params);
}
if ( $new_email ) {
$this->Application->EmailEventUser('USER.EMAIL.CHANGE.VERIFY', $user_id);
}
// direct DB update, since USER.EMAIL.CHANGE.VERIFY puts verification code in user record, that we don't want to loose
$this->Conn->doUpdate($fields_hash, $object->TableName, 'PortalUserId = ' . $user_id);
}
/**
* OnAfterConfigRead for users
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$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');
$form_fields['Username']['min_len'] = $this->Application->ConfigValue('Min_UserName');
$form_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)
+ protected function OnBeforeClone(kEvent &$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 . 'Users
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)
+ protected function OnAfterItemLoad(kEvent &$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);
if ( !$this->Application->isAdmin ) {
$list = $this->Application->recallObject('lang.enabled', 'lang_List');
/* @var $list kDBList */
$list->GoFirst();
$languages = Array ();
while (!$list->EOL()) {
$languages[$list->GetID()] = $list->GetField('LocalName');
$list->GoNext();
}
$object->SetFieldOption('FrontLanguage', 'options', $languages);
}
}
/**
* 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)
+ protected function OnPreCreate(kEvent &$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(kEvent &$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/favorites/favorites_eh.php
===================================================================
--- branches/5.2.x/core/units/favorites/favorites_eh.php (revision 15064)
+++ branches/5.2.x/core/units/favorites/favorites_eh.php (revision 15065)
@@ -1,109 +1,111 @@
<?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 FavoritesEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnFavoriteToggle' => Array ('subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Adds/removes item from favorites
*
* @param kEvent $event
*/
function OnFavoriteToggle(&$event)
{
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$parent_object =& $this->Application->recallObject($parent_prefix);
/* @var $parent_object kDBItem */
if (!$parent_object->isLoaded() || !$this->Application->CheckPermission('FAVORITES', 0, $parent_object->GetDBField('ParentPath'))) {
$event->status = kEvent::erPERM_FAIL;
return ;
}
$user_id = $this->Application->RecallVar('user_id');
$sql = 'SELECT FavoriteId
FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
WHERE (PortalUserId = '.$user_id.') AND (ResourceId = '.$parent_object->GetDBField('ResourceId').')';
$favorite_id = $this->Conn->GetOne($sql);
$object =& $event->getObject(Array('skip_autoload' => true));
/* @var $object kDBItem */
if ($favorite_id) {
$object->Delete($favorite_id);
}
else {
$object->Create();
}
$event->SetRedirectParam('pass', 'm,'.$parent_prefix);
}
/**
* Prepares Favorite record fields
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
+ parent::OnBeforeItemCreate($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
$user_id = $this->Application->RecallVar('user_id');
$object->SetDBField('PortalUserId', $user_id);
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$parent_object =& $this->Application->recallObject($parent_prefix);
/* @var $parent_object kDBItem */
$object->SetDBField('ResourceId', $parent_object->GetDBField('ResourceId'));
$object->SetDBField('ItemTypeId', $this->Application->getUnitOption($parent_prefix, 'ItemType'));
}
/**
* [HOOK] Deletes favorite record to item, that is beeing deleted
*
* @param kEvent $event
*/
function OnDeleteFavoriteItem(&$event)
{
$main_object =& $event->MasterEvent->getObject();
$sql = 'DELETE FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
WHERE ResourceId = '.$main_object->GetDBField('ResourceId');
$this->Conn->Query($sql);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/files/file_eh.php
===================================================================
--- branches/5.2.x/core/units/files/file_eh.php (revision 15064)
+++ branches/5.2.x/core/units/files/file_eh.php (revision 15065)
@@ -1,111 +1,111 @@
<?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 FileEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnDownloadFile' => Array ('subitem' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Remembers user, who is created file record. Makes file primary if no other files are uploaded.
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
}
/**
* Resets primary file mark when more then one file is marked as primary
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->GetDBField('FileName') ) {
$object->SetDBField('FileName', basename($object->GetDBField('FilePath')));
}
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( !$this->Application->isAdminUser ) {
$object->addFilter('active_filter', '%1$s.Status = ' . STATUS_ACTIVE);
}
}
/**
* Returns file contents associated with item
*
* @param kEvent $event
*/
function OnDownloadFile(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$filename = $object->GetField('FilePath', 'full_path');
$file_helper->DownloadFile($filename);
$event->status = kEvent::erSTOP;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/selectors/selectors_event_handler.php
===================================================================
--- branches/5.2.x/core/units/selectors/selectors_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/selectors/selectors_event_handler.php (revision 15065)
@@ -1,449 +1,453 @@
<?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 SelectorsEventHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnResetToBase' => Array('subitem' => 'add|edit'),
'OnMassResetToBase' => Array('subitem' => 'add|edit'),
'OnOpenStyleEditor' => Array('subitem' => 'add|edit'),
'OnSaveStyle' => Array('subitem' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* 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)
+ protected function OnBeforeClone(kEvent &$event)
{
parent::OnBeforeClone($event);
$event->Init($event->Prefix, '-item');
$object =& $event->getObject();
/* @var $object kDBItem */
$title_field = 'SelectorName';
$new_name = $object->GetDBField($title_field);
$original_checked = false;
$foreign_key = $event->getEventParam('foreign_key'); // in case if whole stylesheet is cloned
if ( $foreign_key === false ) {
$foreign_key = $object->GetDBField('StylesheetId');
} // in case if selector is copied ifself
do {
if ( preg_match('/(.*)-([\d]+)/', $new_name, $regs) ) {
$new_name = $regs[1] . '-' . ($regs[2] + 1);
}
elseif ( $original_checked ) {
$new_name = $new_name . '-1';
}
// if we are cloning in temp table this will look for names in temp table,
// since object' TableName contains correct TableName (for temp also!)
// if we are cloning live - look in live
$query = ' SELECT ' . $title_field . '
FROM ' . $object->TableName . '
WHERE ' . $title_field . ' = ' . $this->Conn->qstr($new_name) . ' AND StylesheetId = ' . $foreign_key;
$res = $this->Conn->GetOne($query);
/*// if not found in live table, check in temp table if applicable
if ($res === false && $object->Special == 'temp') {
$query = 'SELECT '.$name_field.' FROM '.$this->GetTempName($master['TableName']).'
WHERE '.$name_field.' = '.$this->Conn->qstr($new_name);
$res = $this->Conn->GetOne($query);
}*/
$original_checked = true;
} while ( $res !== false );
$object->SetDBField($title_field, $new_name);
}
/**
* Show base styles or block styles
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
switch ($event->Special) {
case 'base':
$object->addFilter('type_filter', '%1$s.Type = 1');
break;
case 'block':
$object->addFilter('type_filter', '%1$s.Type = 2');
break;
}
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->SerializeSelectorData($event);
}
/**
* Occurs before creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->SerializeSelectorData($event);
}
/**
- * Enter description here...
+ * Occurs after updating item
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
+ parent::OnAfterItemUpdate($event);
+
$this->UnserializeSelectorData($event);
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$this->UnserializeSelectorData($event);
}
/**
* Returns special of main item for linking with sub-item
*
* @param kEvent $event
* @return string
* @access protected
*/
protected function getMainSpecial(kEvent &$event)
{
return '';
}
/**
* Save css-style name & description before opening css editor
*
* @param kEvent $event
*/
function OnOpenStyleEditor(&$event)
{
$this->SaveChanges($event);
$event->redirect = false;
}
/**
* Saves Changes to Item
*
* @param kEvent $event
*/
function SaveChanges(&$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 ) {
$parent_id = getArrayValue($field_values, 'ParentId');
if ( $parent_id ) {
$object->Load($parent_id);
}
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$object->Create();
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$object->Load($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$object->Update();
}
}
}
/**
* Save style changes from style editor
*
* @param kEvent $event
*/
function OnSaveStyle(&$event)
{
$this->SaveChanges($event);
$object =& $event->getObject();
$this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetId() );
$this->finalizePopup($event);
}
/**
* Extract styles
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$selector_data = $object->GetDBField('SelectorData');
if ( $selector_data ) {
$selector_data = unserialize($selector_data);
$object->SetDBField('SelectorData', $selector_data);
}
else {
$selector_data = Array ();
}
$this->AddParentProperties($event, $selector_data);
}
/**
* Serialize item before saving to db
*
* @param kEvent $event
*/
function SerializeSelectorData(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$selector_data = $object->GetDBField('SelectorData');
if ( !$selector_data ) {
$selector_data = Array ();
}
$selector_data = $this->RemoveParentProperties($event, $selector_data);
if ( !kUtil::IsSerialized($selector_data) ) {
$selector_data = serialize($selector_data);
}
$object->SetDBField('SelectorData', $selector_data);
}
/**
* Unserialize data back when update was made
*
* @param kEvent $event
*/
function UnserializeSelectorData(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$selector_data = $object->GetDBField('SelectorData');
if ( !$selector_data ) {
$selector_data = Array ();
}
if ( kUtil::IsSerialized($selector_data) ) {
$selector_data = unserialize($selector_data);
}
$selector_data = $this->AddParentProperties($event, $selector_data);
$object->SetDBField('SelectorData', $selector_data);
}
/**
* Populate options based on temporary table :)
*
* @param kEvent $event
*/
function OnPrepareBaseStyles(&$event)
{
$object =& $event->getObject();
$parent_info = $object->getLinkedInfo();
$title_field = $this->Application->getUnitOption($event->Prefix,'TitleField');
$sql = 'SELECT '.$title_field.', '.$object->IDField.' FROM '.$object->TableName.' WHERE Type = 1 AND StylesheetId = '.$parent_info['ParentId'].' ORDER BY '.$title_field;
$options = $this->Conn->GetCol($sql,$object->IDField);
$object->SetFieldOption('ParentId', 'options', $options);
}
/**
* Remove properties of parent style that match by value from style
*
* @param kEvent $event
* @param Array $selector_data
* @return Array
*/
function RemoveParentProperties(&$event, $selector_data)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$parent_id = $object->GetDBField('ParentId');
if ( $parent_id ) {
$sql = 'SELECT SelectorData
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $parent_id;
$base_selector_data = $this->Conn->GetOne($sql);
if ( kUtil::IsSerialized($base_selector_data) ) {
$base_selector_data = unserialize($base_selector_data);
}
foreach ($selector_data as $prop_name => $prop_value) {
if ( !$prop_value || getArrayValue($base_selector_data, $prop_name) == $prop_value ) {
unset($selector_data[$prop_name]);
}
}
}
else {
foreach ($selector_data as $prop_name => $prop_value) {
if ( !$prop_value ) {
unset($selector_data[$prop_name]);
}
}
}
$object->SetDBField('SelectorData', $selector_data);
return $selector_data;
}
/**
* Add back properties from parent style, that match this style property values
*
* @param kEvent $event
* @param Array $selector_data
* @return Array
*/
function AddParentProperties(&$event, $selector_data)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$parent_id = $object->GetDBField('ParentId');
if ( $parent_id ) {
$sql = 'SELECT SelectorData
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $parent_id;
$base_selector_data = $this->Conn->GetOne($sql);
if ( kUtil::IsSerialized($base_selector_data) ) {
$base_selector_data = unserialize($base_selector_data);
}
$selector_data = kUtil::array_merge_recursive($base_selector_data, $selector_data);
$object->SetDBField('SelectorData', $selector_data);
return $selector_data;
}
return Array ();
}
/**
* Reset Style definition to base style -> no customizations
*
* @param kEvent $event
*/
function OnResetToBase(&$event)
{
$object =& $event->getObject();
/* @var $object SelectorsItem */
$field_values = $this->getSubmittedFields($event);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$object->ResetStyle();
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
}
/**
* Resets selected styles properties to values of their base classes
*
* @param kEvent $event
*/
function OnMassResetToBase(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object SelectorsItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ( $items_info ) {
foreach ($items_info as $id => $field_values) {
$object->Load($id);
$object->ResetStyle();
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/fck/fck_eh.php
===================================================================
--- branches/5.2.x/core/units/fck/fck_eh.php (revision 15064)
+++ branches/5.2.x/core/units/fck/fck_eh.php (revision 15065)
@@ -1,253 +1,253 @@
<?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 FckEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnGetsEditorStyles' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $this->Application->isAdminUser || $event->Name == 'OnGetsEditorStyles' ) {
// this limits all event execution only to logged-in users in admin
return true;
}
return parent::CheckPermission($event);
}
function CreateXmlHeader()
{
ob_end_clean() ;
// Prevent the browser from caching the result.
// Date in the past
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT') ;
// always modified
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT') ;
// HTTP/1.1
header('Cache-Control: no-store, no-cache, must-revalidate') ;
header('Cache-Control: post-check=0, pre-check=0', false) ;
// HTTP/1.0
header('Pragma: no-cache') ;
// Set the response format.
header( 'Content-Type: text/xml; charset=utf-8' ) ;
// Create the XML document header.
}
function OnLoadCmsTree(&$event)
{
$event->status = kEvent::erSTOP;
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$pages = $category_helper->getStructureTreeAsOptions();
$sql = 'SELECT NamedParentPath, CategoryId
FROM ' . TABLE_PREFIX . 'Categories
WHERE CategoryId IN (' . implode(',', array_keys($pages)) . ')';
$templates = $this->Conn->GetCol($sql, 'CategoryId');
$templates[$this->Application->getBaseCategory()] .= '/Index'; // "Content" category will act as "Home Page"
$res = '<?xml version="1.0" encoding="utf-8" ?>' . "\n";
$res .= '<CmsPages>' . "\n";
foreach ($pages as $id => $title) {
$template = $templates[$id];
$page_path = preg_replace('/^Content\//i', '', strtolower($template).'.html');
$title = $title . ' (' . $page_path . ')';
$real_url = $this->Application->HREF($template, '_FRONT_END_', array('pass' => 'm'), 'index.php');
$res .= '<CmsPage real_url="' . $real_url . '" path="@@' . $id . '@@" title="' . htmlspecialchars($title, ENT_QUOTES) . '" st_id="' . $id . '" serverpath="" />' . "\n";
}
$res.= "</CmsPages>";
$this->CreateXmlHeader();
echo $res;
}
function OnRenameFile(&$event)
{
$event->status = kEvent::erSTOP;
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$old_name = $this->Application->GetVar('old_name');
$new_name = $this->Application->GetVar('new_name');
$folder = $this->Application->GetVar('folder');
$sServerDir = WRITEABLE . '/user_files/' . $folder . '/';
if (!file_exists($sServerDir.$old_name) || !is_file($sServerDir.$old_name)) {
echo 204;
return;
}
$fck_helper =& $this->Application->recallObject('FCKHelper');
/* @var $fck_helper fckFCKHelper*/
if ( !$fck_helper->IsAllowedExtension($folder, $new_name) ) {
echo 203;
return;
}
if ( !rename($sServerDir . $old_name, $sServerDir . $new_name) ) {
// echo $sServerDir.$old_name.' -> '.$sServerDir.$new_name;
echo 205;
return;
}
echo '0';
}
function OnDeleteFiles(&$event)
{
$event->status = kEvent::erSTOP;
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$files = trim($this->Application->GetVar('files'),'|');
// echo $files;
$a_files = explode('|', $files);
$folder = $this->Application->GetVar('folder');
$sServerDir = WRITEABLE . '/user_files/' . $folder . '/';
foreach ($a_files AS $file) {
@unlink($sServerDir.$file);
}
// print_r($a_files);
}
function OnGetFoldersFilesList(&$event)
{
$this->CreateXmlHeader();
$fck_helper =& $this->Application->recallObject('FCKHelper');
/* @var $fck_helper fckFCKHelper */
$ret = '<?xml version="1.0" encoding="utf-8" ?>'."\n" ;
$ret .= "<content>"."\n";
$ret .= $fck_helper->PrintFolders();
$ret .= $fck_helper->PrintFiles();
$ret .= "</content>"."\n";
echo $ret;
exit;
}
function OnCreateFolder(&$event)
{
$event->status = kEvent::erSTOP;
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$new_folder = $this->Application->GetVar('new_folder');
$current_folder = $this->Application->GetVar('current_folder');
$folderPath = WRITEABLE . '/user_files' . '/' . $current_folder . "/" . $new_folder;
if ( file_exists( $folderPath ) && is_dir($folderPath)) {
echo "101";
}
if ( !file_exists( $folderPath ) )
{
// Turn off all error reporting.
error_reporting( 0 ) ;
// Enable error tracking to catch the error.
ini_set( 'track_errors', '1' ) ;
// To create the folder with 0777 permissions, we need to set umask to zero.
$oldumask = umask(0) ;
mkdir( $folderPath, 0777 ) ;
umask( $oldumask ) ;
$sErrorMsg = $php_errormsg ;
// Restore the configurations.
ini_restore( 'track_errors' ) ;
ini_restore( 'error_reporting' ) ;
if ($sErrorMsg)
echo $sErrorMsg ;
else
echo '0';
}
}
/**
* Uploads a file from FCK file browser
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnUploadFile(&$event)
+ protected function OnUploadFile(kEvent &$event)
{
$event->status = kEvent::erSTOP;
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
return;
}
$fck_helper =& $this->Application->recallObject('FCKHelper');
/* @var $fck_helper fckFCKHelper*/
$fck_helper->UploadFile();
}
/**
* Returns compressed CSS file
*
* @param kEvent $event
*/
function OnGetsEditorStyles(&$event)
{
$minify_helper =& $this->Application->recallObject('MinifyHelper');
/* @var $minify_helper MinifyHelper */
$this->Application->InitParser();
$styles_css = $minify_helper->CompressScriptTag( Array ('files' => 'inc/style.css') );
$event->redirect = 'external:' . $styles_css;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/logs/session_logs/session_log_eh.php
===================================================================
--- branches/5.2.x/core/units/logs/session_logs/session_log_eh.php (revision 15064)
+++ branches/5.2.x/core/units/logs/session_logs/session_log_eh.php (revision 15065)
@@ -1,128 +1,130 @@
<?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 SessionLogEventHandler extends kDBEventHandler {
/**
* Opens log for new session
*
* @param kEvent $event
*/
function OnStartSession(&$event)
{
if (!$this->Application->ConfigValue('UseChangeLog')) {
// don't use session log when change log is disabled
return ;
}
$object =& $this->Application->recallObject($event->Prefix, null, Array ('skip_autoload' => 1));
/* @var $object kDBItem */
$fields_hash = Array (
'SessionStart' => adodb_mktime(),
'IP' => $_SERVER['REMOTE_ADDR'],
'PortalUserId' => $this->Application->RecallVar('user_id'),
'SessionId' => $this->Application->GetSID(),
'Status' => SESSION_LOG_ACTIVE,
);
$object->SetDBFieldsFromHash($fields_hash);
$object->UpdateFormattersSubFields();
if ($object->Create()) {
$this->Application->StoreVar('_SessionLogId_', $object->GetID());
}
}
/**
* Closes log for current session
*
* @param kEvent $event
*/
function OnEndSession(&$event)
{
$object =& $this->Application->recallObject($event->Prefix, null, Array ('skip_autoload' => 1));
/* @var $object kDBItem */
$object->Load($this->Application->RecallVar('_SessionLogId_'));
if (!$object->isLoaded()) {
return ;
}
$fields_hash = Array (
'SessionEnd' => adodb_mktime(),
'Status' => SESSION_LOG_LOGGED_OUT,
);
$object->SetDBFieldsFromHash($fields_hash);
$object->UpdateFormattersSubFields();
$object->Update();
}
/**
* Apply custom processing to item
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
- if ($event->Name == 'OnMassDelete' && $type == 'before') {
+ if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
- if ($ids) {
+ if ( $ids ) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $ids) . ') AND Status <> ' . SESSION_LOG_ACTIVE;
$allowed_ids = $this->Conn->GetCol($sql);
$event->setEventParam('ids', $allowed_ids);
}
}
}
/**
* Delete changes, related to deleted session
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'SELECT ' . $this->Application->getUnitOption('change-log', 'IDField') . '
FROM ' . $this->Application->getUnitOption('change-log', 'TableName') . '
WHERE SessionLogId = ' . $object->GetID();
$related_ids = $this->Conn->GetCol($sql);
- if ($related_ids) {
+ if ( $related_ids ) {
$temp_handler =& $this->Application->recallObject('change-log_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems('change-log', '', $related_ids);
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/logs/change_logs/change_log_eh.php
===================================================================
--- branches/5.2.x/core/units/logs/change_logs/change_log_eh.php (revision 15064)
+++ branches/5.2.x/core/units/logs/change_logs/change_log_eh.php (revision 15065)
@@ -1,64 +1,66 @@
<?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 ChangeLogEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnEnableLog' => Array ('self' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Updates affected record count in session, when change log record is deleted
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'UPDATE ' . $this->Application->getUnitOption('session-log', 'TableName') . '
SET AffectedItems = AffectedItems - 1
WHERE SessionLogId = ' . $object->GetDBField('SessionLogId');
$this->Conn->Query($sql);
}
/**
* Changes configuration value to enable log writing
*
* @param kEvent $event
*/
function OnEnableLog(&$event)
{
$this->Application->SetConfigValue('UseChangeLog', 1);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/scheduled_tasks/scheduled_task_eh.php
===================================================================
--- branches/5.2.x/core/units/scheduled_tasks/scheduled_task_eh.php (revision 15064)
+++ branches/5.2.x/core/units/scheduled_tasks/scheduled_task_eh.php (revision 15065)
@@ -1,179 +1,178 @@
<?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 ScheduledTaskEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnMassCancel' => Array ('self' => 'add|edit'),
'OnRun' => Array ('self' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* [HOOK] Refreshes scheduled task list in database based on cached data from unit configs
*
* @param kEvent $event
*/
function OnRefresh(&$event)
{
$scheduled_tasks_from_cache = $this->Application->EventManager->getScheduledTasks(true);
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$processed_ids = Array ();
$scheduled_tasks_from_db = $this->Conn->Query($object->GetSelectSQL(), 'Name');
foreach ($scheduled_tasks_from_cache as $scheduled_task_name => $scheduled_task_params) {
if ( !isset($scheduled_tasks_from_db[$scheduled_task_name]) ) {
$fields_hash = Array (
'Event' => $scheduled_task_params['Event'],
'Name' => $scheduled_task_name,
'Type' => ScheduledTask::TYPE_SYSTEM,
'Status' => isset($scheduled_task_params['Status']) ? $scheduled_task_params['Status'] : STATUS_ACTIVE,
'RunInterval' => $scheduled_task_params['RunInterval'],
);
$object->Clear();
$object->SetDBFieldsFromHash($fields_hash);
$object->Create();
}
else {
$object->LoadFromHash( $scheduled_tasks_from_db[$scheduled_task_name] );
}
$processed_ids[] = $object->GetID();
}
// delete all non-processed scheduled tasks (ones, that were deleted from unit configs)
$sql = 'SELECT ' . $object->IDField . '
FROM ' . $object->TableName . '
WHERE (Type = ' . ScheduledTask::TYPE_SYSTEM . ') AND (' . $object->IDField . ' NOT IN (' . implode(',', $processed_ids) . '))';
$delete_ids = $this->Conn->GetCol($sql);
if ($delete_ids) {
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems($event->Prefix, $event->Special, $delete_ids);
}
$this->Application->removeObject($event->getPrefixSpecial());
}
/**
* Don't allow to delete other user's messages
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
- if ($event->Name == 'OnMassDelete' && $type == 'before') {
- if ($this->Application->isDebugMode()) {
+ if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
+ if ( $this->Application->isDebugMode() ) {
// allow to delete system scheduled tasks in debug mode
- return ;
+ return;
}
$ids = $event->getEventParam('ids');
- if ($ids) {
+
+ if ( $ids ) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' IN (' . implode(',', $ids) . ') AND Type <> ' . ScheduledTask::TYPE_SYSTEM;
- $allowed_ids = $this->Conn->GetCol($sql);
-
- $event->setEventParam('ids', $allowed_ids);
+ $event->setEventParam('ids', $this->Conn->GetCol($sql));
}
}
}
/**
* Cancels scheduled tasks, that are currently running
*
* @param kEvent $event
*/
function OnMassCancel(&$event)
{
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
foreach ($ids as $id) {
$object->Load($id);
if ($object->GetDBField('LastRunStatus') == ScheduledTask::LAST_RUN_RUNNING) {
// only changes status, doesn't affect currency running scheduled tasks
$object->SetDBField('LastRunStatus', ScheduledTask::LAST_RUN_FAILED);
$object->Update();
}
}
}
$this->clearSelectedIDs($event);
}
/**
* Runs selected scheduled tasks
*
* @param kEvent $event
*/
function OnRun(&$event)
{
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$where_clause = Array (
$object->TableName . '.' . $object->IDField . ' IN (' . implode(',', $ids) . ')',
$object->TableName . '.Status = ' . STATUS_ACTIVE,
$object->TableName . '.LastRunStatus <> ' . ScheduledTask::LAST_RUN_RUNNING,
);
$sql = $object->GetSelectSQL() . '
WHERE (' . implode(') AND (', $where_clause) . ')';
$scheduled_tasks = $this->Conn->Query($sql);
foreach ($scheduled_tasks as $scheduled_task_data) {
$scheduled_task_data['EventName'] = $scheduled_task_data['Event'];
$this->Application->EventManager->runScheduledTask($scheduled_task_data);
}
}
$this->clearSelectedIDs($event);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/promo_block_groups/promo_block_group_eh.php
===================================================================
--- branches/5.2.x/core/units/promo_block_groups/promo_block_group_eh.php (revision 15064)
+++ branches/5.2.x/core/units/promo_block_groups/promo_block_group_eh.php (revision 15065)
@@ -1,131 +1,134 @@
<?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 PromoBlockGroupEventHandler extends kDBEventHandler {
/**
* Occurs before creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->beforeItemChange($event);
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->beforeItemChange($event);
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access private
*/
private function beforeItemChange(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->setRequired('TransitionEffectCustom', $object->GetDBField('TransitionEffect') == '-1');
}
/**
- * Occurs before deleting item
+ * Occurs before deleting item, id of item being
+ * deleted is stored as 'id' event param
*
* @param kEvent $event
* @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
parent::OnBeforeItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'SELECT BlockId
FROM ' . TABLE_PREFIX . 'PromoBlocks
WHERE PromoBlockGroupId = ' . $object->GetID();
$block_id = $this->Conn->GetOne($sql);
if ( $block_id ) {
$event->MasterEvent->SetRedirectParam('grid_error', 'la_error_PromoGroupNotEmpty');
$event->status = kEvent::erFAIL;
}
}
/**
* Deleting empty promo block group disconnects it from associated sections
*
* @param kEvent $event
* @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$sql = 'UPDATE ' . TABLE_PREFIX . 'Categories
SET PromoBlockGroupId = 0
WHERE PromoBlockGroupId = ' . $event->getEventParam('id');
$this->Conn->Query($sql);
}
/**
* Set tree update flag
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
if ( $event->status == kEvent::erSUCCESS ) {
$event->SetRedirectParam('refresh_tree', 1);
}
}
/**
* Set tree update flag
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnMassDelete(&$event)
+ protected function OnMassDelete(kEvent &$event)
{
parent::OnMassDelete($event);
if ( $event->status == kEvent::erSUCCESS ) {
$event->SetRedirectParam('refresh_tree', 1);
}
}
}
Index: branches/5.2.x/core/units/images/image_event_handler.php
===================================================================
--- branches/5.2.x/core/units/images/image_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/images/image_event_handler.php (revision 15065)
@@ -1,496 +1,496 @@
<?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 ImageEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnCleanImages' => Array ('subitem' => true),
'OnCleanResizedImages' => Array ('subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Define alternative event processing method names
*
* @return void
* @see kEventHandler::$eventMethods
* @access protected
*/
protected function mapEvents()
{
parent::mapEvents(); // ensure auto-adding of approve/decline and so on events
$image_events = Array (
'OnAfterCopyToTemp'=>'ImageAction',
'OnBeforeDeleteFromLive'=>'ImageAction',
'OnBeforeCopyToLive'=>'ImageAction',
'OnBeforeItemDelete'=>'ImageAction',
'OnAfterClone'=>'ImageAction',
);
$this->eventMethods = array_merge($this->eventMethods, $image_events);
}
/**
* Returns special of main item for linking with sub-item
*
* @param kEvent $event
* @return string
* @access protected
*/
protected function getMainSpecial(kEvent &$event)
{
if ( $event->Special == 'list' && !$this->Application->isAdmin ) {
// ListImages aggregated tag uses this special
return '';
}
return parent::getMainSpecial($event);
}
/**
* Don't allow to delete primary category item image, when there are no more images
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
$parent_info = $object->getLinkedInfo($event->Special);
$sql = 'SELECT ImageId
FROM ' . $object->TableName . '
WHERE DefaultImg = 1 AND ' . $parent_info['ForeignKey'] . ' = ' . $parent_info['ParentId'];
$primary_file_id = $this->Conn->GetOne($sql);
if ( $primary_file_id ) {
$file_id_index = array_search($primary_file_id, $ids);
if ( $file_id_index ) {
// allow deleting of primary product file, when there is another file to make primary
$sql = 'SELECT COUNT(*)
FROM ' . $object->TableName . '
WHERE DefaultImg = 0 AND ' . $parent_info['ForeignKey'] . ' = ' . $parent_info['ParentId'];
$non_primary_file_count = $this->Conn->GetOne($sql);
if ( $non_primary_file_count ) {
unset($ids[$file_id_index]);
}
}
}
$event->setEventParam('ids', $ids);
}
- switch ( $type ) {
+ switch ($type) {
case 'before' :
// empty unused fields
$object->SetDBField($object->GetDBField('LocalImage') ? 'Url' : 'LocalPath', '');
$object->SetDBField($object->GetDBField('LocalThumb') ? 'ThumbUrl' : 'ThumbPath', '');
if ( $object->GetDBField('SameImages') ) {
$object->SetDBField('LocalImage', 1);
$object->SetDBField('LocalPath', '');
$object->SetDBField('Url', '');
}
break;
case 'after':
// make sure, that there is only one primary image for the item
if ( $object->GetDBField('DefaultImg') ) {
$sql = 'UPDATE ' . $object->TableName . '
SET DefaultImg = 0
WHERE ResourceId = ' . $object->GetDBField('ResourceId') . ' AND ImageId <> ' . $object->GetID();
$this->Conn->Query($sql);
}
break;
}
}
/**
* Performs temp-table related action on current image record
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function ImageAction(&$event)
{
$id = $event->getEventParam('id');
$object =& $this->Application->recallObject($event->Prefix . '.-item', $event->Prefix, Array ('skip_autoload' => true));
/* @var $object kDBItem */
if ( in_array($event->Name, Array ('OnBeforeDeleteFromLive', 'OnAfterClone')) ) {
$object->SwitchToLive();
}
elseif ( $event->Name == 'OnBeforeItemDelete' ) {
// keep current table
}
else {
$object->SwitchToTemp();
}
$object->Load($id);
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$fields = Array ('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb');
foreach ($fields as $a_field => $mode_field) {
$file = $object->GetDBField($a_field);
if ( !$file ) {
continue;
}
$source_file = FULL_PATH . $file;
switch ($event->Name) {
// Copy image files to pending dir and update corresponding fields in temp record
// Checking for existing files and renaming if necessary - two users may upload same pending files at the same time!
case 'OnAfterCopyToTemp':
$file = preg_replace('/^' . preg_quote(IMAGES_PATH, '/') . '/', IMAGES_PENDING_PATH, $file, 1);
$new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
$dst_file = FULL_PATH . $new_file;
copy($source_file, $dst_file);
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
// Copy image files to live dir (checking if file exists and renaming if necessary)
// and update corresponding fields in temp record (which gets copied to live automatically)
case 'OnBeforeCopyToLive':
if ( $object->GetDBField($mode_field) ) {
// if image is local -> rename file if it exists in live folder
$file = preg_replace('/^' . preg_quote(IMAGES_PENDING_PATH, '/') . '/', IMAGES_PATH, $file, 1);
$new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
$dst_file = FULL_PATH . $new_file;
rename($source_file, $dst_file);
}
else {
// if image is remote url - remove local file (if any), update local file field with empty value
if ( file_exists($source_file) ) {
@unlink($source_file);
}
$new_file = '';
}
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
case 'OnBeforeDeleteFromLive': // Delete image files from live folder before copying over from temp
case 'OnBeforeItemDelete': // Delete image files when deleting Image object
@unlink(FULL_PATH . $file);
break;
case 'OnAfterClone':
// Copy files when cloning objects, renaming it on the fly
$new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
$dst_file = FULL_PATH . $new_file;
copy($source_file, $dst_file);
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
}
}
if ( in_array($event->Name, Array ('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) {
$object->Update(null, true);
}
}
/**
* Sets primary image of user/category/category item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPrimary(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('DefaultImg', 1);
$object->Update();
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->processImageStatus($event);
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$this->processImageStatus($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->Update();
}
/**
* Occurs before item changed
*
* @param kEvent $event
*/
function processImageStatus(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $object->GetDBField('ResourceId');
$sql = 'SELECT ImageId
FROM ' . $object->TableName . '
WHERE ResourceId = ' . $id . ' AND DefaultImg = 1';
$primary_image_id = $this->Conn->GetOne($sql);
if ( !$primary_image_id ) {
$object->SetDBField('DefaultImg', 1);
}
if ( $object->GetDBField('DefaultImg') && $object->Validate() ) {
$sql = 'UPDATE ' . $object->TableName . '
SET DefaultImg = 0
WHERE ResourceId = ' . $id . ' AND ImageId <> ' . $object->GetDBField('ImageId');
$this->Conn->Query($sql);
$object->SetDBField('Enabled', 1);
}
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( !$this->Application->isAdminUser ) {
$object->addFilter('active', '%1$s.Enabled = 1');
}
$product_id = $event->getEventParam('product_id');
if ( $product_id ) {
$object->removeFilter('parent_filter');
$sql = 'SELECT ResourceId
FROM ' . $this->Application->getUnitOption('p', 'TableName') . '
WHERE ProductId = ' . $product_id;
$resource_id = (int)$this->Conn->GetOne($sql);
$object->addFilter('product_images', '%1$s.ResourceId = ' . $resource_id);
}
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$types = $event->getEventParam('types');
$except_types = $event->getEventParam('except');
$type_clauses = $this->getTypeClauses($event);
$search_helper->SetComplexFilter($event, $type_clauses, $types, $except_types);
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function getTypeClauses(&$event)
{
$type_clauses = Array ();
$type_clauses['additional']['include'] = '%1$s.DefaultImg != 1';
$type_clauses['additional']['except'] = '%1$s.DefaultImg = 1';
$type_clauses['additional']['having_filter'] = false;
return $type_clauses;
}
/**
* [SCHEDULED TASK] Remove unused images from "/system/images" and "/system/images/pending" folders
*
* @param kEvent $event
*/
function OnCleanImages(&$event)
{
// 1. get images, that are currently in use
$active_images = $this->_getActiveImages( $this->Application->getUnitOption('img', 'TableName') );
$active_images[] = 'noimage.gif';
// 2. get images on disk
$this->_deleteUnusedImages(FULL_PATH . IMAGES_PATH, $active_images);
// 3. get images in use from "images/pending" folder
$active_images = $this->_getPendingImages();
// 4. get image on disk
$this->_deleteUnusedImages(FULL_PATH . IMAGES_PENDING_PATH, $active_images);
}
/**
* Gets image filenames (no path) from given table
*
* @param string $image_table
* @return Array
*/
function _getActiveImages($image_table)
{
$sql = 'SELECT LocalPath, ThumbPath
FROM ' . $image_table . '
WHERE COALESCE(LocalPath, "") <> "" OR COALESCE(ThumbPath) <> ""';
$images = $this->Conn->Query($sql);
$active_images = Array ();
foreach ($images as $image) {
if ($image['LocalPath']) {
$active_images[] = basename($image['LocalPath']);
}
if ($image['ThumbPath']) {
$active_images[] = basename($image['ThumbPath']);
}
}
return $active_images;
}
/**
* Gets active images, that are currently beeing edited inside temporary tables
*
* @return Array
*/
function _getPendingImages()
{
$tables = $this->Conn->GetCol('SHOW TABLES');
$mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_' . TABLE_PREFIX . 'CatalogImages/';
$active_images = Array ();
foreach ($tables as $table) {
if (!preg_match($mask_edit_table, $table)) {
continue;
}
$active_images = array_unique( array_merge($active_images, $this->_getActiveImages($table)) );
}
return $active_images;
}
/**
* Deletes all files in given path, except of given $active_images
*
* @param string $path
* @param Array $active_images
*/
function _deleteUnusedImages($path, &$active_images)
{
$images = glob($path . '*.*');
if ($images) {
$images = array_map('basename', $images);
// delete images, that are on disk, but are not mentioned in CatalogImages table
$delete_images = array_diff($images, $active_images);
foreach ($delete_images as $delete_image) {
unlink($path . $delete_image);
}
}
}
/**
* [SCHEDULED TASK] Remove all images from "/system/images/resized" and "/system/images/pending/resized" folders
*
* @param kEvent $event
*/
function OnCleanResizedImages(&$event)
{
$images = glob(FULL_PATH . IMAGES_PATH . 'resized/*.*');
if ($images) {
foreach ($images as $image) {
unlink($image);
}
}
$images = glob(FULL_PATH . IMAGES_PENDING_PATH . 'resized/*.*');
if ($images) {
foreach ($images as $image) {
unlink($image);
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/configuration/configuration_event_handler.php
===================================================================
--- branches/5.2.x/core/units/configuration/configuration_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/configuration/configuration_event_handler.php (revision 15065)
@@ -1,372 +1,376 @@
<?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 ConfigurationEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnGenerateMaintenancePage' => Array ('self' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Changes permission section to one from REQUEST, not from config
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
$event->setEventParam('PermSection', $this->Application->GetVar('section'));
return parent::CheckPermission($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
$module = $this->Application->GetVar('module');
$section = $this->Application->GetVar('section');
$object->addFilter('module_filter', '%1$s.ModuleOwner = ' . $this->Conn->qstr($module));
$object->addFilter('section_filter', '%1$s.Section = ' . $this->Conn->qstr($section));
if ( !$this->Application->ConfigValue('AllowAdminConsoleInterfaceChange') ) {
$object->addFilter('interface_change_filter', '%1$s.VariableName <> "AdminConsoleInterface"');
}
if ( defined('IS_INSTALL') && IS_INSTALL ) {
$object->addFilter('install_filter', '%1$s.Install = 1');
}
$object->addFilter('visible_filter', '%1$s.Heading <> ""');
}
/**
* Performs validation of configuration variable value
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
static $default_field_options = null;
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// ability to validate each configuration variable separately
if ( !isset($default_field_options) ) {
$default_field_options = $object->GetFieldOptions('VariableValue');
}
$new_field_options = $default_field_options;
$validation = $object->GetDBField('Validation');
if ( $validation ) {
$new_field_options = array_merge($new_field_options, unserialize($validation));
}
$object->SetFieldOptions('VariableValue', $new_field_options);
// if password field is empty, then don't update
if ( $object->GetDBField('ElementType') == 'password' ) {
if ( trim($object->GetDBField('VariableValue')) == '' ) {
$field_options = $object->GetFieldOptions('VariableValue');
$field_options['skip_empty'] = 1;
$object->SetFieldOptions('VariableValue', $field_options);
}
else {
$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
/* @var $password_formatter kPasswordFormatter */
$object->SetDBField('VariableValue', $password_formatter->EncryptPassword($object->GetDBField('VariableValue'), 'b38'));
}
}
$field_name = $object->GetDBField('VariableName');
$field_values = $this->Application->GetVar($event->getPrefixSpecial(true));
$state_country_hash = Array ('Comm_State' => 'Comm_Country', 'Comm_Shipping_State' => 'Comm_Shipping_Country');
if ( array_key_exists($field_name, $state_country_hash) ) {
// if this is state field
$sql = 'SELECT VariableId
FROM ' . $this->Application->getUnitOption('conf', 'TableName') . '
WHERE VariableName = "' . $state_country_hash[$field_name] . '"';
$country_variable_id = $this->Conn->GetOne($sql);
$check_state = $object->GetDBField('VariableValue');
$check_country = $field_values[$country_variable_id]['VariableValue'];
if ( !$check_country || !$check_state ) {
return;
}
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
/* @var $cs_helper kCountryStatesHelper */
$state_iso = $cs_helper->getStateIso($check_state, $check_country);
if ( $state_iso !== false ) {
$object->SetDBField('VariableValue', $state_iso);
}
else {
// selected state doesn't belong to selected country
$object->SetError('VariableValue', 'invalid_state', 'la_InvalidState');
}
}
$variable_name = $object->GetDBField('VariableName');
$new_value = $object->GetDBField('VariableValue');
if ( $variable_name == 'AdminConsoleInterface' ) {
$can_change = $this->Application->ConfigValue('AllowAdminConsoleInterfaceChange');
if ( ($new_value != $object->GetOriginalField('VariableValue')) && !$can_change ) {
$object->SetError('VariableValue', 'not_allowed', 'la_error_OperationNotAllowed');
}
}
elseif ( $variable_name == 'HardMaintenanceTemplate' ) {
$compile = $event->MasterEvent->getEventParam('compile_maintenance_template');
$compile = $compile || $new_value != $object->GetOriginalField('VariableValue');
if ( $compile && !$this->generateMaintenancePage($new_value) ) {
$object->SetError('VariableValue', 'template_file_missing', 'la_error_TemplateFileMissing');
}
}
elseif ( $variable_name == 'DefaultEmailRecipients' ) {
$email_event_data = $this->Application->GetVar('emailevents_' . $event->Prefix);
$object->SetDBField('VariableValue', $email_event_data[0]['Recipients']);
}
}
/**
- * Enter description here...
+ * Occurs after updating item
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
static $skin_deleted = false;
+ parent::OnAfterItemUpdate($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('ElementType') == 'password' ) {
if ( trim($object->GetDBField('VariableValue')) == '' ) {
$field_options = $object->GetFieldOptions('VariableValue');
unset($field_options['skip_empty']);
$object->SetFieldOptions('VariableValue', $field_options);
}
}
// allows to check if variable's value was changed now
$variable_name = $object->GetDBField('VariableName');
$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());
if ( $object->GetDBField('VariableValue') != $object->GetOriginalField('VariableValue') ) {
$changed[] = $variable_name;
$this->Application->SetVar($event->getPrefixSpecial() . '_changed', $changed);
// update value in cache, so other code (during this script run) would use new value
$this->Application->SetConfigValue($variable_name, $object->GetDBField('VariableValue'), true);
}
if ( $variable_name == 'Require_AdminSSL' || $variable_name == 'AdminSSL_URL' ) {
// when administrative console is moved to SSL mode, then delete skin
if ( in_array($variable_name, $changed) && !$skin_deleted ) {
$skin_helper =& $this->Application->recallObject('SkinHelper');
/* @var $skin_helper SkinHelper */
$skin_file = $skin_helper->getSkinPath();
if ( file_exists($skin_file) ) {
unlink($skin_file);
}
$skin_deleted = true;
}
}
$this->Application->StoreVar('config_was_updated', 1);
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
// 1. save user selected module root category
$new_category_id = getArrayValue($items_info, 'ModuleRootCategory', 'VariableValue');
if ( $new_category_id !== false ) {
unset($items_info['ModuleRootCategory']);
}
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
if ( $items_info ) {
$has_error = false;
foreach ($items_info as $id => $field_values) {
$object->Clear(); // clear validation errors from previous variable
$object->Load($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
if ( !$object->Update($id) ) {
// don't stop when error found !
$has_error = true;
}
}
$event->status = $has_error ? kEvent::erFAIL : kEvent::erSUCCESS;
}
if ( $event->status == kEvent::erSUCCESS ) {
if ( $new_category_id !== false ) {
// root category was submitted
$module = $this->Application->GetVar('module');
$root_category_id = $this->Application->findModule('Name', $module, 'RootCat');
if ( $root_category_id != $new_category_id ) {
// root category differs from one in db
$fields_hash = Array ('RootCat' => $new_category_id);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Modules', 'Name = ' . $this->Conn->qstr($module));
}
}
// reset cache
$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());
$require_refresh = Array ('AdvancedUserManagement', 'Site_Name', 'AdminConsoleInterface', 'UsePopups');
$refresh_sections = array_intersect($require_refresh, $changed);
$require_full_refresh = Array ('Site_Name', 'AdminConsoleInterface');
if ( array_intersect($require_full_refresh, $changed) ) {
$event->SetRedirectParam('refresh_all', 1);
}
elseif ( $refresh_sections ) {
$event->SetRedirectParam('refresh_tree', 1);
}
if ( $refresh_sections ) {
// reset sections too, because of AdvancedUserManagement
$this->Application->DeleteSectionCache();
}
$this->Application->DeleteUnitCache($changed);
}
elseif ( $this->Application->GetVar('errors_' . $event->getPrefixSpecial()) ) {
// because we have list out there, and this is item
$this->Application->removeObject($event->getPrefixSpecial());
}
// keeps module and section in REQUEST to ensure, that last admin template will work
$event->SetRedirectParam('module', $this->Application->GetVar('module'));
$event->SetRedirectParam('section', $this->Application->GetVar('section'));
}
/**
* Process items from selector (selected_ids var, key - prefix, value - comma separated ids)
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$selected_ids = $this->Application->GetVar('selected_ids');
$this->Application->StoreVar('ModuleRootCategory', $selected_ids['c']);
$event->SetRedirectParam('opener', 'u');
}
/**
* Generates maintenance page
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnGenerateMaintenancePage(kEvent &$event)
{
$event->setEventParam('compile_maintenance_template', 1);
$event->CallSubEvent('OnUpdate');
}
/**
* Generates HTML version of hard maintenance template
*
* @param string $template
* @return bool
* @access protected
*/
protected function generateMaintenancePage($template = null)
{
if ( !isset($template) ) {
$template = $this->Application->ConfigValue('HardMaintenanceTemplate');
}
$curl_helper =& $this->Application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
$html = $curl_helper->Send($this->Application->BaseURL() . '?t=' . $template);
if ( $curl_helper->isGoodResponseCode() ) {
file_put_contents(WRITEABLE . DIRECTORY_SEPARATOR . 'maintenance.html', $html);
return true;
}
return false;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/modules/modules_event_handler.php
===================================================================
--- branches/5.2.x/core/units/modules/modules_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/modules/modules_event_handler.php (revision 15065)
@@ -1,176 +1,178 @@
<?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 ModulesEventHandler extends kDBEventHandler {
/**
* Builds item (loads if needed)
*
* Pattern: Prototype Manager
*
* @param kEvent $event
* @access protected
*/
protected function OnItemBuild(kEvent &$event)
{
$this->Application->SetVar($event->getPrefixSpecial(true) . '_id', $event->Special);
parent::OnItemBuild($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( $event->Special ) {
$object->addFilter('current_module', '%1$s.Name = ' . $event->Special);
}
$object->addFilter('not_core', '%1$s.Name <> "Core"');
}
/**
* Define alternative event processing method names
*
* @return void
* @see kEventHandler::$eventMethods
* @access protected
*/
protected function mapEvents()
{
parent::mapEvents();
$this->eventMethods['OnMassApprove'] = 'moduleAction';
$this->eventMethods['OnMassDecline'] = 'moduleAction';
}
/**
* Disabled modules, but not In-Portal
*
* @param kEvent $event
*/
function moduleAction(&$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) {
return ;
}
$updated = 0;
$status_field = $this->Application->getUnitOption($event->Prefix, 'StatusField');
$status_field = array_shift($status_field);
foreach ($ids as $id) {
$object->Load($id);
if (in_array($id, Array ('In-Portal', 'Core')) || !$object->isLoaded()) {
// don't allow any kind of manupulations with kernel
// approve/decline on not installed module
continue;
}
$enabled = $event->Name == 'OnMassApprove' ? 1 : 0;
$object->SetDBField($status_field, $enabled);
if (!$object->GetChangedFields()) {
// no changes -> skip
continue;
}
if ($object->Update()) {
$updated++;
$sql = 'UPDATE ' . TABLE_PREFIX . 'ImportScripts
SET Status = ' . $enabled . '
WHERE Module = "' . $object->GetDBField('Name') . '"';
$this->Conn->Query($sql);
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
if ( $updated ) {
$event->status = kEvent::erSUCCESS;
- $event->setRedirectParams(Array ('opener' => 's'), true);
+ $event->SetRedirectParam('opener', 's');
$this->Application->DeleteUnitCache();
$this->Application->DeleteSectionCache();
$event->SetRedirectParam('RefreshTree', 1);
}
}
/**
* Occurs after list is queried
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterListQuery(&$event)
+ protected function OnAfterListQuery(kEvent &$event)
{
parent::OnAfterListQuery($event);
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$new_modules = $modules_helper->getModules(kModulesHelper::NOT_INSTALLED);
- if (!$new_modules || $this->Application->RecallVar('user_id') != USER_ROOT) {
- return ;
+ if ( !$new_modules || $this->Application->RecallVar('user_id') != USER_ROOT ) {
+ return;
}
require_once FULL_PATH . '/core/install/install_toolkit.php';
$toolkit = new kInstallToolkit();
$object =& $event->getObject();
/* @var $object kDBList */
foreach ($new_modules as $module) {
$module_record = Array (
'Name' => $toolkit->getModuleName($module),
'Path' => 'modules/' . $module . '/',
'Version' => $toolkit->GetMaxModuleVersion('modules/' . $module . '/'),
'Loaded' => 0,
'BuildDate' => null,
);
$object->addRecord($module_record);
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/permission_types/permission_type_eh.php
===================================================================
--- branches/5.2.x/core/units/permission_types/permission_type_eh.php (revision 15064)
+++ branches/5.2.x/core/units/permission_types/permission_type_eh.php (revision 15065)
@@ -1,40 +1,42 @@
<?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 PermissionTypeEventHandler extends kDBEventHandler {
/**
* Cant delete system permissions
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
parent::OnBeforeItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('IsSystem') ) {
// prevents deletion of this permission
$event->status = kEvent::erFAIL;
// informs main event, that redirect shouldn't be made
$event->MasterEvent->status = kEvent::erFAIL;
$this->Application->SetVar('cant_delete_system_permission', 1);
}
}
}
Index: branches/5.2.x/core/units/user_groups/user_groups_eh.php
===================================================================
--- branches/5.2.x/core/units/user_groups/user_groups_eh.php (revision 15064)
+++ branches/5.2.x/core/units/user_groups/user_groups_eh.php (revision 15065)
@@ -1,154 +1,154 @@
<?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 UserGroupsEventHandler extends kDBEventHandler {
/**
* Adds user as member for selected groups
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
if ($event->Prefix == 'u-ug') {
$new_groups = $this->Application->GetVar('g');
if (!$new_groups) {
return ;
}
$new_groups = array_keys($new_groups);
// don't insert duplicate group membership record
$user_id = $this->Application->GetVar('u_id');
$table_name = $this->Application->GetTempName(TABLE_PREFIX.'UserGroupRelations', 'prefix:u');
$sql = 'SELECT GroupId
FROM '.$table_name.'
WHERE PortalUserId = '.(int)$user_id;
$old_groups = $this->Conn->GetCol($sql);
$new_groups = array_diff($new_groups, $old_groups);
if ($new_groups) {
foreach ($new_groups as $new_group) {
$fields_hash = Array (
'GroupId' => $new_group,
'PortalUserId' => $user_id,
);
$this->Conn->doInsert($fields_hash, $table_name);
}
}
}
elseif ($event->Prefix == 'g-ug') {
$new_users = $this->Application->GetVar('u');
if (!$new_users) {
return ;
}
$new_users = array_keys($new_users);
// don't insert duplicate group membership record
$group_id = $this->Application->GetVar('g_id');
$table_name = $this->Application->GetTempName(TABLE_PREFIX.'UserGroupRelations', 'prefix:g');
$sql = 'SELECT PortalUserId
FROM ' . $table_name . '
WHERE GroupId = ' . (int)$group_id;
$old_users = $this->Conn->GetCol($sql);
$new_users = array_diff($new_users, $old_users);
if ($new_users) {
foreach ($new_users as $new_user) {
$fields_hash = Array (
'GroupId' => $group_id,
'PortalUserId' => $new_user,
);
$this->Conn->doInsert($fields_hash, $table_name);
}
}
}
$this->Application->StoreVar($this->Application->GetTopmostPrefix($event->Prefix).'_modified', '1', true); // true for optional
$event->SetRedirectParam('opener', 'u');
}
/**
* Sets primary group for user (in editing only)
*
* @param kEvent $event
*/
function OnSetPrimary(&$event)
{
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$user =& $this->Application->recallObject('u');
/* @var $user kDBItem */
$user->SetDBField('PrimaryGroupId', array_shift($ids));
$user->Update();
}
$this->clearSelectedIDs($event);
}
/**
* Don't allow primary group record deleting
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
- if ($event->Name == 'OnMassDelete' && $type == 'before') {
+ if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
- if ($ids) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ if ( $ids ) {
+ $object =& $event->getObject(Array ('skip_autoload' => true));
- if ($event->Prefix == 'u-ug') {
+ if ( $event->Prefix == 'u-ug' ) {
// allow deleting non-primary group of current user ($ids - groups)
$sql = 'SELECT PrimaryGroupId
FROM ' . $this->Application->GetTempName(TABLE_PREFIX . 'Users', 'prefix:u') . '
WHERE PortalUserId = ' . (int)$this->Application->GetVar('u_id');
$primary_group_id = (int)$this->Conn->GetOne($sql);
$index = array_search($primary_group_id, $ids);
- if ($index !== false) {
+ if ( $index !== false ) {
unset($ids[$index]);
$event->setEventParam('ids', $ids);
}
}
- elseif ($event->Prefix == 'g-ug') {
+ elseif ( $event->Prefix == 'g-ug' ) {
// allow deleting users from group record, then it's not their primary group ($ids - users)
$group_id = (int)$this->Application->GetVar('g_id');
$sql = 'SELECT PortalUserId
FROM ' . TABLE_PREFIX . 'Users
WHERE PortalUserId IN (' . implode(',', $ids) . ') AND PrimaryGroupId = ' . $group_id;
$exclude_users = $this->Conn->GetCol($sql);
$event->setEventParam('ids', array_diff($ids, $exclude_users));
}
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/category_items/category_items_event_handler.php
===================================================================
--- branches/5.2.x/core/units/category_items/category_items_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/category_items/category_items_event_handler.php (revision 15065)
@@ -1,158 +1,174 @@
<?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 CategoryItemsEventHander extends kDBEventHandler
{
/**
* Setting language dependant navigation bar as calculated field
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
/* @var $ml_formatter kMultiLanguage */
$object->addCalculatedField('CategoryName', 'c.' . $ml_formatter->LangFieldName('CachedNavbar'));
}
/**
* Set's new category as primary for product
*
* @param kEvent $event
*/
function OnSetPrimary(&$event)
{
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$ids = $this->StoreSelectedIDs($event);
if ( $ids ) {
$id = array_shift($ids);
$table_info = $object->getLinkedInfo();
$this->Conn->Query('UPDATE ' . $object->TableName . ' SET PrimaryCat = 0 WHERE ' . $table_info['ForeignKey'] . ' = ' . $table_info['ParentId']);
$this->Conn->Query('UPDATE ' . $object->TableName . ' SET PrimaryCat = 1 WHERE (' . $table_info['ForeignKey'] . ' = ' . $table_info['ParentId'] . ') AND (CategoryId = ' . $id . ')');
}
- $event->setRedirectParams(Array ('opener' => 's'), true);
+ $event->SetRedirectParam('opener', 's');
}
/**
* Apply custom processing to item
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
- protected function customProcessing(&$event, $type)
+ protected function customProcessing(kEvent &$event, $type)
{
- if($event->Name == 'OnMassDelete')
- {
+ if ( $event->Name == 'OnMassDelete' ) {
$object =& $event->getObject();
$table_info = $object->getLinkedInfo();
- switch ($type)
- {
+ switch ($type) {
case 'before':
$ids = $event->getEventParam('ids');
- if($ids)
- {
- $ids = $this->Conn->GetCol('SELECT CategoryId FROM '.$object->TableName.' WHERE (PrimaryCat=0) AND ('.$table_info['ForeignKey'].'='.$table_info['ParentId'].') AND CategoryId IN ('.implode(',',$ids).')');
- $event->setEventParam('ids',$ids);
+
+ if ( $ids ) {
+ $sql = 'SELECT CategoryId
+ FROM ' . $object->TableName . '
+ WHERE (PrimaryCat = 0) AND (' . $table_info['ForeignKey'] . '=' . $table_info['ParentId'] . ') AND CategoryId IN (' . implode(',', $ids) . ')';
+ $event->setEventParam('ids', $this->Conn->GetCol($sql));
}
break;
- // not needed because 'before' does not allow to delete primary cat!
+ // not needed because 'before' does not allow to delete primary cat!
/*case 'after':
// set 1st not deleted category as primary
- $has_primary = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$object->TableName.' WHERE (PrimaryCat=1) AND ('.$table_info['ForeignKey'].' = '.$table_info['ParentId'].')');
- if(!$has_primary)
- {
- $cat_id = $this->Conn->GetOne('SELECT CategoryId FROM '.$object->TableName.' WHERE '.$table_info['ForeignKey'].' = '.$table_info['ParentId']);
- $this->Conn->Query('UPDATE '.$object->TableName.' SET PrimaryCat = 1 WHERE ('.$table_info['ForeignKey'].' = '.$table_info['ParentId'].') AND (CategoryId = '.$cat_id.')');
+ $sql = 'SELECT COUNT(*)
+ FROM ' . $object->TableName . '
+ WHERE (PrimaryCat = 1) AND (' . $table_info['ForeignKey'] . ' = ' . $table_info['ParentId'] . ')';
+ $has_primary = $this->Conn->GetOne($sql);
+
+ if ( !$has_primary ) {
+ $sql = 'SELECT CategoryId
+ FROM ' . $object->TableName . '
+ WHERE ' . $table_info['ForeignKey'] . ' = ' . $table_info['ParentId'];
+ $cat_id = $this->Conn->GetOne($sql);
+
+ $sql = 'UPDATE ' . $object->TableName . '
+ SET PrimaryCat = 1
+ WHERE (' . $table_info['ForeignKey'] . ' = ' . $table_info['ParentId'] . ') AND (CategoryId = ' . $cat_id . ')';
+ $this->Conn->Query($sql);
}
break;*/
}
}
}
/**
* Removes primary mark from cloned category items record
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterClone(&$event)
+ protected function OnAfterClone(kEvent &$event)
{
+ parent::OnAfterClone($event);
+
$id = $event->getEventParam('id');
$table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
- $sql = 'UPDATE %s SET PrimaryCat = 0 WHERE %s = %s';
- $this->Conn->Query( sprintf($sql, $table, $id_field, $id) );
+ $sql = 'UPDATE %s
+ SET PrimaryCat = 0
+ WHERE %s = %s';
+ $this->Conn->Query(sprintf($sql, $table, $id_field, $id));
}
/**
* Deletes items of requested type from requested categories.
* In case if item is deleted from it's last category, then delete item too.
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnDeleteFromCategory(&$event)
{
$category_ids = $event->getEventParam('category_ids');
if ( !$category_ids ) {
return ;
}
$item_prefix = $event->getEventParam('item_prefix');
$item =& $this->Application->recallObject($item_prefix . '.-item', null, Array ('skip_autoload' => true));
/* @var $item kCatDBItem */
$ci_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$item_table = $this->Application->getUnitOption($item_prefix, 'TableName');
$sql = 'SELECT ItemResourceId, CategoryId
FROM %1$s
INNER JOIN %2$s ON (%1$s.ResourceId = %2$s.ItemResourceId)
WHERE CategoryId IN (%3$s)';
$category_items = $this->Conn->Query( sprintf($sql, $item_table, $ci_table, implode(',', $category_ids)) );
$item_hash = Array ();
foreach ($category_items as $ci_row) {
$item_hash[ $ci_row['ItemResourceId'] ][] = $ci_row['CategoryId'];
}
foreach ($item_hash as $item_resource_id => $delete_category_ids) {
$item->Load($item_resource_id, 'ResourceId');
$item->DeleteFromCategories($delete_category_ids);
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/groups/groups_event_handler.php
===================================================================
--- branches/5.2.x/core/units/groups/groups_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/groups/groups_event_handler.php (revision 15065)
@@ -1,70 +1,70 @@
<?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 GroupsEventHandler extends kDBEventHandler {
/**
* Adds grouping by user id
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
switch ($event->Special) {
case 'user':
$user_id = $this->Application->GetVar('u_id');
if ( $user_id !== false ) {
// show only groups, that user doesn't belong to
$table_name = $this->Application->GetTempName(TABLE_PREFIX . 'UserGroupRelations', 'prefix:u');
$sql = 'SELECT GroupId
FROM ' . $table_name . '
WHERE PortalUserId = ' . (int)$user_id;
$group_ids = $this->Conn->GetCol($sql);
// add system groups
array_push($group_ids, $this->Application->ConfigValue('User_GuestGroup')); // Guest
array_push($group_ids, $this->Application->ConfigValue('User_LoggedInGroup')); // Everyone
$object->addFilter('already_member_filter', '%1$s.GroupId NOT IN (' . implode(',', $group_ids) . ')');
}
break;
}
}
/**
* Refreshes left tree on save
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
$this->Application->StoreVar('refresh_tree', 1);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/reviews/reviews_event_handler.php
===================================================================
--- branches/5.2.x/core/units/reviews/reviews_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/reviews/reviews_event_handler.php (revision 15065)
@@ -1,610 +1,617 @@
<?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 ReviewsEventHandler extends kDBEventHandler
{
/**
* Returns special of main item for linking with sub-item
*
* @param kEvent $event
* @return string
* @access protected
*/
protected function getMainSpecial(kEvent &$event)
{
if ( $event->Special == 'product' && !$this->Application->isAdmin ) {
// rev.product should auto-link
return '';
}
return parent::getMainSpecial($event);
}
/**
* Checks REVIEW/REVIEW.PENDING permission by main object primary category (not current category)
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnAddReview' || $event->Name == 'OnCreate' ) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$perm_name = $this->getPermPrefix($event).'.REVIEW';
$res = $this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId')) ||
$this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'));
if ( !$res ) {
$event->status = kEvent::erPERM_FAIL;
}
return $res;
}
$check_events = Array (
'OnItemBuild', 'OnUpdate', /*'OnMassApprove', 'OnMassDecline'*/
);
$perm_category = $this->_getReviewCategory($event);
if ( in_array($event->Name, $check_events) ) {
// check for PRODUCT.VIEW permission
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_prefix = $this->getPermPrefix($event);
if ( $perm_category === false ) {
// no item id present -> allow
return true;
}
switch ($event->Name) {
case 'OnItemBuild':
$res = $this->Application->CheckPermission($perm_prefix . '.VIEW', 0, $perm_category);
break;
case 'OnUpdate':
case 'OnMassApprove':
case 'OnMassDecline':
$res = $this->Application->CheckPermission($perm_prefix . '.ADD', 0, $perm_category) ||
$this->Application->CheckPermission($perm_prefix . '.MODIFY', 0, $perm_category);
break;
default:
$res = false;
break;
}
if ( !$res ) {
$event->status = kEvent::erPERM_FAIL;
}
return $res;
}
return parent::CheckPermission($event);
}
/**
* Returns primary category of review's main item
*
* @param kEvent $event
* @return int
*/
function _getReviewCategory(&$event)
{
$items_info = $this->Application->GetVar($event->getPrefixSpecial());
if ($items_info) {
// rev:PresetFormFields is used to initialize new review creation
list ($review_id, ) = each($items_info);
}
else {
// when adding new review in admin
$review_id = false;
}
if (!$review_id) {
return false;
}
$object =& $event->getObject();
/* @var $object kDBItem */
// 1. get main item resource id (use object, because of temp tables in admin)
$sql = 'SELECT ItemId
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $review_id;
$resource_id = $this->Conn->GetOne($sql);
// 2. set main item id (for permission checks)
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$sql = 'SELECT ' . $this->Application->getUnitOption($parent_prefix, 'IDField') .'
FROM ' . $this->Application->getUnitOption($parent_prefix, 'TableName') .'
WHERE ResourceId = ' . $resource_id;
$this->Application->SetVar($parent_prefix . '_id', $this->Conn->GetOne($sql));
// 3. get main item category
$sql = 'SELECT CategoryId
FROM ' . $this->Application->getUnitOption('ci', 'TableName') .'
WHERE ItemResourceId = ' . $resource_id .' AND PrimaryCat = 1';
return $this->Conn->GetOne($sql);
}
/**
* Returns prefix for permissions
*
* @param kEvent $event
*/
function getPermPrefix(&$event)
{
$main_prefix = $this->Application->GetTopmostPrefix($event->Prefix, true);
// this will return LINK for l, ARTICLE for n, TOPIC for bb, PRODUCT for p
return $this->Application->getUnitOption($main_prefix, 'PermItemPrefix');
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @access protected
* @see OnListBuild
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( !$this->Application->isAdminUser ) {
$object->addFilter('active', '%1$s.Status = ' . STATUS_ACTIVE);
}
switch ($event->Special) {
case 'showall':
$object->clearFilters();
break;
case 'item': // used ?
$object->clearFilters();
$parent_info = $object->getLinkedInfo();
$parent =& $this->Application->recallObject($parent_info['ParentPrefix']);
/* @var $parent kDBItem */
$object->addFilter('item_reviews', '%1$s.ItemId = ' . $parent->GetDBField('ResourceId'));
break;
case 'products': // used in In-Portal (Structure & Data -> Reviews section)
$object->removeFilter('parent_filter'); // this is important
$object->addFilter('product_reviews', 'pr.ResourceId IS NOT NULL');
break;
}
if ( preg_match('/(.*)-rev/', $event->Prefix, $regs) ) {
// "Structure & Data" -> "Reviews" (section in K4)
$item_type = $this->Application->getUnitOption($regs[1], 'ItemType');
$object->addFilter('itemtype_filter', '%1$s.ItemType = ' . $item_type);
if ( $this->Application->isAdmin ) {
// temporarily solution so we can see sub-items on separate grid in Admin
$object->removeFilter('parent_filter');
}
}
if ( $event->getEventParam('type') == 'current_user' ) {
$object->addFilter('current_user', '%1$s.CreatedById = ' . $this->Application->RecallVar('user_id'));
$object->addFilter('current_ip', '%1$s.IPAddress = "' . $_SERVER['REMOTE_ADDR'] . '"');
}
}
/**
* Adds review from front in case if user is logged in
*
* @param kEvent $event
*/
function OnAddReview(&$event)
{
$event->CallSubEvent('OnCreate');
}
/**
* Get new review status on user review permission
*
* @param kEvent $event
* @return int
*/
function getReviewStatus(&$event)
{
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix);
/* @var $main_object kCatDBItem */
$ret = STATUS_DISABLED;
$perm_name = $this->getPermPrefix($event).'.REVIEW';
if ($this->Application->CheckPermission($perm_name, 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_ACTIVE;
}
else if ($this->Application->CheckPermission($perm_name.'.PENDING', 0, $main_object->GetDBField('CategoryId'))) {
$ret = STATUS_PENDING;
}
return $ret;
}
/**
* Prefills all fields on front-end
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$parent_info = $object->getLinkedInfo();
$item_type = $this->Application->getUnitOption($parent_info['ParentPrefix'], 'ItemType');
$object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']);
$object->SetDBField('ItemType', $item_type);
$object->SetDBField('Module', $this->Application->findModule('Var', $parent_info['ParentPrefix'], 'Name'));
if ( $this->Application->isAdminUser ) {
// don't perform spam control on admin
return ;
}
$spam_helper =& $this->Application->recallObject('SpamHelper');
/* @var $spam_helper SpamHelper */
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', 0);
if ( $spam_helper->InSpamControl() ) {
$event->status = kEvent::erFAIL;
$object->SetError('ReviewText', 'too_frequent', 'lu_ferror_review_duplicate');
return;
}
$rating = $object->GetDBField('Rating');
if ( $rating < 1 || $rating > 5 ) {
$object->SetDBField('Rating', null);
}
$object->SetDBField('ItemId', $parent_info['ParentId']); // ResourceId
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
$object->SetDBField('Status', $this->getReviewStatus($event));
$object->SetDBField('TextFormat', 0); // set plain text format directly
}
/**
* Sets correct rating value
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$rating = $object->GetDBField('Rating');
if ( !$rating ) {
$object->SetDBField('Rating', null);
}
}
/**
* Updates item review counter
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$this->updateSubitemCounters($event);
if ( !$this->Application->isAdminUser ) {
$spam_helper =& $this->Application->recallObject('SpamHelper');
/* @var $spam_helper SpamHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
$parent_info = $object->getLinkedInfo();
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
$review_settings = $config_mapping['ReviewDelayValue'] . ':' . $config_mapping['ReviewDelayInterval'];
$spam_helper->InitHelper($parent_info['ParentId'], 'Review', $review_settings);
$spam_helper->AddToSpamControl();
$review_status = $object->GetDBField('Status');
if ( $review_status == STATUS_ACTIVE || $review_status == STATUS_PENDING ) {
$email_event = $this->getPermPrefix($event) . '.REVIEW.' . ($review_status == STATUS_ACTIVE ? 'ADD' : 'ADD.PENDING');
$this->Application->EmailEventUser($email_event, $object->GetDBField('CreatedById'));
$this->Application->EmailEventAdmin($email_event);
}
}
}
/**
* Updates item review counter
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$this->updateSubitemCounters($event);
$object =& $event->getObject();
/* @var $object kDBItem */
- if ($this->Application->isAdminUser && !$object->IsTempTable()) {
+ if ( $this->Application->isAdminUser && !$object->IsTempTable() ) {
// send email on review status change from reviews grid in admin
$review_status = $object->GetDBField('Status');
$process_status = Array (STATUS_ACTIVE, STATUS_DISABLED);
- if (($review_status != $object->GetOriginalField('Status')) && in_array($review_status, $process_status)) {
+ if ( ($review_status != $object->GetOriginalField('Status')) && in_array($review_status, $process_status) ) {
$this->_loadMainObject($event);
$email_event = $this->getPermPrefix($event) . '.REVIEW.' . ($review_status == STATUS_ACTIVE ? 'APPROVE' : 'DENY');
$this->Application->EmailEventUser($email_event, $object->GetDBField('CreatedById'));
}
}
}
/**
* Loads main object of review (link, article, etc.)
*
* @param kEvent $event
* @return kCatDBItem
*/
function _loadMainObject(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$parent_table_key = $this->Application->getUnitOption($event->Prefix, 'ParentTableKey');
$foreign_key = $this->Application->getUnitOption($event->Prefix, 'ForeignKey');
$main_object =& $this->Application->recallObject($parent_prefix, null, Array ('skip_autoload' => true));
/* @var $main_object kDBItem */
$main_object->Load($object->GetDBField($foreign_key), $parent_table_key);
}
/**
* Updates total review counter, cached rating, votes count
*
* @param kEvent $event
*/
function updateSubitemCounters(&$event)
{
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$main_object =& $this->Application->recallObject($parent_prefix, null, Array ('raise_warnings' => 0));
/* @var $main_object kCatDBItem */
if (!$main_object->isLoaded()) {
// deleting main item / cloning main item
return ;
}
$object =& $event->getObject(); // for temp tables
/* @var $object kDBItem */
// 1. update review counter
$sql = 'SELECT COUNT(ReviewId)
FROM '.$object->TableName.'
WHERE ItemId = '.$main_object->GetDBField('ResourceId');
$review_count = $this->Conn->GetOne($sql);
$main_object->SetDBField('CachedReviewsQty', $review_count);
// 2. update votes counter + rating
$rating = $object->GetDBField('Rating');
$avg_rating = $main_object->GetDBField('CachedRating');
$votes_count = $main_object->GetDBField('CachedVotesQty');
switch ($event->Name) {
case 'OnAfterItemCreate': // adding new review with rating
$this->changeRating($avg_rating, $votes_count, $rating, '+');
break;
case 'OnAfterItemDelete':
$this->changeRating($avg_rating, $votes_count, $rating, '-');
break;
case 'OnAfterItemUpdate':
$this->changeRating($avg_rating, $votes_count, $object->GetOriginalField('Rating'), '-');
$this->changeRating($avg_rating, $votes_count, $rating, '+');
break;
}
$main_object->SetDBField('CachedRating', "$avg_rating"); // covert $avg_rating value to string
$main_object->SetDBField('CachedVotesQty', $votes_count);
$main_object->Update();
}
/**
* Changes average rating and votes count based on requested operation
*
* @param float $avg_rating average rating before new vote
* @param int $votes_count votes count before new vote
* @param int $rating new vote (from 1 to 5)
* @param string $operation requested operation (+ / -)
*/
function changeRating(&$avg_rating, &$votes_count, $rating, $operation)
{
if ($rating < 1 || $rating > 5) {
return ;
}
if ($operation == '+') {
$avg_rating = (($avg_rating * $votes_count) + $rating) / ($votes_count + 1);
++$votes_count;
}
else {
$avg_rating = (($avg_rating * $votes_count) - $rating) / ($votes_count - 1);
--$votes_count;
}
}
-
/**
* Updates main item cached review counter
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
+ parent::OnAfterItemDelete($event);
+
$this->updateSubitemCounters($event);
}
/**
* Creates review & redirect to confirmation template
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
parent::OnCreate($event);
if ( $event->status != kEvent::erSUCCESS || $this->Application->isAdmin ) {
return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $this->Application->GetVar('ajax') == 'yes' ) {
$ajax_form_helper =& $this->Application->recallObject('AjaxFormHelper');
/* @var $ajax_form_helper AjaxFormHelper */
$params = Array ('status' => 'OK');
if ( $event->status != kEvent::erSUCCESS ) {
$ajax_form_helper->prepareJSONErrors($event, $params);
}
// let FormManager decide what template to show
$params['review_status'] = $object->GetDBField('Status');
$ajax_form_helper->sendResponse($event, $params);
}
else {
$event->SetRedirectParam('opener', 's');
$next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'success_template' : 'success_pending_template';
$event->redirect = $this->Application->GetVar($next_template);
$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$event->SetRedirectParam('pass', 'm,'.$parent_prefix);
}
}
/**
* Makes left join to item's table, when in separate grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
if (preg_match('/(.*)-rev/', $event->Prefix, $regs) && $this->Application->prefixRegistred($regs[1])) {
// "Structure & Data" -> "Reviews" (section in K4)
// 1. add join to items table (for "Structure & Data" -> "Reviews" section)
$item_table = $this->Application->getUnitOption($regs[1], 'TableName');
$ci_table = $this->Application->getUnitOption('ci', 'TableName');
$list_sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs');
$list_sqls[''] .= ' LEFT JOIN '.$item_table.' item_table ON item_table.ResourceId = %1$s.ItemId';
$list_sqls[''] .= ' LEFT JOIN '.$ci_table.' ci ON item_table.ResourceId = ci.ItemResourceId AND ci.PrimaryCat = 1';
$this->Application->setUnitOption($event->Prefix, 'ListSQLs', $list_sqls);
// 2. add calculated field
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
$calculated_fields['']['CatalogItemName'] = 'item_table.' . $this->getTitleField($regs[1]);
$calculated_fields['']['CatalogItemId'] = 'item_table.' . $this->Application->getUnitOption($regs[1], 'IDField');
$calculated_fields['']['CatalogItemCategory'] = 'ci.CategoryId';
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
}
}
/**
* Convert TitleField field of kMultiLanguage formatter used for it
*
* @param string $prefix
* @return string
*/
function getTitleField($prefix)
{
$lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
$title_field = $this->Application->getUnitOption($prefix, 'TitleField');
$field_options = $this->Application->getUnitOption($prefix.'.'.$title_field, 'Fields');
$formatter_class = isset($field_options['formatter']) ? $field_options['formatter'] : '';
if ($formatter_class == 'kMultiLanguage' && !isset($field_options['master_field'])) {
$title_field = $lang_prefix.$title_field;
}
return $title_field;
}
/**
* Set's new perpage for Category Item Reviews (used on Front-end)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPerPage(kEvent &$event)
{
parent::OnSetPerPage($event);
$parent_prefix = $event->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$event->SetRedirectParam('pass', 'm,' . $event->getPrefixSpecial() . ',' . $parent_prefix);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/forms/form_submissions/form_submissions_eh.php
===================================================================
--- branches/5.2.x/core/units/forms/form_submissions/form_submissions_eh.php (revision 15064)
+++ branches/5.2.x/core/units/forms/form_submissions/form_submissions_eh.php (revision 15065)
@@ -1,546 +1,552 @@
<?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 FormSubmissionsEventHandler extends kDBEventHandler {
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( !$this->Application->isAdmin ) {
if ( $event->Name == 'OnCreate' ) {
// anybody can submit forms on front
return true;
}
}
$section = $event->getSection();
$form_id = $this->Application->GetVar('form_id');
$event->setEventParam('PermSection', $section . ':' . $form_id);
return parent::CheckPermission($event);
}
/**
* Always allow to view feedback form
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array ('self' => true),
'OnEdit' => Array ('self' => 'view', 'subitem' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Returns filter block based on field element type
*
* @param string $element_type
* @return string
*/
function _getFilterBlock($element_type)
{
$mapping = Array (
'text' => 'grid_like_filter',
'select' => 'grid_options_filter',
'radio' => 'grid_options_filter',
'checkbox' => 'grid_options_filter',
'password' => 'grid_like_filter',
'textarea' => 'grid_like_filter',
'label' => 'grid_like_filter',
'upload' => 'grid_empty_filter',
);
return $mapping[$element_type];
}
function OnBuildFormFields(&$event)
{
$form_id = $this->Application->GetVar('form_id');
if (!$form_id) return ;
$conf_fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$conf_grids = $this->Application->getUnitOption($event->Prefix, 'Grids');
$helper =& $this->Application->recallObject('InpCustomFieldsHelper');
/* @var $helper InpCustomFieldsHelper */
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'FormFields
WHERE FormId = ' . (int)$form_id . '
ORDER BY Priority DESC';
$fields = $this->Conn->Query($sql, 'FormFieldId');
$use_options = Array ('radio', 'select', 'checkbox');
$check_visibility = $this->Application->LoggedIn() && !$this->Application->isAdminUser;
foreach ($fields as $field_id => $options) {
$field_visible = $check_visibility ? $options['Visibility'] == SubmissionFormField::VISIBILITY_EVERYONE : true;
$field_options = Array('type' => 'string', 'default' => $options['DefaultValue']);
if ($options['Required'] && $field_visible) {
$field_options['required'] = 1;
}
if ($options['Validation'] == 1) {
$field_options['formatter'] = 'kFormatter';
$field_options['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
}
if ($options['DisplayInGrid']) {
$title = $options['Prompt'];
if (substr($title, 0, 1) == '+') {
$this->Application->Phrases->AddCachedPhrase('form_col_title' . $field_id, substr($title, 1));
$title = 'form_col_title' . $field_id;
}
$conf_grids['Default']['Fields']['fld_' . $field_id] = Array (
'title' => $title, 'no_special' => 1, 'nl2br' => 1, 'first_chars' => 200,
'filter_block' => $this->_getFilterBlock($options['ElementType'])
);
if ($options['ElementType'] == 'upload') {
$conf_grids['Default']['Fields']['fld_' . $field_id]['data_block'] = 'grid_upload_td';
}
if ($options['Validation'] == 1) {
$conf_grids['Default']['Fields']['fld_' . $field_id]['data_block'] = 'grid_email_td';
}
}
if ($options['ElementType'] == 'checkbox' && !$options['ValueList']) {
// fix case, when user haven't defined any options for checkbox
$options['ValueList'] = '1=la_Yes||0=la_No';
}
if (in_array($options['ElementType'], $use_options) && $options['ValueList']) {
// field type can have options and user have defined them too
$field_options['options'] = $helper->GetValuesHash( $options['ValueList'] );
$field_options['formatter'] = 'kOptionsFormatter';
}
if ($options['ElementType'] == 'password') {
$field_options['formatter'] = 'kPasswordFormatter';
$field_options['encryption_method'] = 'plain';
$field_options['verify_field'] = 'fld_' . $field_id . '_verify';
}
if ($options['ElementType'] == 'upload') {
$field_options['formatter'] = 'kUploadFormatter';
$field_options['upload_dir'] = WRITEBALE_BASE . DIRECTORY_SEPARATOR . 'user_files' . DIRECTORY_SEPARATOR . 'form_submissions';
if ( $options['UploadMaxSize'] ) {
$field_options['max_size'] = $options['UploadMaxSize'] * 1024; // convert Kbytes to bytes
}
if ( $options['UploadExtensions'] ) {
$field_options['file_types'] = '*.' . implode(';*.', explode(',', $options['UploadExtensions']));
}
}
$conf_fields['fld_' . $field_id] = $field_options;
}
$this->Application->setUnitOption($event->Prefix, 'Fields', $conf_fields);
$this->Application->setUnitOption($event->Prefix, 'Grids', $conf_grids);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
$object->addFilter('form_filter', '%1$s.FormId = ' . (int)$this->Application->GetVar('form_id'));
}
/**
* Allows user to see it's last feedback form data
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'last' ) {
// allow user to see his last submitted form
return $this->Application->RecallVar('last_submission_id');
}
if ( $this->Application->isAdminUser ) {
// don't check ids in admin
return parent::getPassedID($event);
}
// no way to see other user's form submission by giving it's ID directly in url
return 0;
}
/**
* Creates new form submission from Front-End
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
parent::OnCreate($event);
- if ($event->status != kEvent::erSUCCESS) {
- return ;
+ if ( $event->status != kEvent::erSUCCESS ) {
+ return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
// allows user to view only it's last submission
$this->Application->StoreVar('last_submission_id', $object->GetID());
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($object);
$notify_email = $form->GetDBField('SubmitNotifyEmail');
- if ($notify_email) {
+ if ( $notify_email ) {
$send_params = Array (
'to_name' => $notify_email,
'to_email' => $notify_email,
);
$this->Application->EmailEventAdmin('FORM.SUBMITTED', null, $send_params);
}
else {
$this->Application->EmailEventAdmin('FORM.SUBMITTED');
}
// $this->Application->EmailEventUser('FORM.SUBMITTED', null, 'to_email' => '');
$event->SetRedirectParam('opener', 's');
$event->SetRedirectParam('m_cat_id', 0);
$theme =& $this->Application->recallObject('theme.current');
/* @var $theme kDBItem */
- $template = kUtil::unhtmlentities( $this->Application->GetVar('success_template') ); // kHTTPQuery do htmlspecialchars on everything
+ $template = kUtil::unhtmlentities($this->Application->GetVar('success_template')); // kHTTPQuery do htmlspecialchars on everything
$alias_template = $theme->GetField('TemplateAliases', $template);
$event->redirect = $alias_template ? $alias_template : $template;
}
/**
* Processes Captcha code
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']);
if ( !$object->GetDBField('ReferrerURL') ) {
$referrer = $this->Application->GetVar('original_referrer');
if ( !$referrer ) {
$base_url = preg_quote($this->Application->BaseURL(), '/');
$referrer = preg_replace('/^' . $base_url . '/', '/', $_SERVER['HTTP_REFERER'], 1);
}
$object->SetDBField('ReferrerURL', $referrer);
}
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($object);
// validate captcha code
if ( $form->GetDBField('UseSecurityImage') && !$this->Application->LoggedIn() ) {
$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
/* @var $captcha_helper kCaptchaHelper */
$captcha_helper->validateCode($event, false);
}
}
/**
* Checks, that target submission was selected for merging
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->setRequired('MergeToSubmission', $object->GetDBField('IsMergeToSubmission'));
}
/**
* Passes form_id, when using "Prev"/"Next" toolbar buttons
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndGo(&$event)
+ protected function OnPreSaveAndGo(kEvent &$event)
{
parent::OnPreSaveAndGo($event);
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
$event->SetRedirectParam('pass', 'm,form,formsubs');
}
}
/**
* Saves edited item in temp table and goes
* to passed tabs, by redirecting to it with OnPreSave event
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndGoToTab(&$event)
+ protected function OnPreSaveAndGoToTab(kEvent &$event)
{
parent::OnPreSaveAndGoToTab($event);
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
$event->SetRedirectParam('pass', 'm,form,formsubs');
}
}
/**
* Set's new per-page for grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPerPage(kEvent &$event)
{
parent::OnSetPerPage($event);
$event->SetRedirectParam('pass', 'm,form,' . $event->getPrefixSpecial());
}
/**
* Occurs when page is changed (only for hooking)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPage(kEvent &$event)
{
parent::OnSetPage($event);
$event->SetRedirectParam('pass', 'm,form,' . $event->getPrefixSpecial());
}
/**
* Fills merge-to dropdown
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
if ($event->Special == 'merge-to') {
return ;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$form_id = $object->GetDBField('FormId');
$email_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_EMAIL);
if (!$email_field) {
return ;
}
$merge_to =& $this->Application->recallObject($event->Prefix . '.merge-to', null, Array ('skip_autoload' => true));
/* @var $merge_to kDBItem */
$sql = $merge_to->GetSelectSQL() . ' WHERE (FormId = ' . $form_id . ') AND (' . $email_field . ' = ' . $this->Conn->qstr( $object->GetDBField($email_field) ) . ')';
$submissions = $this->Conn->Query($sql, $object->IDField);
// remove this submission
unset($submissions[ $object->GetID() ]);
if (!$submissions) {
return ;
}
$options = Array ();
$name_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_NAME);
$subject_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_SUBJECT);
$language =& $this->Application->recallObject('lang.current');
/* @var $language kDBItem */
$date_format = $language->GetDBField('DateFormat');
foreach ($submissions as $submission_id => $submission_data) {
$option_title = ''; // SenderName (email@address.com) - Subject (06/29/2010)
$merge_to->LoadFromHash($submission_data);
if ($name_field) {
$option_title = $merge_to->GetDBField($name_field) . ' (' . $merge_to->GetDBField($email_field) . ') - ';
}
else {
$option_title = $merge_to->GetDBField($email_field) . ' - ';
}
if ($subject_field) {
$option_title .= $merge_to->GetField($subject_field) . ' (' . $merge_to->GetField('SubmissionTime', $date_format) . ')';
}
else {
$option_title .= $merge_to->GetField('SubmissionTime', $date_format);
}
$options[$submission_id] = $option_title;
}
$object->SetFieldOption('MergeToSubmission', 'options', $options);
}
/**
* Returns submission field name based on given role
*
* @param int $form_id
* @param string $role
* @return string
*/
function getFieldByRole($form_id, $role)
{
static $cache = Array ();
if (!array_key_exists($form_id, $cache)) {
$id_field = $this->Application->getUnitOption('formflds', 'IDField');
$table_name = $this->Application->getUnitOption('formflds', 'TableName');
$sql = 'SELECT ' . $id_field . ', EmailCommunicationRole
FROM ' . $table_name . '
WHERE FormId = ' . $form_id . ' AND EmailCommunicationRole <> 0';
$cache[$form_id] = $this->Conn->GetCol($sql, 'EmailCommunicationRole');
}
// get field name by role
return array_key_exists($role, $cache[$form_id]) ? 'fld_' . $cache[$form_id][$role] : false;
}
/**
* Performs submission merge
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
parent::OnUpdate($event);
if ($event->status == kEvent::erSUCCESS) {
$object =& $event->getObject();
/* @var $object kDBItem */
$merge_to = $object->GetDBField('MergeToSubmission');
if (!$merge_to) {
return ;
}
$form_id = $object->GetDBField('FormId');
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Forms
WHERE FormId = ' . $form_id;
$form_info = $this->Conn->GetRow($sql);
$reply =& $this->Application->recallObject('submission-log.merge', null, Array ('skip_autoload' => true));
/* @var $reply kDBItem */
$email_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_EMAIL);
$subject_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_SUBJECT);
$body_field = $this->getFieldByRole($form_id, SubmissionFormField::COMMUNICATION_ROLE_BODY);
$reply->SetDBField('FormSubmissionId', $merge_to);
if ($email_field) {
$reply->SetDBField('FromEmail', $object->GetDBField($email_field));
}
$reply->SetDBField('ToEmail', $form_info['ReplyFromEmail']);
if ($subject_field) {
$reply->SetDBField('Subject', $object->GetDBField($subject_field));
}
if ($body_field) {
$reply->SetDBField('Message', $object->GetDBField($body_field));
}
$reply->SetDBField('SentOn_date', $object->GetDBField('SubmissionTime'));
$reply->SetDBField('SentOn_time', $object->GetDBField('SubmissionTime'));
$reply->SetDBField('MessageId', $object->GetDBField('MessageId'));
$reply->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
// as if emails was really received via mailbox
$this->Application->SetVar('client_mode', 1);
if ($reply->Create()) {
// delete submission, since it was merged
$object->Delete();
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/forms/drafts/draft_eh.php
===================================================================
--- branches/5.2.x/core/units/forms/drafts/draft_eh.php (revision 15064)
+++ branches/5.2.x/core/units/forms/drafts/draft_eh.php (revision 15065)
@@ -1,59 +1,59 @@
<?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 DraftEventHandler extends kDBEventHandler
{
/**
* Sets user, who created draft
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$user_id = $this->Application->RecallVar('user_id');
$object->SetDBField('CreatedById', $user_id);
}
/**
* Allows to load draft, that best matches given form submission
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'related' ) {
$form_submission =& $this->Application->recallObject('formsubs');
/* @var $form_submission kDBItem */
return Array (
'FormSubmissionId' => $form_submission->GetID(),
'CreatedById' => $this->Application->RecallVar('user_id'),
);
}
return parent::getPassedID($event);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/forms/forms/forms_eh.php
===================================================================
--- branches/5.2.x/core/units/forms/forms/forms_eh.php (revision 15064)
+++ branches/5.2.x/core/units/forms/forms/forms_eh.php (revision 15065)
@@ -1,627 +1,627 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class FormsEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
// user can view any form on front-end
'OnItemBuild' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function OnCreateSubmissionNodes(&$event)
{
if (defined('IS_INSTALL') && IS_INSTALL) {
// skip any processing, because Forms table doesn't exists until install is finished
return ;
}
$forms = $this->getForms();
if (!$forms) {
return ;
}
$form_subsection = Array(
'parent' => 'in-portal:forms',
'icon' => 'form_submission',
'label' => '',
'url' => Array('t' => 'submissions/submissions_list', 'pass' => 'm,form'),
'permissions' => Array('view', 'add', 'edit', 'delete'),
'priority' => 1,
'type' => stTREE,
);
$priority = 1;
$sections = $this->Application->getUnitOption($event->Prefix, 'Sections');
foreach ($forms as $form_id => $form_name) {
$this->Application->Phrases->AddCachedPhrase('form_sub_label_'.$form_id, $form_name);
$this->Application->Phrases->AddCachedPhrase('la_description_in-portal:submissions:'.$form_id, $form_name.' Submissions');
$form_subsection['label'] = 'form_sub_label_'.$form_id;
$form_subsection['url']['form_id'] = $form_id;
$form_subsection['priority'] = $priority++;
$sections['in-portal:submissions:'.$form_id] = $form_subsection;
}
$this->Application->setUnitOption($event->Prefix, 'Sections', $sections);
}
function getForms()
{
$cache_key = 'forms[%FormSerial%]';
$forms = $this->Application->getCache($cache_key);
if ($forms === false) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT Title, FormId
FROM ' . TABLE_PREFIX . 'Forms
ORDER BY Title ASC';
$forms = $this->Conn->GetCol($sql, 'FormId');
$this->Application->setCache($cache_key, $forms);
}
return $forms;
}
/**
* 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)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
if ( $event->status == kEvent::erSUCCESS ) {
$this->OnCreateFormFields($event);
$this->_deleteSectionCache();
}
}
/**
* 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)
+ protected function OnMassDelete(kEvent &$event)
{
parent::OnMassDelete($event);
if ( $event->status == kEvent::erSUCCESS ) {
$this->_deleteSectionCache();
}
}
function _deleteSectionCache()
{
$reset_event = new kEvent('adm:OnResetSections');
$this->Application->HandleEvent($reset_event);
$this->Application->StoreVar('RefreshStructureTree', 1);
}
/**
* Dynamically fills custom data config
*
* @param kEvent $event
*/
function OnCreateFormFields(&$event)
{
$cur_fields = $this->Conn->Query('DESCRIBE '.TABLE_PREFIX.'FormSubmissions', 'Field');
$cur_fields = array_keys($cur_fields);
// keep all fields, that are not created on the fly (includes ones, that are added during customizations)
foreach ($cur_fields as $field_index => $field_name) {
if (!preg_match('/^fld_[\d]+/', $field_name)) {
unset($cur_fields[$field_index]);
}
}
$desired_fields = $this->Conn->GetCol('SELECT CONCAT(\'fld_\', FormFieldId) FROM '.TABLE_PREFIX.'FormFields ORDER BY FormFieldId');
$sql = array();
$fields_to_add = array_diff($desired_fields, $cur_fields);
foreach ($fields_to_add as $field) {
$field_expression = $field.' Text NULL';
$sql[] = 'ADD COLUMN '.$field_expression;
}
$fields_to_drop = array_diff($cur_fields, $desired_fields);
foreach ($fields_to_drop as $field) {
$sql[] = 'DROP COLUMN '.$field;
}
if ($sql) {
$query = 'ALTER TABLE '.TABLE_PREFIX.'FormSubmissions '.implode(', ', $sql);
$this->Conn->Query($query);
}
}
/**
* Enter description here...
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnFormSubmit(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$fields = explode(',',$this->Application->GetVar('fields'));
$required_fields = explode(',', $this->Application->GetVar('required_fields'));
$fields_params = $this->Application->GetVar('fields_params');
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
foreach ($fields as $field) {
$virtual_fields[$field] = Array ();
if ( in_array($field, $required_fields) ) {
$virtual_fields[$field]['required'] = 1;
}
$params = getArrayValue($fields_params, $field);
if ( $params !== false ) {
if ( getArrayValue($params, 'Type') == 'email' ) {
$virtual_fields[$field]['formatter'] = 'kFormatter';
$virtual_fields[$field]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
$virtual_fields[$field]['error_msgs'] = Array ('invalid_format' => '!la_invalid_email!');
}
if ( getArrayValue($params, 'Type') == 'file' ) {
$virtual_fields[$field]['formatter'] = 'kUploadFormatter';
$virtual_fields[$field]['upload_dir'] = '/uploads/sketches/';
}
}
}
$object->SetVirtualFields($virtual_fields);
$field_values = $this->getSubmittedFields($event);
$checkboxes = explode(',', $this->Application->GetVar('checkbox_fields')); // MailingList,In-Link,In-Newz,In-Bulletin
foreach ($checkboxes as $checkbox) {
if (isset($field_values[$checkbox])) {
$field_values[$checkbox] = 1;
}
else {
$field_values[$checkbox] = '0';
}
}
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
if ( $object->Validate() ) {
$event->redirect = $this->Application->GetVar('success_template');
$this->Application->EmailEventAdmin($this->Application->GetVar('email_event'));
$send_params = Array (
'to_email' => $field_values[$this->Application->GetVar('email_field')],
'to_name' => $field_values[$this->Application->GetVar('name_field')]
);
$this->Application->EmailEventUser($this->Application->GetVar('email_event'), null, $send_params);
if ( $field_values['MailingList'] ) {
$this->Application->StoreVar('SubscriberEmail', $field_values['Email']);
$this->Application->HandleEvent($sub_event, 'u:OnSubscribeUser', Array ('no_unsubscribe' => 1));
}
}
else {
$event->status = kEvent::erFAIL;
}
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->itemChanged($event);
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->itemChanged($event);
}
/**
* Occurs before item is changed
*
* @param kEvent $event
*/
function itemChanged(&$event)
{
$this->_validatePopSettings($event);
$this->_disableSecurityImage($event);
$this->_setRequired($event);
}
/**
* Validates POP3 settings (performs test connect)
*
* @param kEvent $event
*/
function _validatePopSettings(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$modes = Array ('Reply', 'Bounce');
$fields = Array ('Server', 'Port', 'Username', 'Password');
$changed_fields = array_keys( $object->GetChangedFields() );
foreach ($modes as $mode) {
$set = true;
$changed = false;
foreach ($fields as $field) {
$value = $object->GetDBField($mode . $field);
if (strlen( trim($value) ) == 0) {
$set = false;
break;
}
if (!$changed && in_array($mode . $field, $changed_fields)) {
$changed = true;
}
}
if ($set && $changed) {
// fields are set and at least on of them is changed
$connection_info = Array ();
foreach ($fields as $field) {
$connection_info[ strtolower($field) ] = $object->GetDBField($mode . $field);
}
$pop3_helper =& $this->Application->makeClass('POP3Helper', Array ($connection_info, 10));
/* @var $pop3_helper POP3Helper */
switch ( $pop3_helper->initMailbox(true) ) {
case 'socket':
$object->SetError($mode . 'Server', 'connection_failed');
break;
case 'login':
$object->SetError($mode . 'Username', 'login_failed');
break;
case 'list':
$object->SetError($mode . 'Server', 'message_listing_failed');
break;
}
}
}
}
/**
* Makes email communication fields required, when form uses email communication
*
* @param kEvent $event
*/
function _setRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required = $object->GetDBField('EnableEmailCommunication');
$fields = Array (
'ReplyFromName', 'ReplyFromEmail', 'ReplyServer', 'ReplyPort', 'ReplyUsername', 'ReplyPassword',
);
if ($required && $object->GetDBField('BounceEmail')) {
$bounce_fields = Array ('BounceEmail', 'BounceServer', 'BouncePort', 'BounceUsername', 'BouncePassword');
$fields = array_merge($fields, $bounce_fields);
}
$object->setRequired($fields, $required);
}
/**
* Don't use security image, when form requires login
*
* @param kEvent $event
*/
function _disableSecurityImage(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ($object->GetDBField('RequireLogin')) {
$object->SetDBField('UseSecurityImage', 0);
}
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
*/
function OnProcessReplies(&$event)
{
$this->_processMailbox($event, false);
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
*/
function OnProcessBouncedReplies(&$event)
{
$this->_processMailbox($event, true);
}
/**
* Queries pop3 server about new incoming mail
*
* @param kEvent $event
* @param bool $bounce_mode
*/
function _processMailbox(&$event, $bounce_mode = false)
{
$this->Application->SetVar('client_mode', 1);
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT *
FROM ' . $table_name . '
WHERE EnableEmailCommunication = 1';
$forms = $this->Conn->Query($sql, $id_field);
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
$field_prefix = $bounce_mode ? 'Bounce' : 'Reply';
foreach ($forms as $form_id => $form_info) {
$recipient_email = $bounce_mode ? $form_info['BounceEmail'] : $form_info['ReplyFromEmail'];
if (!$recipient_email) {
continue;
}
$mailbox_helper->process(
Array (
'server' => $form_info[$field_prefix . 'Server'],
'port' => $form_info[$field_prefix . 'Port'],
'username' => $form_info[$field_prefix . 'Username'],
'password' => $form_info[$field_prefix . 'Password']
),
Array (&$this, 'isValidRecipient'),
Array (&$this, 'processEmail'),
Array (
'recipient_email' => $recipient_email,
'bounce_mode' => $bounce_mode,
'form_info' => $form_info,
)
);
}
}
function isValidRecipient($params)
{
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
$recipients = $mailbox_helper->getRecipients();
$recipient_email = $params['recipient_email'];
$emails_found = preg_match_all('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $recipients, $all_emails);
if (is_array($all_emails)) {
for ($i = 0; $i < $emails_found; $i++) {
if ($all_emails[1][$i] == $recipient_email) {
// only read messages, that are addresses to submission reply email
return true;
}
}
}
// If this is a forwarded message - we drop all the other aliases and deliver only to the x-forward to address;
if (preg_match('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $mailbox_helper->headers['x-forward-to'], $get_to_email)) {
if ($get_to_email[1] == $recipient_email) {
// only read messages, that are addresses to submission reply email
return true;
}
}
return false;
}
function processEmail($params, &$fields_hash)
{
if ($params['bounce_mode']) {
// mark original message as bounced
$mailbox_helper =& $this->Application->recallObject('MailboxHelper');
/* @var $mailbox_helper MailboxHelper */
if (!array_key_exists('attachments', $mailbox_helper->parsedMessage)) {
// for now only parse bounces based on attachments, skip other bounce types
return false;
}
for ($i = 0; $i < count($mailbox_helper->parsedMessage['attachments']); $i++) {
$attachment =& $mailbox_helper->parsedMessage['attachments'][$i];
switch ($attachment['headers']['content-type']) {
case 'message/delivery-status':
// save as BounceInfo
$mime_decode_helper =& $this->Application->recallObject('MimeDecodeHelper');
/* @var $mime_decode_helper MimeDecodeHelper */
$charset = $mailbox_helper->parsedMessage[ $fields_hash['MessageType'] ][0]['charset'];
$fields_hash['Message'] = $mime_decode_helper->convertEncoding($charset, $attachment['data']);
break;
case 'message/rfc822':
// undelivered message
$fields_hash['Subject'] = $attachment['filename2'] ? $attachment['filename2'] : $attachment['filename'];
break;
}
}
}
if (!preg_match('/^(.*) #verify(.*)$/', $fields_hash['Subject'], $regs)) {
// incorrect subject, no verification code
$form_info = $params['form_info'];
if ($form_info['ProcessUnmatchedEmails'] && ($fields_hash['FromEmail'] != $params['recipient_email'])) {
// it's requested to convert unmatched emails to new submissions
$form_id = $form_info['FormId'];
$this->Application->SetVar('form_id', $form_id);
$sql = 'SELECT ' . $this->Application->getUnitOption('formsubs', 'IDField') . '
FROM ' . $this->Application->getUnitOption('formsubs', 'TableName') . '
WHERE MessageId = ' . $this->Conn->qstr($fields_hash['MessageId']);
$found = $this->Conn->GetOne($sql);
if ($found) {
// don't process same message twice
return false;
}
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'FormFields
WHERE (FormId = ' . $form_info['FormId'] . ') AND (EmailCommunicationRole > 0)';
$form_fields = $this->Conn->Query($sql, 'EmailCommunicationRole');
// what roles are filled from what fields
$role_mapping = Array (
SubmissionFormField::COMMUNICATION_ROLE_EMAIL => 'FromEmail',
SubmissionFormField::COMMUNICATION_ROLE_NAME => 'FromName',
SubmissionFormField::COMMUNICATION_ROLE_SUBJECT => 'Subject',
SubmissionFormField::COMMUNICATION_ROLE_BODY => 'Message',
);
$submission_fields = Array ();
foreach ($role_mapping as $role => $email_field) {
if (array_key_exists($role, $form_fields)) {
$submission_fields[ 'fld_' . $form_fields[$role]['FormFieldId'] ] = $fields_hash[$email_field];
}
}
if ($submission_fields) {
// remove object, because it's linked to single form upon creation forever
$this->Application->removeObject('formsubs.-item');
$form_submission =& $this->Application->recallObject('formsubs.-item', null, Array ('skip_autoload' => true));
/* @var $form_submission kDBItem */
// in case that other non-role mapped fields are required
$form_submission->IgnoreValidation = true;
$form_submission->SetDBFieldsFromHash($submission_fields);
$form_submission->SetDBField('FormId', $form_id);
$form_submission->SetDBField('MessageId', $fields_hash['MessageId']);
$form_submission->SetDBField('SubmissionTime_date', adodb_mktime());
$form_submission->SetDBField('SubmissionTime_time', adodb_mktime());
$form_submission->SetDBField('ReferrerURL', $this->Application->Phrase('la_Text_Email'));
return $form_submission->Create();
}
}
return false;
}
$sql = 'SELECT ' . $this->Application->getUnitOption('submission-log', 'IDField') . '
FROM ' . $this->Application->getUnitOption('submission-log', 'TableName') . '
WHERE MessageId = ' . $this->Conn->qstr($fields_hash['MessageId']);
$found = $this->Conn->GetOne($sql);
if ($found) {
// don't process same message twice
return false;
}
$reply_to =& $this->Application->recallObject('submission-log.-reply-to', null, Array ('skip_autoload' => true));
/* @var $reply_to kDBItem */
$reply_to->Load($regs[2], 'VerifyCode');
if (!$reply_to->isLoaded()) {
// fake verification code OR feedback, containing submission log was deleted
return false;
}
if ($params['bounce_mode']) {
// mark original message as bounced
$reply_to->SetDBField('BounceInfo', $fields_hash['Message']);
$reply_to->SetDBField('BounceDate_date', TIMENOW);
$reply_to->SetDBField('BounceDate_time', TIMENOW);
$reply_to->SetDBField('SentStatus', SUBMISSION_LOG_BOUNCE);
$reply_to->Update();
return true;
}
$reply =& $this->Application->recallObject('submission-log.-reply', null, Array ('skip_autoload' => true));
/* @var $reply kDBItem */
$reply->SetDBFieldsFromHash($fields_hash);
$reply->SetDBField('ReplyTo', $reply_to->GetID());
$reply->SetDBField('FormSubmissionId', $reply_to->GetDBField('FormSubmissionId'));
$reply->SetDBField('ToEmail', $params['recipient_email']);
$reply->SetDBField('Subject', $regs[1]); // save subject without verification code
$reply->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
return $reply->Create();
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/forms/submission_log/submission_log_eh.php
===================================================================
--- branches/5.2.x/core/units/forms/submission_log/submission_log_eh.php (revision 15064)
+++ branches/5.2.x/core/units/forms/submission_log/submission_log_eh.php (revision 15065)
@@ -1,707 +1,710 @@
<?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 SubmissionLogEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnResendReply' => Array ('subitem' => 'add|edit'),
'OnSaveDraft' => Array ('subitem' => 'add|edit'),
'OnUseDraft' => Array ('subitem' => 'add|edit'),
'OnDeleteDraft' => Array ('subitem' => 'add|edit'),
'OnProcessBounceMail' => Array ('subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
$section = $event->getSection();
$form_id = $this->Application->GetVar('form_id');
if ( $form_id ) {
// copy form_id to env to be passed info upload links
$this->Application->SetVar($event->getPrefixSpecial() . '_form_id', $form_id);
}
else {
$form_id = $this->Application->GetVar($event->getPrefixSpecial() . '_form_id');
}
$event->setEventParam('PermSection', $section . ':' . $form_id);
return parent::CheckPermission($event);
}
/**
* Prepares new kDBItem object
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$form_submission =& $this->Application->recallObject('formsubs');
/* @var $form_submission kDBItem */
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($form_submission);
/* @var $form kDBItem */
$from_email = $form->GetDBField('ReplyFromEmail');
$to_email = $form_submission_helper->getFieldByRole($form_submission, SubmissionFormField::COMMUNICATION_ROLE_EMAIL);
- if ($this->Application->GetVar('client_mode')) {
+ if ( $this->Application->GetVar('client_mode') ) {
// debug code for sending email from client
$object->SetDBField('FromEmail', $to_email);
$object->SetDBField('ToEmail', $from_email);
}
else {
$object->SetDBField('FromEmail', $from_email);
$object->SetDBField('ToEmail', $to_email);
}
$object->SetDBField('Cc', $form->GetDBField('ReplyCc'));
$object->SetDBField('Bcc', $form->GetDBField('ReplyBcc'));
$ids = $this->StoreSelectedIDs($event);
- if ($ids) {
+ if ( $ids ) {
$org_message =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
/* @var $org_message kDBItem */
- $org_message->Load( array_shift($ids) );
+ $org_message->Load(array_shift($ids));
// client could reply from different email, so compare to admin email!
- if ($org_message->GetDBField('ToEmail') == $from_email) {
+ if ( $org_message->GetDBField('ToEmail') == $from_email ) {
// can reply only to client email, not own :)
// transform subject
$message_subject = $org_message->GetDBField('Subject');
- if ($message_subject) {
+ if ( $message_subject ) {
$object->SetDBField('Subject', $this->_transformSubject($message_subject, 'Re'));
}
// add signature
$message_body = $form->GetDBField('ReplyMessageSignature');
- if ($org_message->GetDBField('Message')) {
+ if ( $org_message->GetDBField('Message') ) {
// add replied marks
$message_body .= '> ' . preg_replace('/([\r]*\n)/', '\\1> ', $org_message->GetDBField('Message'));
}
$object->SetDBField('ToEmail', $org_message->GetDBField('FromEmail')); // user client's email from reply
$object->SetDBField('Message', $message_body);
$object->SetDBField('ReplyTo', $org_message->GetID());
}
}
else {
$sql = 'SELECT COUNT(*)
FROM ' . $object->TableName . '
WHERE FormSubmissionId = ' . $form_submission->GetID();
$replies_found = $this->Conn->GetOne($sql);
- if (!$replies_found) {
+ if ( !$replies_found ) {
// 1st message from admin -> quote subject & text from feedback
$message_subject = $form_submission_helper->getFieldByRole($form_submission, SubmissionFormField::COMMUNICATION_ROLE_SUBJECT, true);
- if ($message_subject) {
+ if ( $message_subject ) {
$object->SetDBField('Subject', $this->_transformSubject($message_subject, 'Re'));
}
// add signature
$message_body = $form->GetDBField('ReplyMessageSignature');
// add replied marks
$original_message_body = $form_submission_helper->getFieldByRole($form_submission, SubmissionFormField::COMMUNICATION_ROLE_BODY);
- if ($original_message_body) {
+ if ( $original_message_body ) {
$message_body .= '> ' . preg_replace('/([\r]*\n)/', '\\1> ', $original_message_body);
}
$object->SetDBField('Message', $message_body);
}
}
$this->clearSelectedIDs($event);
}
/**
* Parses $search string in subject and reformats it
* Used for replying and forwarding
*
* @param string $subject
* @param string $search
* @return string
*/
function _transformSubject($subject, $search = 'Re')
{
$regex = '/'.$search.'(\[([\d]+)\]){0,1}:/i';
preg_match_all($regex, $subject, $regs);
if ($regs[2]) {
$reply_count = 0; // reply count without numbers (equals to "re[1]")
$max_reply_number = 0; // maximal reply number
sort($regs[2], SORT_NUMERIC); // sort ascending (non-numeric replies first)
foreach ($regs[2] as $match) {
if (!$match) {
// found "re:"
$reply_count++;
}
elseif ($match > $max_reply) {
// found "re:[number]"
$max_reply_number = $match;
}
}
return $search.'['.($reply_count + $max_reply_number + 1).']: '.trim(preg_replace($regex, '', $subject));
}
return $search.': '.$subject;
}
/**
* Resends reply, that was not sent last time
*
* @param kEvent $event
*/
function OnResendReply(&$event)
{
$ids = $this->StoreSelectedIDs($event);
if (!$ids) {
return ;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$sql = 'SELECT f.ReplyFromEmail, sl.' . $object->IDField . '
FROM ' . $object->TableName . ' sl
JOIN ' . $this->Application->getUnitOption('formsubs', 'TableName') . ' fs ON fs.FormSubmissionId = sl.FormSubmissionId
JOIN ' . $this->Application->getUnitOption('form', 'TableName') . ' f ON f.FormId = fs.FormId
WHERE sl.' . $object->IDField . ' IN (' . implode(',', $ids) . ')';
$reply_emails = $this->Conn->GetCol($sql, $object->IDField);
foreach ($ids as $id) {
$object->Load($id);
// allow to send messages, that were successfully sended before :(
if (($object->GetDBField('ToEmail') != $reply_emails[$id]) && ($object->GetDBField('SentStatus') != SUBMISSION_LOG_SENT)) {
$object->SetOriginalField('SentStatus', 0); // reset sent status to update sent date automatically
$this->_sendEmail($object); // resend email here
}
}
$this->clearSelectedIDs($event);
if (!$this->Application->GetVar('from_list')) {
$event->SetRedirectParam('opener', 'u');
}
}
/**
* Updates last operation dates for log record
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->_validateRecipients($event);
$this->_updateStatusDates($event);
}
/**
* Updates last operation dates for log record
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_validateRecipients($event);
$this->_updateStatusDates($event);
}
/**
* Validates email recipients
*
* @param kEvent $event
*/
function _validateRecipients(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$cc = $object->GetDBField('Cc');
if ($cc && ($esender->GetRecipients($cc) === false)) {
$object->SetError('Cc', 'invalid_format');
}
$bcc = $object->GetDBField('Bcc');
if ($bcc && ($esender->GetRecipients($bcc) === false)) {
$object->SetError('Bcc', 'invalid_format');
}
}
/**
* Generates verification code and sets it inside sent message
*
* @param kDBItem $object
* @return string
*/
function _generateVerificationCode(&$object)
{
$code = Array (
$object->GetDBField('FromEmail'),
$object->GetDBField('ToEmail'),
$object->GetID(),
microtime(true)
);
$object->SetDBField('VerifyCode', md5( implode('-', $code) ));
}
/**
* Sends email based on fields from given submission-log record
*
* @param kDBItem $object
*/
function _sendEmail(&$object)
{
if ($this->Application->GetVar('client_mode')) {
return ;
}
if (!$object->GetDBField('VerifyCode')) {
$this->_generateVerificationCode($object);
}
$form_submission =& $this->_getFormSubmission($object);
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($form_submission);
$send_params = Array (
'from_name' => $form->GetDBField('ReplyFromName'),
'from_email' => $object->GetDBField('FromEmail'),
'to_email' => $object->GetDBField('ToEmail'),
'subject' => $object->GetDBField('Subject'),
'message' => $object->GetDBField('Message'),
);
$to_name = $form_submission_helper->getFieldByRole($form_submission, SubmissionFormField::COMMUNICATION_ROLE_NAME);
if ($to_name) {
$send_params['to_name'] = $to_name;
}
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$esender->SetReturnPath( $form->GetDBField('BounceEmail') );
if ($object->GetDBField('Cc')) {
$recipients = $esender->GetRecipients( $object->GetDBField('Cc') );
foreach ($recipients as $recipient_info) {
$esender->AddCc($recipient_info['Email'], $recipient_info['Name']);
}
}
if ($object->GetDBField('Bcc')) {
$recipients = $esender->GetRecipients( $object->GetDBField('Bcc') );
foreach ($recipients as $recipient_info) {
$esender->AddBcc($recipient_info['Email'], $recipient_info['Name']);
}
}
if ($object->GetDBField('Attachment')) {
$attachments = explode('|', $object->GetField('Attachment', 'file_paths'));
foreach ($attachments as $attachment) {
$esender->AddAttachment($attachment);
}
}
$this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.TO.USER', null, $send_params);
// mark as sent after sending is finished
$object->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
// reset bounce status before (re-)sending
$object->SetDBField('BounceInfo', NULL);
$object->SetDBField('BounceDate_date', NULL);
$object->SetDBField('BounceDate_time', NULL);
if ($object->GetDBField('DraftId')) {
$temp_handler =& $this->Application->recallObject('draft_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems('draft', '', Array ($object->GetDBField('DraftId')));
$object->SetDBField('DraftId', 0);
}
$object->Update();
}
/**
* Sends new email after log record was created
* Updates last update time for submission
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$this->_sendEmail($object); // send email
$this->_updateSubmission($event);
$reply_to = $object->GetDBField('ReplyTo');
if ( !$reply_to ) {
$reply_to = $this->_getLastMessageId($event, !$this->Application->GetVar('client_mode'));
}
if ( $reply_to ) {
// this is reply to other message -> mark it as replied
$org_message =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
/* @var $org_message kDBItem */
$org_message->Load($reply_to);
$org_message->SetDBField('ReplyStatus', SUBMISSION_LOG_REPLIED);
$org_message->Update();
}
if ( $this->Application->GetVar('client_mode') ) {
// new reply from client received -> send notification about it
$this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.FROM.USER');
}
}
/**
* Returns last message id (client OR admin)
*
* @param kEvent $event
* @param bool $from_client
* @return int
*/
function _getLastMessageId(&$event, $from_client = false)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$form_submission =& $this->_getFormSubmission($object);
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($form_submission);
$reply_email = $form->GetDBField('ReplyFromEmail');
$sql = 'SELECT MAX(' . $object->IDField . ')
FROM ' . $object->TableName . '
WHERE (FormSubmissionId = ' . $form_submission->GetID() . ') AND (ToEmail' . ($from_client ? ' = ' : ' <> ') . $this->Conn->qstr($reply_email) . ')';
return $this->Conn->GetOne($sql);
}
/**
* Updates last update time for submission
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$this->_updateSubmission($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// send out email event to admin for bouncing
- if ( $object->GetOriginalField('SentStatus') != $object->GetDBField('SentStatus')
- && $object->GetDBField('SentStatus') == SUBMISSION_LOG_BOUNCE ) {
+ $sent_status = $object->GetDBField('SentStatus');
+ if ( $object->GetOriginalField('SentStatus') != $sent_status && $sent_status == SUBMISSION_LOG_BOUNCE ) {
$this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.FROM.USER.BOUNCED');
}
}
/**
* Sets last sent/reply dates based on field changes in log record
*
* @param kEvent $event
*/
function _updateStatusDates(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$now = adodb_mktime();
$sent_status = $object->GetDBField('SentStatus');
if (($event->Special != 'merge') && ($sent_status == SUBMISSION_LOG_SENT) && ($sent_status != $object->GetOriginalField('SentStatus'))) {
// sent status was set
$object->SetDBField('SentOn_date', $now);
$object->SetDBField('SentOn_time', $now);
}
$reply_status = $object->GetDBField('ReplyStatus');
if (($reply_status == SUBMISSION_LOG_REPLIED) && ($reply_status != $object->GetOriginalField('ReplyStatus'))) {
// sent status was set
$object->SetDBField('RepliedOn_date', $now);
$object->SetDBField('RepliedOn_time', $now);
}
}
/**
* Returns form submission by given event of submission log
*
* @param kDBItem $object
* @return kDBItem
*/
function &_getFormSubmission(&$object)
{
$submission_id = $object->GetDBField('FormSubmissionId');
$form_submission =& $this->Application->recallObject('formsubs.-item', null, Array ('skip_autoload' => true));
/* @var $form_submission kDBItem */
if ($form_submission->isLoaded() && ($form_submission->GetID() == $submission_id)) {
// already loaded AND has needed id
return $form_submission;
}
$form_submission->Load($submission_id);
return $form_submission;
}
/**
* Sets last updated field for form submission
*
* @param kEvent $event
*/
function _updateSubmission(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$form_submission =& $this->_getFormSubmission($object);
// 1. set last updated
$last_updated = max ($object->GetDBField('SentOn'), $object->GetDBField('RepliedOn'));
if ($form_submission->GetDBField('LastUpdatedOn') < $last_updated) {
// don't set smaller last update, that currenly set
$form_submission->SetDBField('LastUpdatedOn_date', $last_updated);
$form_submission->SetDBField('LastUpdatedOn_time', $last_updated);
}
// 2. update submission status
$form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
/* @var $form_submission_helper FormSubmissionHelper */
$form =& $form_submission_helper->getForm($form_submission);
$client_responce = $form->GetDBField('ReplyFromEmail') == $object->GetDBField('ToEmail');
$replied = $object->GetDBField('ReplyStatus') == SUBMISSION_LOG_REPLIED;
if (!$client_responce && !$replied) {
// admin sends new email to client
$form_submission->SetDBField('LogStatus', SUBMISSION_REPLIED);
}
elseif ($client_responce) {
// client email becomes replied OR receiving new unreplied email from client
$form_submission->SetDBField('LogStatus', $replied ? SUBMISSION_REPLIED : SUBMISSION_NEW_EMAIL);
}
if ($object->GetDBField('SentStatus') == SUBMISSION_LOG_BOUNCE) {
// propagate bounce status from reply
$form_submission->SetDBField('LogStatus', SUBMISSION_BOUNCE);
}
$form_submission->Update();
}
/**
* Saves current unsent message as draft
*
* @param kEvent $event
*/
function OnSaveDraft(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
/* @var $draft kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
foreach ($items_info as $id => $field_values) {
$object->setID($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$load_keys = Array (
'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
'CreatedById' => $this->Application->RecallVar('user_id'),
);
// get existing draft for given submission and user
$draft->Load($load_keys);
$draft->SetDBField('Message', $object->GetDBField('Message'));
if ($draft->isLoaded()) {
$draft->Update();
}
else {
$draft->SetDBFieldsFromHash($load_keys);
$draft->Create();
}
}
}
$this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
$event->SetRedirectParam('opener', 'u');
}
/**
* Uses found draft instead of submission reply body
*
* @param kEvent $event
*/
function OnUseDraft(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
/* @var $draft kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
foreach ($items_info as $id => $field_values) {
$object->setID($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$load_keys = Array (
'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
'CreatedById' => $this->Application->RecallVar('user_id'),
);
// get existing draft for given submission and user
$draft->Load($load_keys);
if ($draft->isLoaded()) {
$object->SetDBField('Message', $draft->GetDBField('Message'));
$object->SetDBField('DraftId', $draft->GetID());
}
}
}
$this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
$event->redirect = false;
}
/**
* Deletes draft, that matches given user and form submission
*
* @param kEvent $event
*/
function OnDeleteDraft(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
/* @var $draft kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
foreach ($items_info as $id => $field_values) {
$object->setID($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$object->SetDBField('DraftId', 0);
$load_keys = Array (
'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
'CreatedById' => $this->Application->RecallVar('user_id'),
);
// get existing draft for given submission and user
$draft->Load($load_keys);
if ($draft->isLoaded()) {
$temp_handler =& $this->Application->recallObject('draft_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems('draft', '', Array ($draft->GetID()));
}
}
}
$this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
$event->redirect = false;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/config_search/config_search_event_handler.php
===================================================================
--- branches/5.2.x/core/units/config_search/config_search_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/config_search/config_search_event_handler.php (revision 15065)
@@ -1,154 +1,154 @@
<?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 ConfigSearchEventHandler extends kDBEventHandler {
/**
* Changes permission section to one from REQUEST, not from config
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
$module = $this->Application->GetVar('module');
$main_prefix = $this->Application->findModule('Name', $module, 'Var');
$section = $this->Application->getUnitOption($main_prefix.'.search', 'PermSection');
$event->setEventParam('PermSection', $section);
return parent::CheckPermission($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
// show only items that belong to selected module
$module = $this->Application->GetVar('module');
$object->addFilter('module_filter', '%1$s.ModuleName = ' . $this->Conn->qstr($module));
// don't show disabled search items
$object->addFilter('active_filter', '%1$s.SimpleSearch <> -1');
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return ;
}
parent::OnUpdate($event);
$conf_update = new kEvent('conf:OnUpdate');
$conf_update->redirect = false;
$this->Application->HandleEvent($conf_update);
$event->SetRedirectParam('opener', 's');
// keeps module and section in REQUEST to ensure, that last admin template will work
$event->SetRedirectParam('module', $this->Application->GetVar('module'));
$event->SetRedirectParam('module_key', $this->Application->GetVar('module_key'));
$event->SetRedirectParam('section', $this->Application->GetVar('section'));
}
/**
* Cancels kDBItem Editing/Creation
*
* @param kEvent $event
* @return void
* @access protected
*/
- function OnCancel(&$event)
+ protected function OnCancel(kEvent &$event)
{
parent::OnCancel($event);
$event->SetRedirectParam('opener', 's');
}
/**
* [HOOK] Creates search config record corresponding to custom field, that was just created
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCreateCustomField(&$event)
{
$custom_field =& $event->MasterEvent->getObject();
/* @var $custom_field kDBItem */
if ( $custom_field->GetDBField('Type') == 6 || $custom_field->GetDBField('IsSystem') == 1 ) {
// user & system custom fields are not searchable
return ;
}
$object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$custom_id = $custom_field->GetID();
if ( !$object->isLoaded() || ($object->GetDBField('CustomFieldId') != $custom_id) ) {
$object->Load($custom_id, 'CustomFieldId');
}
$cf_search = Array ();
$element_type = $custom_field->GetDBField('ElementType');
$cf_search['DisplayOrder'] = $custom_field->GetDBField('DisplayOrder');
$cf_search['FieldType'] = $element_type;
$cf_search['DisplayName'] = $custom_field->GetDBField('FieldLabel');
$cf_search['FieldName'] = $custom_field->GetDBField('FieldName');
$cf_search['Description'] = $custom_field->GetDBField('Prompt');
$cf_search['ConfigHeader'] = $custom_field->GetDBField('Heading'); // 'la_Text_CustomFields';
$cf_search['SimpleSearch'] = in_array($element_type, Array ('text', 'range', 'select', 'multiselect')) ? 1 : 0;
$cf_search['TableName'] = 'CustomFields';
$sql = 'SELECT Module
FROM ' . TABLE_PREFIX . 'ItemTypes
WHERE ItemType = ' . $custom_field->GetDBField('Type');
$cf_search['ModuleName'] = $this->Conn->GetOne($sql);
$object->SetFieldsFromHash($cf_search);
$object->SetDBField('CustomFieldId', $custom_id);
if ( $object->isLoaded() ) {
$object->Update();
}
else {
$object->Create();
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/relationship/relationship_event_handler.php
===================================================================
--- branches/5.2.x/core/units/relationship/relationship_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/relationship/relationship_event_handler.php (revision 15065)
@@ -1,297 +1,300 @@
<?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 RelationshipEventHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnProcessSelected' => Array ('subitem' => 'add|edit')
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Initializes new relation
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$table_info = $object->getLinkedInfo();
$object->SetDBField('SourceId', $table_info['ParentId']);
$source_itemtype = $this->Application->getUnitOption($table_info['ParentPrefix'], 'ItemType');
$object->SetDBField('SourceType', $source_itemtype);
$object->SetDBField('TargetId', $this->Application->GetVar('target_id'));
$object->SetDBField('TargetType', $this->Application->GetVar('target_type'));
$this->OnAfterItemLoad($event);
}
/**
* Add new relation
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$dst_field = $this->Application->RecallVar('dst_field');
if ( $dst_field == 'TargetId' ) {
// prepare target_id & target_type
$object =& $event->getObject(Array ('skip_autoload' => true));
$target_id = 0;
$target_prefix = false;
$selected_ids = $this->Application->GetVar('selected_ids');
foreach ($selected_ids as $selected_prefix => $target_id) {
if ( $target_id > 0 ) {
$target_prefix = $selected_prefix;
break;
}
}
if ( !$target_prefix ) {
$event->SetRedirectParam('opener', 'u');
return;
}
$sql = 'SELECT ResourceId
FROM ' . $this->Application->getUnitOption($target_prefix, 'TableName') . '
WHERE ' . $this->Application->getUnitOption($target_prefix, 'IDField') . ' IN (' . $target_id . ')';
$target_id = $this->Conn->GetOne($sql);
$target_type = $this->Application->getUnitOption($target_prefix, 'ItemType');
// don't add same relation twice
$table_info = $object->getLinkedInfo();
$sql = 'SELECT TargetId
FROM ' . $object->TableName . '
WHERE (SourceId = ' . $table_info['ParentId'] . ') AND (TargetId = ' . $target_id . ')';
$duplicate_relation = $this->Conn->GetOne($sql) == $target_id;
$event->SetRedirectParam('opener', 'u');
if ( !$duplicate_relation ) {
// place correct template in opener stack
$source_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
$template = $this->Application->getUnitOption($source_prefix, 'AdminTemplatePath') . '/relations_edit';
$redirect_params = Array (
$event->Prefix . '_event' => 'OnNew',
'target_id' => $target_id,
'm_opener' => 's',
'target_type' => $target_type,
'pass' => 'all,' . $event->Prefix,
);
$this->Application->EventManager->openerStackPush($template, $redirect_params);
}
}
else {
$event->SetRedirectParam('opener', 'u');
}
}
/**
* Set ItemName & ItemType virtual fields based on loaded item data
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$sql = 'SELECT Prefix
FROM ' . TABLE_PREFIX . 'ItemTypes
WHERE ItemType = ' . $object->GetDBField('TargetType');
$target_prefix = $this->Conn->GetOne($sql);
$title_field = $this->getTitleField($target_prefix);
$title_phrase = $this->Application->getUnitOption($target_prefix, 'TitlePhrase');
$sql = 'SELECT ' . $title_field . '
FROM ' . $this->Application->getUnitOption($target_prefix, 'TableName') . '
WHERE ResourceId = ' . $object->GetDBField('TargetId');
$object->SetDBField('ItemName', $this->Conn->GetOne($sql));
$object->SetDBField('ItemType', $this->Application->Phrase($title_phrase));
}
/**
* Creates needed sql query to load list,
* if no query is defined in config for
* special requested, then use default
* query
*
* @param kEvent $event
+ * @return string
* @access protected
*/
- function ListPrepareQuery(&$event)
+ protected function ListPrepareQuery(kEvent &$event)
{
return $this->BaseQuery($event, 'ListSQLs');
}
/**
* Creates needed sql query to load item,
* if no query is defined in config for
- * special requested, then use default
- * query
+ * special requested, then use list query
*
* @param kEvent $event
+ * @return string
* @access protected
*/
- function ItemPrepareQuery(&$event)
+ protected function ItemPrepareQuery(kEvent &$event)
{
return $this->BaseQuery($event, 'ItemSQLs');
}
/**
* Get item name & type based on relation type & modules installed
*
* @param kEvent $event
* @param string $sql_field
*/
function BaseQuery(&$event, $sql_field)
{
$sqls = $this->Application->getUnitOption($event->Prefix,$sql_field);
$sql = isset($sqls[$event->Special]) ? $sqls[$event->Special] : $sqls[''];
$configs = $this->extractModulesInfo();
// 2. build sql based on information queried
$sql_templates['ItemName'] = 'IFNULL(%s.%s,\' \')';
$sql_templates['TableJoin'] = 'LEFT JOIN %1$s ON %1$s.ResourceId = rel.TargetId';
$sql_templates['TargetName'] = 'IF(rel.TargetType = %s, \'%s\', %s)';
$sql_parts = Array();
$sql_parts['TargetName'] = "''";
foreach ($configs as $prefix => $config_data) {
$title_field = $this->getTitleField($prefix);
$sql_parts['ItemName'][] = sprintf($sql_templates['ItemName'], $config_data['TableName'], $title_field);
$sql_parts['TableJoin'][] = sprintf($sql_templates['TableJoin'], $config_data['TableName']);
$sql_parts['TargetName'] = sprintf( $sql_templates['TargetName'],
$config_data['ItemType'],
'!'.$config_data['TitlePhrase'].'!',
$sql_parts['TargetName']);
$sql_parts['TargetName'] = str_replace('rel','%1$s',$sql_parts['TargetName']);
}
$object =& $event->getObject();
$vars = Array('#ITEM_NAMES#', '#ITEM_TYPES#');
$replacements = Array( implode(', ',$sql_parts['ItemName']), $sql_parts['TargetName'] );
$calculated_fields = $object->getCalculatedFields();
foreach ($calculated_fields as $field_name => $field_expression) {
$calculated_fields[$field_name] = str_replace($vars, $replacements, $field_expression);
}
$object->setCalculatedFields($calculated_fields);
$sql = str_replace('#ITEM_JOIN#', implode(' ',$sql_parts['TableJoin']), $sql);
$sql = str_replace('rel.','%1$s.',$sql);
return $sql;
}
/**
* Convert TitleField field of kMultiLanguage formatter used for it
*
* @param string $prefix
* @return string
*/
function getTitleField($prefix)
{
$lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
$title_field = $this->Application->getUnitOption($prefix, 'TitleField');
$field_options = $this->Application->getUnitOption($prefix.'.'.$title_field, 'Fields');
$formatter_class = isset($field_options['formatter']) ? $field_options['formatter'] : '';
if ($formatter_class == 'kMultiLanguage' && !isset($field_options['master_field'])) {
$title_field = $lang_prefix.$title_field;
}
return $title_field;
}
/**
* Get configs from modules installed
*
* @return Array
* @access private
*/
function extractModulesInfo()
{
// get installed modules & their config info
// maybe we should leave only prefixes, that have "view" permission
$configs = Array();
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$prefix = $module_data['Var'];
if ($prefix == 'm') {
$prefix = 'c';
}
if (!$this->Application->prefixRegistred($prefix)) continue;
$configs[$prefix] = $this->Application->getUnitOptions($prefix);
if($configs[$prefix] === false) unset($configs[$prefix]);
if(!isset($configs[$prefix]['CatalogItem']) || !$configs[$prefix]['CatalogItem']) unset($configs[$prefix]);
}
return $configs;
}
/**
* Deletes relations to hooked item from other items
*
* @param kEvent $event
*/
function OnDeleteForeignRelations(&$event)
{
$main_object =& $event->MasterEvent->getObject();
/* @var $main_object kDBItem */
$sql = 'DELETE FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE TargetId = ' . $main_object->GetDBField('ResourceId');
$this->Conn->Query($sql);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/phrases/phrases_event_handler.php
===================================================================
--- branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/phrases/phrases_event_handler.php (revision 15065)
@@ -1,457 +1,468 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class PhrasesEventHandler extends kDBEventHandler
{
/**
* Apply some special processing to object 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, kEvent &$event)
{
// don't call parent
if ( $event->Special == 'import' || $event->Special == 'export' ) {
$this->RemoveRequiredFields($object);
$object->setRequired(Array ('LangFile', 'PhraseType', 'Module'));
// allow multiple phrase types to be selected during import/export
$object->SetFieldOption('PhraseType', 'type', 'string');
}
}
/**
* Allow to create phrases from front end in debug mode with DBG_PHRASES constant set
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( !$this->Application->isAdmin && $this->Application->isDebugMode(false) && kUtil::constOn('DBG_PHRASES') ) {
$allow_events = Array ('OnCreate', 'OnUpdate');
if ( in_array($event->Name, $allow_events) ) {
return true;
}
}
return parent::CheckPermission($event);
}
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnItemBuild' => Array('self' => true, 'subitem' => true),
'OnPreparePhrase' => Array('self' => true, 'subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Prepares phrase for translation
*
* @param kEvent $event
*/
function OnPreparePhrase(&$event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if (!$label) {
return ;
}
// we got label, try to get it's ID then if any
$phrase_id = $this->_getPhraseId($label);
if ($phrase_id) {
$event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $phrase_id);
$event->SetRedirectParam('pass', 'm,' . $event->getPrefixSpecial());
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->SetRedirectParam('next_template', $next_template);
}
}
else {
$event->CallSubEvent('OnNew');
}
if ($this->Application->GetVar('simple_mode')) {
$event->SetRedirectParam('simple_mode', 1);
}
}
function _getPhraseId($phrase)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($this->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Sets phrase type based on place where it's created (to display on form only)
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnPreCreate(&$event)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$this->_setPhraseModule($object);
}
/**
* Forces new label in case if issued from get link
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
if ( $label ) {
// phrase is created in language, used to display phrases
$object->SetDBField('Phrase', $label);
$object->SetDBField('PhraseType', $this->_getPhraseType($label)); // to show on form
$object->SetDBField('PrimaryTranslation', $this->_getPrimaryTranslation($label));
}
$this->_setPhraseModule($object);
if ( $event->Special == 'export' || $event->Special == 'import' ) {
$object->SetDBField('PhraseType', '|0|1|2|');
$object->SetDBField('Module', '|' . implode('|', array_keys($this->Application->ModuleInfo)) . '|');
}
}
/**
* Returns given phrase translation on primary language
*
* @param string $phrase
* @return string
* @access protected
*/
protected function _getPrimaryTranslation($phrase)
{
$sql = 'SELECT l' . $this->Application->GetDefaultLanguageId() . '_Translation
FROM ' . $this->Application->getUnitOption($this->Prefix, 'TableName') . '
WHERE PhraseKey = ' . $this->Conn->qstr( mb_strtoupper($phrase) );
return $this->Conn->GetOne($sql);
}
/**
* Sets new phrase module
*
* @param kDBItem $object
* @return void
* @access protected
*/
protected function _setPhraseModule(&$object)
{
$last_module = $this->Application->GetVar('last_module');
if ( $last_module ) {
$object->SetDBField('Module', $last_module);
}
}
/**
* Forces create to use live table
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCreate(&$event)
+ protected function OnCreate(kEvent &$event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
- if ($this->Application->GetVar('m_lang') != $this->Application->GetVar('lang_id')) {
+ if ( $this->Application->GetVar('m_lang') != $this->Application->GetVar('lang_id') ) {
$object->SwitchToLive();
}
$this->returnToOriginalTemplate($event);
}
parent::OnCreate($event);
}
/**
* Redirects to original template after phrase is being update
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent &$event)
{
if ( $this->Application->GetVar($event->Prefix . '_label') ) {
$this->returnToOriginalTemplate($event);
}
parent::OnUpdate($event);
}
/**
* Returns to original template after phrase adding/editing
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function returnToOriginalTemplate(&$event)
+ protected function returnToOriginalTemplate(kEvent &$event)
{
$next_template = $this->Application->GetVar('next_template');
- if ($next_template) {
+ if ( $next_template ) {
$event->redirect = $next_template;
$event->SetRedirectParam('opener', 's');
}
}
/**
* Set last change info, when phrase is created
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$primary_language_id = $this->Application->GetDefaultLanguageId();
if ( !$object->GetDBField('l' . $primary_language_id . '_Translation') ) {
// no translation on primary language -> try to copy from other language
$src_languages = Array ('lang_id', 'm_lang'); // editable language, theme language
foreach ($src_languages as $src_language) {
$src_language = $this->Application->GetVar($src_language);
$src_value = $src_language ? $object->GetDBField('l' . $src_language . '_Translation') : false;
if ( $src_value ) {
$object->SetDBField('l' . $primary_language_id . '_Translation', $src_value);
break;
}
}
}
$this->_phraseChanged($event);
}
/**
* Update last change info, when phrase is updated
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_phraseChanged($event);
}
/**
* Set's phrase key and last change info, used for phrase updating and loading
*
* @param kEvent $event
*/
function _phraseChanged(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$label = $object->GetDBField('Phrase');
$object->SetDBField('PhraseKey', mb_strtoupper($label));
$object->SetDBField('PhraseType', $this->_getPhraseType($label));
if ( $this->translationChanged($object) ) {
$object->SetDBField('LastChanged_date', adodb_mktime() );
$object->SetDBField('LastChanged_time', adodb_mktime() );
$object->SetDBField('LastChangeIP', $_SERVER['REMOTE_ADDR']);
}
$this->Application->Session->SetCookie('last_module', $object->GetDBField('Module'));
}
/**
* Returns phrase type, that corresponds given phrase label
*
* @param string $label
* @return int
* @access protected
*/
protected function _getPhraseType($label)
{
$phrase_type_map = Array (
'LU' => Language::PHRASE_TYPE_FRONT,
'LA' => Language::PHRASE_TYPE_ADMIN,
'LC' => Language::PHRASE_TYPE_COMMON
);
$label = mb_strtoupper($label);
$label_prefix = substr($label, 0, 2);
return isset($phrase_type_map[$label_prefix]) ? $phrase_type_map[$label_prefix] : Language::PHRASE_TYPE_COMMON;
}
/**
* Checks, that at least one of phrase's translations was changed
*
* @param kDBItem $object
* @return bool
*/
function translationChanged(&$object)
{
$changed_fields = array_keys( $object->GetChangedFields() );
$translation_fields = Array ('Translation', 'HintTranslation', 'ColumnTranslation');
foreach ($changed_fields as $changed_field) {
$changed_field = preg_replace('/^l[\d]+_/', '', $changed_field);
if ( in_array($changed_field, $translation_fields) ) {
return true;
}
}
return false;
}
/**
* Changes default module to custom (when available)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
if ($this->Application->findModule('Name', 'Custom')) {
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Module']['default'] = 'Custom';
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
// make sure, that PrimaryTranslation column always refrers to primary language column
$language_id = $this->Application->GetVar('lang_id');
if (!$language_id) {
$language_id = $this->Application->GetVar('m_lang');
}
$primary_language_id = $this->Application->GetDefaultLanguageId();
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
foreach ($calculated_fields[''] as $field_name => $field_expression) {
$field_expression = str_replace('%5$s', $language_id, $field_expression);
$field_expression = str_replace('%4$s', $primary_language_id, $field_expression);
$calculated_fields[''][$field_name] = $field_expression;
}
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
if ($this->Application->GetVar('regional')) {
$this->Application->setUnitOption($event->Prefix, 'PopulateMlFields', true);
}
}
/**
* Saves changes & changes language
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveAndChangeLanguage(&$event)
+ protected function OnPreSaveAndChangeLanguage(kEvent &$event)
{
$label = $this->Application->GetVar($event->getPrefixSpecial() . '_label');
- if ($label && !$this->UseTempTables($event)) {
+ if ( $label && !$this->UseTempTables($event) ) {
$phrase_id = $this->_getPhraseId($label);
- if ($phrase_id) {
+ if ( $phrase_id ) {
$event->CallSubEvent('OnUpdate');
$event->SetRedirectParam('opener', 's');
}
else {
$event->CallSubEvent('OnCreate');
$event->SetRedirectParam('opener', 's');
}
- if ($event->status != kEvent::erSUCCESS) {
- return ;
+ if ( $event->status != kEvent::erSUCCESS ) {
+ return;
}
$event->SetRedirectParam($event->getPrefixSpecial() . '_event', 'OnPreparePhrase');
$event->SetRedirectParam('pass_events', true);
}
- if ($this->Application->GetVar('simple_mode')) {
+ if ( $this->Application->GetVar('simple_mode') ) {
$event->SetRedirectParam('simple_mode', 1);
}
parent::OnPreSaveAndChangeLanguage($event);
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnEdit(&$event)
+ protected function OnEdit(kEvent &$event)
{
parent::OnEdit($event);
// use language from grid, instead of primary language used by default
$event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang'));
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/languages/languages_event_handler.php
===================================================================
--- branches/5.2.x/core/units/languages/languages_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/languages/languages_event_handler.php (revision 15065)
@@ -1,665 +1,675 @@
<?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 LanguagesEventHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnChangeLanguage' => Array ('self' => true),
'OnSetPrimary' => Array ('self' => 'advanced:set_primary|add|edit'),
'OnImportLanguage' => Array ('self' => 'advanced:import'),
'OnExportLanguage' => Array ('self' => 'advanced:export'),
'OnExportProgress' => Array ('self' => 'advanced:export'),
'OnReflectMultiLingualFields' => Array ('self' => 'view'),
'OnSynchronizeLanguages' => Array ('self' => 'edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnItemBuild' ) {
// check permission without using $event->getSection(),
// so first cache rebuild won't lead to "ldefault_Name" field being used
return true;
}
return parent::CheckPermission($event);
}
/**
* Allows to get primary language object
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'primary' ) {
return $this->Application->GetDefaultLanguageId();
}
return parent::getPassedID($event);
}
/**
* [HOOK] Updates table structure on new language adding/removing language
*
* @param kEvent $event
*/
function OnReflectMultiLingualFields(&$event)
{
if ($this->Application->GetVar('ajax') == 'yes') {
$event->status = kEvent::erSTOP;
}
if (is_object($event->MasterEvent)) {
if ($event->MasterEvent->status != kEvent::erSUCCESS) {
// only rebuild when all fields are validated
return ;
}
if (($event->MasterEvent->Name == 'OnSave') && !$this->Application->GetVar('new_language')) {
// only rebuild during new language adding
return ;
}
}
$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
$this->Application->UnitConfigReader->ReReadConfigs();
foreach ($this->Application->UnitConfigReader->configData as $prefix => $config_data) {
$ml_helper->createFields($prefix);
}
$event->SetRedirectParam('action_completed', 1);
}
/**
* Allows to set selected language as primary
*
* @param kEvent $event
*/
function OnSetPrimary(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$this->StoreSelectedIDs($event);
$ids = $this->getSelectedIDs($event);
if ($ids) {
$id = array_shift($ids);
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object LanguagesItem */
$object->Load($id);
$object->copyMissingData( $object->setPrimary() );
}
}
/**
* [HOOK] Reset primary status of other languages if we are saving primary language
*
* @param kEvent $event
*/
function OnUpdatePrimary(&$event)
{
if ($event->MasterEvent->status != kEvent::erSUCCESS) {
return ;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object LanguagesItem */
$object->SwitchToLive();
// set primary for each languages, that have this checkbox checked
$ids = explode(',', $event->MasterEvent->getEventParam('ids'));
foreach ($ids as $id) {
$object->Load($id);
if ($object->GetDBField('PrimaryLang')) {
$object->copyMissingData( $object->setPrimary(true, false) );
}
if ($object->GetDBField('AdminInterfaceLang')) {
$object->setPrimary(true, true);
}
}
// if no primary language left, then set primary last language (not to load again) from edited list
$sql = 'SELECT '.$object->IDField.'
FROM '.$object->TableName.'
WHERE PrimaryLang = 1';
$primary_language = $this->Conn->GetOne($sql);
if (!$primary_language) {
$object->setPrimary(false, false); // set primary language
}
$sql = 'SELECT '.$object->IDField.'
FROM '.$object->TableName.'
WHERE AdminInterfaceLang = 1';
$primary_language = $this->Conn->GetOne($sql);
if (!$primary_language) {
$object->setPrimary(false, true); // set admin interface language
}
}
/**
* Prefills options with dynamic values
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
// set dynamic hints for options in date format fields
$options = $fields['InputDateFormat']['options'];
if ($options) {
foreach ($options as $i => $v) {
$options[$i] = $v . ' (' . adodb_date($i) . ')';
}
$fields['InputDateFormat']['options'] = $options;
}
$options = $fields['InputTimeFormat']['options'];
if ($options) {
foreach ($options as $i => $v) {
$options[$i] = $v . ' (' . adodb_date($i) . ')';
}
$fields['InputTimeFormat']['options'] = $options;
}
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
+ parent::OnBeforeItemUpdate($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
$status_fields = $this->Application->getUnitOption($event->Prefix, 'StatusField');
$status_field = array_shift($status_fields);
if ( $object->GetDBField('PrimaryLang') == 1 && $object->GetDBField($status_field) == 0 ) {
$object->SetDBField($status_field, 1);
}
}
/**
* Shows only enabled languages on front
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( in_array($event->Special, Array ('enabled', 'selected', 'available')) ) {
$object->addFilter('enabled_filter', '%1$s.Enabled = ' . STATUS_ACTIVE);
}
// site domain language picker
if ( $event->Special == 'selected' || $event->Special == 'available' ) {
$edit_picker_helper =& $this->Application->recallObject('EditPickerHelper');
/* @var $edit_picker_helper EditPickerHelper */
$edit_picker_helper->applyFilter($event, 'Languages');
}
// apply domain-based language filtering
$languages = $this->Application->siteDomainField('Languages');
if ( strlen($languages) ) {
$languages = explode('|', substr($languages, 1, -1));
$object->addFilter('domain_filter', '%1$s.LanguageId IN (' . implode(',', $languages) . ')');
}
}
/**
* Copy labels from another language
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$src_language = $object->GetDBField('CopyFromLanguage');
if ( $object->GetDBField('CopyLabels') && $src_language ) {
$dst_language = $object->GetID();
// 1. schedule data copy after OnSave event is executed
$var_name = $event->getPrefixSpecial() . '_copy_data' . $this->Application->GetVar('m_wid');
$pending_actions = $this->Application->RecallVar($var_name, Array ());
if ( $pending_actions ) {
$pending_actions = unserialize($pending_actions);
}
$pending_actions[$src_language] = $dst_language;
$this->Application->StoreVar($var_name, serialize($pending_actions));
$object->SetDBField('CopyLabels', 0);
}
}
/**
* Saves language from temp table to live
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
if ( $event->status != kEvent::erSUCCESS ) {
return;
}
$var_name = $event->getPrefixSpecial() . '_copy_data' . $this->Application->GetVar('m_wid');
$pending_actions = $this->Application->RecallVar($var_name, Array ());
if ( $pending_actions ) {
$pending_actions = unserialize($pending_actions);
}
// create multilingual columns for phrases & email events table first (actual for 6+ language)
$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
$ml_helper->createFields('phrases');
$ml_helper->createFields('emailevents');
foreach ($pending_actions as $src_language => $dst_language) {
// phrases import
$sql = 'UPDATE ' . $this->Application->getUnitOption('phrases', 'TableName') . '
SET l' . $dst_language . '_Translation = l' . $src_language . '_Translation';
$this->Conn->Query($sql);
// events import
$sql = 'UPDATE ' . $this->Application->getUnitOption('emailevents', 'TableName') . '
SET
l' . $dst_language . '_Subject = l' . $src_language . '_Subject,
l' . $dst_language . '_Body = l' . $src_language . '_Body';
$this->Conn->Query($sql);
}
$this->Application->RemoveVar($var_name);
$event->CallSubEvent('OnReflectMultiLingualFields');
$event->CallSubEvent('OnUpdatePrimary');
}
/**
* 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)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('CopyLabels', 1);
$sql = 'SELECT ' . $object->IDField . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE PrimaryLang = 1';
$primary_lang_id = $this->Conn->GetOne($sql);
$object->SetDBField('CopyFromLanguage', $primary_lang_id);
$object->SetDBField('SynchronizationModes', Language::SYNCHRONIZE_DEFAULT);
}
/**
* Sets new language mark
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(kEvent &$event)
{
parent::OnBeforeDeleteFromLive($event);
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$sql = 'SELECT ' . $id_field . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE ' . $id_field . ' = ' . $event->getEventParam('id');
$id = $this->Conn->GetOne($sql);
if ( !$id ) {
$this->Application->SetVar('new_language', 1);
}
}
function OnChangeLanguage(&$event)
{
$language_id = $this->Application->GetVar('language');
$language_field = $this->Application->isAdmin ? 'AdminLanguage' : 'FrontLanguage';
$this->Application->SetVar('m_lang', $language_id);
// set new language for this session
$this->Application->Session->SetField('Language', $language_id);
// remember last user language
if ($this->Application->RecallVar('user_id') == USER_ROOT) {
$this->Application->StorePersistentVar($language_field, $language_id);
}
else {
$object =& $this->Application->recallObject('u.current');
/* @var $object kDBItem */
$object->SetDBField($language_field, $language_id);
$object->Update();
}
// without this language change in admin will cause erase of last remembered tree section
$this->Application->SetVar('skip_last_template', 1);
}
/**
* Parse language XML file into temp tables and redirect to progress bar screen
*
* @param kEvent $event
*/
function OnImportLanguage(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$items_info = $this->Application->GetVar('phrases_import');
if ($items_info) {
list ($id, $field_values) = each($items_info);
$object =& $this->Application->recallObject('phrases.import', 'phrases', Array('skip_autoload' => true));
/* @var $object kDBItem */
$object->setID($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
if (!$object->Validate()) {
$event->status = kEvent::erFAIL;
return ;
}
$filename = $object->GetField('LangFile', 'full_path');
if (!filesize($filename)) {
$object->SetError('LangFile', 'la_empty_file', 'la_EmptyFile');
$event->status = kEvent::erFAIL;
}
$language_import_helper =& $this->Application->recallObject('LanguageImportHelper');
/* @var $language_import_helper LanguageImportHelper */
$language_import_helper->performImport(
$filename,
$object->GetDBField('PhraseType'),
$object->GetDBField('Module'),
$object->GetDBField('ImportOverwrite') ? LANG_OVERWRITE_EXISTING : LANG_SKIP_EXISTING
);
// delete uploaded language pack after import is finished
unlink($filename);
$event->SetRedirectParam('opener', 'u');
}
}
/**
* Stores ids of selected languages and redirects to export language step 1
*
* @param kEvent $event
*/
function OnExportLanguage(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return;
}
$this->Application->setUnitOption('phrases','AutoLoad',false);
$this->StoreSelectedIDs($event);
$this->Application->StoreVar('export_language_ids', implode(',', $this->getSelectedIDs($event)) );
$event->setRedirectParams( Array('phrases.export_event' => 'OnNew', 'pass' => 'all,phrases.export') );
}
/**
* Saves selected languages to xml file passed
*
* @param kEvent $event
*/
function OnExportProgress(&$event)
{
$items_info = $this->Application->GetVar('phrases_export');
if ($items_info) {
list($id, $field_values) = each($items_info);
$object =& $this->Application->recallObject('phrases.export', null, Array('skip_autoload' => true));
/* @var $object kDBItem */
$object->setID($id);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
if (!$object->Validate()) {
$event->status = kEvent::erFAIL;
return ;
}
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->CheckFolder(EXPORT_PATH);
if (!is_writable(EXPORT_PATH)) {
$event->status = kEvent::erFAIL;
$object->SetError('LangFile', 'write_error', 'la_ExportFolderNotWritable');
return ;
}
if ( substr($field_values['LangFile'], -5) != '.lang') {
$field_values['LangFile'] .= '.lang';
}
$filename = EXPORT_PATH . '/' . $field_values['LangFile'];
$language_import_helper =& $this->Application->recallObject('LanguageImportHelper');
/* @var $language_import_helper LanguageImportHelper */
if ($object->GetDBField('DoNotEncode')) {
$language_import_helper->setExportEncoding('plain');
}
$language_import_helper->setExportLimits($field_values['ExportPhrases'], $field_values['ExportEmailEvents']);
$lang_ids = explode(',', $this->Application->RecallVar('export_language_ids') );
$language_import_helper->performExport($filename, $field_values['PhraseType'], $lang_ids, $field_values['Module']);
}
$event->redirect = 'regional/languages_export_step2';
$event->SetRedirectParam('export_file', $field_values['LangFile']);
}
/**
* Returns to previous template in opener stack
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnGoBack(kEvent &$event)
{
$event->SetRedirectParam('opener', 'u');
}
function OnScheduleTopFrameReload(&$event)
{
$this->Application->StoreVar('RefreshTopFrame',1);
}
/**
* Do now allow deleting current language
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemDelete(&$event)
+ protected function OnBeforeItemDelete(kEvent &$event)
{
+ parent::OnBeforeItemDelete($event);
+
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('PrimaryLang') || $object->GetDBField('AdminInterfaceLang') || $object->GetID() == $this->Application->GetVar('m_lang') ) {
$event->status = kEvent::erFAIL;
}
}
/**
* Deletes phrases and email events on given language
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemDelete(&$event)
+ protected function OnAfterItemDelete(kEvent &$event)
{
parent::OnAfterItemDelete($event);
$object =& $event->getObject();
/* @var $object kDBItem */
// clean EmailEvents table
$fields_hash = Array (
'l' . $object->GetID() . '_Subject' => NULL,
'l' . $object->GetID() . '_Body' => NULL,
);
$this->Conn->doUpdate($fields_hash, $this->Application->getUnitOption('emailevents', 'TableName'), 1);
// clean Phrases table
$fields_hash = Array (
'l' . $object->GetID() . '_Translation' => NULL,
+ 'l' . $object->GetID() . '_HintTranslation' => NULL,
+ 'l' . $object->GetID() . '_ColumnTranslation' => NULL,
);
$this->Conn->doUpdate($fields_hash, $this->Application->getUnitOption('phrases', 'TableName'), 1);
}
/**
* Copy missing phrases across all system languages (starting from primary)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSynchronizeLanguages(&$event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$source_languages = $target_languages = Array ();
// get language list with primary language first
$sql = 'SELECT SynchronizationModes, LanguageId
FROM ' . TABLE_PREFIX . 'Languages
WHERE SynchronizationModes <> ""
ORDER BY PrimaryLang DESC';
$languages = $this->Conn->GetCol($sql, 'LanguageId');
foreach ($languages as $language_id => $synchronization_modes) {
$synchronization_modes = explode('|', substr($synchronization_modes, 1, -1));
if ( in_array(Language::SYNCHRONIZE_TO_OTHERS, $synchronization_modes) ) {
$source_languages[] = $language_id;
}
if ( in_array(Language::SYNCHRONIZE_FROM_OTHERS, $synchronization_modes) ) {
$target_languages[] = $language_id;
}
}
foreach ($source_languages as $source_id) {
foreach ($target_languages as $target_id) {
if ( $source_id == $target_id ) {
continue;
}
$sql = 'UPDATE ' . TABLE_PREFIX . 'LanguageLabels
SET l' . $target_id . '_Translation = l' . $source_id . '_Translation
WHERE COALESCE(l' . $target_id . '_Translation, "") = "" AND COALESCE(l' . $source_id . '_Translation, "") <> ""';
$this->Conn->Query($sql);
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/permissions/permissions_event_handler.php
===================================================================
--- branches/5.2.x/core/units/permissions/permissions_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/permissions/permissions_event_handler.php (revision 15065)
@@ -1,262 +1,266 @@
<?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 PermissionsEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnGroupSavePermissions' => Array ('subitem' => 'advanced:manage_permissions'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Save category permissions
*
* @param kEvent $event
*/
function OnCategorySavePermissions(&$event)
{
$group_id = $this->Application->GetVar('current_group_id');
$category_id = $this->Application->GetVar('c_id');
$permissions = $this->Application->GetVar($event->getPrefixSpecial(true));
if (isset($permissions[$group_id])) {
$permissions = $permissions[$group_id];
$object =& $event->getObject( Array('skip_autoload' => true) );
$permissions_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $permissions_helper kPermissionsHelper */
$permissions_helper->LoadPermissions($group_id, $category_id, 0, 'c');
// format: <perm_name>['inherited'] || <perm_name>['value']
$delete_ids = Array();
$create_sql = Array();
$update_sql = Array();
$create_mask = '(%s,%s,'.$group_id.',%s,0,'.$category_id.')';
$new_id = (int)$this->Conn->GetOne('SELECT MIN('.$object->IDField.') FROM '.$object->TableName);
if($new_id > 0) $new_id = 0;
--$new_id;
foreach ($permissions as $perm_name => $perm_data) {
$inherited = $perm_data['inherited'];
$perm_value = isset($perm_data['value']) ? $perm_data['value'] : false;
$perm_id = $permissions_helper->getPermissionID($perm_name);
if ($inherited && ($perm_id != 0)) {
// permission become inherited (+ direct value was set before) => DELETE
$delete_ids[] = $permissions_helper->getPermissionID($perm_name);
}
if (!$inherited) {
// not inherited
if (($perm_id != 0) && ($perm_value != $permissions_helper->getPermissionValue($perm_name))) {
// record was found in db & new value differs from old one => UPDATE
$update_sql[$perm_id] = ' UPDATE '.$object->TableName.'
SET PermissionValue = '.$perm_value.'
WHERE (PermissionId = '.$perm_id.')';
}
if ($perm_id == 0) {
// not found in db, but set directly => INSERT
$create_sql[] = sprintf($create_mask, $new_id--, $this->Conn->qstr($perm_name), $this->Conn->qstr($perm_value));
}
}
// permission state was not changed in all other cases
}
$this->UpdatePermissions($event, $create_sql, $update_sql, $delete_ids);
}
$event->MasterEvent->SetRedirectParam('item_prefix', $this->Application->GetVar('item_prefix'));
$event->MasterEvent->SetRedirectParam('group_id', $this->Application->GetVar('group_id'));
}
/**
* Saves permissions while editing group
*
* @param kEvent $event
*
* @return void
* @access protected
*/
protected function OnGroupSavePermissions(&$event)
{
if ( !$this->Application->CheckPermission('in-portal:user_groups.advanced:manage_permissions', 1) ) {
// no permission to save permissions
return ;
}
$permissions = $this->Application->GetVar($event->getPrefixSpecial(true));
if ( !$permissions ) {
return ;
}
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$group_id = $this->Application->GetVar('g_id');
$permissions_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $permissions_helper kPermissionsHelper */
$permissions_helper->LoadPermissions($group_id, 0, 1, 'g');
$delete_ids = $create_sql = Array ();
$create_mask = '(%s,%s,' . $group_id . ',%s,1,0)';
$new_id = (int)$this->Conn->GetOne('SELECT MIN(' . $object->IDField . ') FROM ' . $object->TableName);
if ( $new_id > 0 ) {
$new_id = 0;
}
--$new_id;
$sections_helper =& $this->Application->recallObject('SectionsHelper');
/* @var $sections_helper kSectionsHelper */
foreach ($permissions as $section_name => $section_permissions) {
$section_data =& $sections_helper->getSectionData($section_name);
if ( $section_data && isset($section_data['perm_prefix']) ) {
// using permission from other prefix
$section_name = $this->Application->getUnitOption($section_data['perm_prefix'] . '.main', 'PermSection');
}
foreach ($section_permissions as $perm_name => $perm_value) {
if ( !$permissions_helper->isOldPermission($section_name, $perm_name) ) {
$perm_name = $section_name . '.' . $perm_name;
}
$db_perm_value = $permissions_helper->getPermissionValue($perm_name);
if ( $db_perm_value == 1 && $perm_value == 0 ) {
// permission was disabled => delete it's record
$delete_ids[] = $permissions_helper->getPermissionID($perm_name);
}
elseif ( $db_perm_value == 0 && $perm_value == 1 ) {
// permission was enabled => created it's record
$create_sql[$perm_name] = sprintf($create_mask, $new_id--, $this->Conn->qstr($perm_name), $this->Conn->qstr($perm_value));
}
// permission state was not changed in all other cases
}
}
$this->UpdatePermissions($event, $create_sql, Array (), $delete_ids);
if ( $this->Application->GetVar('advanced_save') == 1 ) {
// advanced permission popup [save button]
$this->finalizePopup($event);
// $event->redirect = 'incs/just_close';
}
elseif ( $this->Application->GetVar('section_name') != '' ) {
// save simple permissions before opening advanced permission popup
$event->redirect = false;
}
}
/**
* Apply modification sqls to permissions table
*
* @param kEvent $event
* @param Array $create_sql
* @param Array $update_sql
* @param Array $delete_ids
*/
function UpdatePermissions(&$event, $create_sql, $update_sql, $delete_ids)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ($delete_ids) {
$action = ChangeLog::DELETE;
$object->Load($delete_ids[count($delete_ids) - 1]);
$delete_sql = ' DELETE FROM '.$object->TableName.'
WHERE '.$object->IDField.' IN ('.implode(',', $delete_ids).')';
$this->Conn->Query($delete_sql);
}
if ($create_sql) {
$create_sql = ' INSERT INTO '.$object->TableName.'
VALUES '.implode(',', $create_sql);
$this->Conn->Query($create_sql);
$sql = 'SELECT MIN(' . $object->IDField . ')
FROM ' . $object->TableName;
$id = $this->Conn->GetOne($sql);
$action = ChangeLog::CREATE;
$object->Load($id);
}
if ($update_sql) {
foreach ($update_sql as $id => $sql) {
$this->Conn->Query($sql);
}
$action = ChangeLog::UPDATE;
$object->Load($id);
$object->SetDBField('PermissionValue', $object->GetDBField('PermissionValue') ? 0 : 1);
}
if ($delete_ids || $create_sql || $update_sql) {
$object->setModifiedFlag($action);
if ($event->Name == 'OnCategorySavePermissions') {
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
}
}
}
/**
* Don't delete permissions from live table in case of new category creation.
* Called as much times as permission count for categories set, so don't
* perform any sql queries here!
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(kEvent &$event)
{
+ parent::OnBeforeDeleteFromLive($event);
+
if ( $event->Prefix == 'c-perm' ) {
// only when saving category permissions, not group permissions
$foreign_keys = $event->getEventParam('foreign_key');
if ( (count($foreign_keys) == 1) && ($foreign_keys[0] == 0) ) {
// parent item has zero id
$temp_object =& $this->Application->recallObject('c');
/* @var $temp_object CategoriesItem */
if ( $temp_object->isLoaded() ) {
// category with id = 0 found in temp table
$event->status = kEvent::erFAIL;
}
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/email_events/email_events_event_handler.php
===================================================================
--- branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 15064)
+++ branches/5.2.x/core/units/email_events/email_events_event_handler.php (revision 15065)
@@ -1,1210 +1,1216 @@
<?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 EmailEventsEventsHandler extends kDBEventHandler
{
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnFrontOnly' => Array ('self' => 'edit'),
'OnSaveSelected' => Array ('self' => 'view'),
'OnProcessEmailQueue' => Array ('self' => 'add|edit'),
'OnSuggestAddress' => Array ('self' => 'add|edit'),
// events only for developers
'OnPreCreate' => Array ('self' => 'debug'),
'OnDelete' => Array ('self' => 'debug'),
'OnDeleteAll' => Array ('self' => 'debug'),
'OnMassDelete' => Array ('self' => 'debug'),
'OnMassApprove' => Array ('self' => 'debug'),
'OnMassDecline' => Array ('self' => 'debug'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Changes permission section to one from REQUEST, not from config
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
$module = $this->Application->GetVar('module');
if ( strlen($module) > 0 ) {
// checking permission when lising module email events in separate section
$module = explode(':', $module, 2);
if ( count($module) == 1 ) {
$main_prefix = $this->Application->findModule('Name', $module[0], 'Var');
}
else {
$exceptions = Array ('Category' => 'c', 'Users' => 'u');
$main_prefix = $exceptions[$module[1]];
}
$section = $this->Application->getUnitOption($main_prefix . '.email', 'PermSection');
$event->setEventParam('PermSection', $section);
}
// checking permission when listing all email events when editing language
return parent::CheckPermission($event);
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if ( $event->Special == 'module' ) {
$module = $this->Application->GetVar('module');
$object->addFilter('module_filter', '%1$s.Module = ' . $this->Conn->qstr($module));
}
if ( !$event->Special && !$this->Application->isDebugMode() ) {
// no special
$object->addFilter('enabled_filter', '%1$s.Enabled <> ' . STATUS_DISABLED);
}
}
/**
* Prepares new kDBItem object
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnNew(&$event)
+ protected function OnNew(kEvent &$event)
{
parent::OnNew($event);
$mapping = Array ('conf' => 'VariableValue', 'site-domain' => 'DefaultEmailRecipients');
if ( isset($mapping[$event->Special]) ) {
$object =& $event->getObject();
/* @var $object kDBItem */
$target_object =& $this->Application->recallObject($event->Special);
/* @var $target_object kDBList */
$object->SetDBField('Recipients', $target_object->GetDBField($mapping[$event->Special]));
}
}
/**
* Set default headers
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnPreCreate(&$event)
+ protected function OnPreCreate(kEvent &$event)
{
parent::OnPreCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('Headers', $this->Application->ConfigValue('Smtp_DefaultHeaders'));
}
/**
* Sets status Front-End Only to selected email events
*
* @param kEvent $event
*/
function OnFrontOnly(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = kEvent::erFAIL;
return ;
}
$ids = implode(',', $this->StoreSelectedIDs($event));
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'UPDATE '.$table_name.'
SET FrontEndOnly = 1
WHERE EventId IN ('.$ids.')';
$this->Conn->Query($sql);
$this->clearSelectedIDs($event);
}
/**
* Sets selected user to email events selected
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnSelectUser(&$event)
+ protected function OnSelectUser(kEvent &$event)
{
- if ($event->Special != 'module') {
+ if ( $event->Special != 'module' ) {
parent::OnSelectUser($event);
- return ;
+ return;
}
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return ;
+ return;
}
$items_info = $this->Application->GetVar('u');
- if ($items_info) {
- $user_id = array_shift( array_keys($items_info) );
+ if ( $items_info ) {
+ $user_id = array_shift(array_keys($items_info));
$selected_ids = $this->getSelectedIDs($event, true);
- $ids = $this->Application->RecallVar($event->getPrefixSpecial().'_selected_ids');
+ $ids = $this->Application->RecallVar($event->getPrefixSpecial() . '_selected_ids');
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
- $sql = 'UPDATE '.$table_name.'
- SET '.$this->Application->RecallVar('dst_field').' = '.$user_id.'
- WHERE '.$id_field.' IN ('.$ids.')';
+
+ $sql = 'UPDATE ' . $table_name . '
+ SET ' . $this->Application->RecallVar('dst_field') . ' = ' . $user_id . '
+ WHERE ' . $id_field . ' IN (' . $ids . ')';
$this->Conn->Query($sql);
}
$this->finalizePopup($event);
}
/**
* Saves selected ids to session
*
* @param kEvent $event
*/
function OnSaveSelected(&$event)
{
$this->StoreSelectedIDs($event);
}
/**
* Returns email event object based on given kEvent object
*
* @param kEvent $event
* @return kDBItem
*/
function &_getEmailEvent(&$event)
{
$false = false;
$name = $event->getEventParam('EmailEventName');
$type = $event->getEventParam('EmailEventType');
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
if (!$object->isLoaded() || ($object->GetDBField('Event') != $name || $object->GetDBField('Type') != $type)) {
// get event parameters by name & type
$load_keys = Array ('Event' => $name, 'Type' => $type);
$object->Load($load_keys);
if (!$object->isLoaded() || ($object->GetDBField('Enabled') == STATUS_DISABLED)) {
// event record not found OR is disabled
return $false;
}
if ($object->GetDBField('FrontEndOnly') && $this->Application->isAdmin) {
return $false;
}
}
return $object;
}
/**
* Processes email sender
*
* @param kEvent $event
* @param Array $direct_params
*/
function _processSender(&$event, $direct_params = Array ())
{
$this->Application->removeObject('u.email-from');
$object =& $this->_getEmailEvent($event);
/* @var $object kDBItem */
$email = $name = '';
// set defaults from event
if ($object->GetDBField('CustomSender')) {
$address = $object->GetDBField('SenderAddress');
$address_type = $object->GetDBField('SenderAddressType');
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
$email = $address;
break;
case EmailEvent::ADDRESS_TYPE_USER:
$sql = 'SELECT FirstName, LastName, Email, PortalUserId
FROM ' . TABLE_PREFIX . 'Users
WHERE Username = ' . $this->Conn->qstr($address);
$user_info = $this->Conn->GetRow($sql);
if ($user_info) {
// user still exists
$email = $user_info['Email'];
$name = trim($user_info['FirstName'] . ' ' . $user_info['LastName']);
$user =& $this->Application->recallObject('u.email-from', null, Array('skip_autoload' => true));
/* @var $user UsersItem */
$user->Load($user_info['PortalUserId']);
}
break;
}
if ($object->GetDBField('SenderName')) {
$name = $object->GetDBField('SenderName');
}
}
// update with custom data given during event execution
if (array_key_exists('from_email', $direct_params)) {
$email = $direct_params['from_email'];
}
if (array_key_exists('from_name', $direct_params)) {
$name = $direct_params['from_name'];
}
// still nothing, set defaults
if (!$email) {
$email = $this->Application->ConfigValue('DefaultEmailSender');
}
if (!$name) {
$name = strip_tags( $this->Application->ConfigValue('Site_Name') );
}
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$esender->SetFrom($email, $name);
return Array ($email, $name);
}
/**
* Processes email recipients
*
* @param kEvent $event
* @param Array $direct_params
* @return Array
*/
function _processRecipients(&$event, &$direct_params = Array ())
{
$this->Application->removeObject('u.email-to');
$object =& $this->_getEmailEvent($event);
/* @var $object kDBItem */
$to_email = $to_name = '';
$all_recipients = Array ();
$this->_addRecipientsFromXml($all_recipients, $object->GetDBField('Recipients'));
if ( !array_key_exists(EmailEvent::RECIPIENT_TYPE_TO, $all_recipients) ) {
$all_recipients[EmailEvent::RECIPIENT_TYPE_TO] = Array ();
}
// remove all "To" recipients, when not allowed
$overwrite_to_email = array_key_exists('overwrite_to_email', $direct_params) ? $direct_params['overwrite_to_email'] : false;
if ( !$object->GetDBField('CustomRecipient') || $overwrite_to_email ) {
$all_recipients[EmailEvent::RECIPIENT_TYPE_TO] = Array ();
}
// update with custom data given during event execution (user_id)
$to_user_id = $event->getEventParam('EmailEventToUserId');
if ( $to_user_id > 0 ) {
$language_field = $event->getEventParam('EmailEventType') == EmailEvent::EVENT_TYPE_FRONTEND ? 'FrontLanguage' : 'AdminLanguage';
$sql = 'SELECT FirstName, LastName, Email, ' . $language_field . ' AS Language
FROM ' . TABLE_PREFIX . 'Users
WHERE PortalUserId = ' . $to_user_id;
$user_info = $this->Conn->GetRow($sql);
if ( $user_info ) {
$add_recipient = Array (
'RecipientAddressType' => EmailEvent::ADDRESS_TYPE_EMAIL,
'RecipientAddress' => $user_info['Email'],
'RecipientName' => trim($user_info['FirstName'] . ' ' . $user_info['LastName']),
);
if ( $user_info['Language'] && !isset($direct_params['language_id']) ) {
$direct_params['language_id'] = $user_info['Language'];
}
array_unshift($all_recipients[EmailEvent::RECIPIENT_TYPE_TO], $add_recipient);
$user =& $this->Application->recallObject('u.email-to', null, Array('skip_autoload' => true));
/* @var $user UsersItem */
$user->Load($to_user_id);
}
}
elseif ( is_numeric($to_user_id) ) {
// recipient is system user with negative ID (root, guest, etc.) -> send to admin
$this->_addDefaultRecipient($all_recipients);
}
// update with custom data given during event execution (email + name)
$add_recipient = Array ();
if ( array_key_exists('to_email', $direct_params) ) {
$add_recipient['RecipientName'] = '';
$add_recipient['RecipientAddressType'] = EmailEvent::ADDRESS_TYPE_EMAIL;
$add_recipient['RecipientAddress'] = $direct_params['to_email'];
}
if ( array_key_exists('to_name', $direct_params) ) {
$add_recipient['RecipientName'] = $direct_params['to_name'];
}
if ( $add_recipient ) {
array_unshift($all_recipients[EmailEvent::RECIPIENT_TYPE_TO], $add_recipient);
}
if ( ($object->GetDBField('Type') == EmailEvent::EVENT_TYPE_ADMIN) && !$all_recipients[EmailEvent::RECIPIENT_TYPE_TO] ) {
// admin email event without direct recipient -> send to admin
$this->_addDefaultRecipient($all_recipients);
}
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$header_mapping = Array (
EmailEvent::RECIPIENT_TYPE_TO => 'To',
EmailEvent::RECIPIENT_TYPE_CC => 'Cc',
EmailEvent::RECIPIENT_TYPE_BCC => 'Bcc',
);
$default_email = $this->Application->ConfigValue('DefaultEmailSender');
foreach ($all_recipients as $recipient_type => $recipients) {
// add recipients to email
$pairs = Array ();
foreach ($recipients as $recipient) {
$address = $recipient['RecipientAddress'];
$address_type = $recipient['RecipientAddressType'];
$recipient_name = $recipient['RecipientName'];
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
$pairs[] = Array ('email' => $address, 'name' => $recipient_name);
break;
case EmailEvent::ADDRESS_TYPE_USER:
$sql = 'SELECT FirstName, LastName, Email
FROM ' . TABLE_PREFIX . 'Users
WHERE Username = ' . $this->Conn->qstr($address);
$user_info = $this->Conn->GetRow($sql);
if ($user_info) {
// user still exists
$name = trim($user_info['FirstName'] . ' ' . $user_info['LastName']);
$pairs[] = Array (
'email' => $user_info['Email'],
'name' => $name ? $name : $recipient_name,
);
}
break;
case EmailEvent::ADDRESS_TYPE_GROUP:
$sql = 'SELECT u.FirstName, u.LastName, u.Email
FROM ' . TABLE_PREFIX . 'UserGroups g
JOIN ' . TABLE_PREFIX . 'UserGroupRelations ug ON ug.GroupId = g.GroupId
JOIN ' . TABLE_PREFIX . 'Users u ON u.PortalUserId = ug.PortalUserId
WHERE g.Name = ' . $this->Conn->qstr($address);
$users = $this->Conn->Query($sql);
foreach ($users as $user_info) {
$name = trim($user_info['FirstName'] . ' ' . $user_info['LastName']);
$pairs[] = Array (
'email' => $user_info['Email'],
'name' => $name ? $name : $recipient_name,
);
}
break;
}
}
if ( !$pairs ) {
continue;
}
if ( $recipient_type == EmailEvent::RECIPIENT_TYPE_TO ) {
$to_email = $pairs[0]['email'] ? $pairs[0]['email'] : $default_email;
$to_name = $pairs[0]['name'] ? $pairs[0]['name'] : $to_email;
}
$header_name = $header_mapping[$recipient_type];
foreach ($pairs as $pair) {
$email = $pair['email'] ? $pair['email'] : $default_email;
$name = $pair['name'] ? $pair['name'] : $email;
$esender->AddRecipient($header_name, $email, $name);
}
}
return Array ($to_email, $to_name);
}
/**
* This is default recipient, when we can't determine actual one
*
* @param Array $recipients
* @return void
*/
function _addDefaultRecipient(&$recipients)
{
$xml = $this->Application->ConfigValue('DefaultEmailRecipients');
if ( !$this->_addRecipientsFromXml($recipients, $xml) ) {
$recipient = Array (
'RecipientName' => $this->Application->ConfigValue('DefaultEmailSender'),
'RecipientAddressType' => EmailEvent::ADDRESS_TYPE_EMAIL,
'RecipientAddress' => $this->Application->ConfigValue('DefaultEmailSender'),
);
array_unshift($recipients[EmailEvent::RECIPIENT_TYPE_TO], $recipient);
}
}
/**
* Adds multiple recipients from an XML
*
* @param Array $recipients
* @param string $xml
* @return bool
* @access protected
*/
protected function _addRecipientsFromXml(&$recipients, $xml)
{
if ( !$xml ) {
return false;
}
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
// group recipients by type
$records = $minput_helper->parseMInputXML($xml);
foreach ($records as $record) {
$recipient_type = $record['RecipientType'];
if ( !array_key_exists($recipient_type, $recipients) ) {
$recipients[$recipient_type] = Array ();
}
$recipients[$recipient_type][] = $record;
}
return true;
}
/**
* Returns email event message by ID (headers & body in one piece)
*
* @param kEvent $event
* @param int $language_id
* @return string
*/
function _getMessageBody(&$event, $language_id = null)
{
if (!isset($language_id)) {
$language_id = $this->Application->GetVar('m_lang');
}
$object =& $this->_getEmailEvent($event);
// 1. get message body
$message_body = $this->_formMessageBody($object, $language_id, $object->GetDBField('MessageType'));
// 2. replace tags if needed
$default_replacement_tags = Array (
'<inp:touser _Field="password"' => '<inp2:u_Field name="Password_plain"',
'<inp:touser _Field="UserName"' => '<inp2:u_Field name="Username"',
'<inp:touser _Field' => '<inp2:u_Field name',
);
$replacement_tags = $object->GetDBField('ReplacementTags');
$replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array ();
$replacement_tags = array_merge($default_replacement_tags, $replacement_tags);
foreach ($replacement_tags as $replace_from => $replace_to) {
$message_body = str_replace($replace_from, $replace_to, $message_body);
}
return $message_body;
}
/**
* Prepare email message body
*
* @param kDBItem $object
* @param int $language_id
* @return string
*/
function _formMessageBody(&$object, $language_id)
{
$default_language_id = $this->Application->GetDefaultLanguageId();
$fields_hash = Array (
'Headers' => $object->GetDBField('Headers'),
);
// prepare subject
$subject = $object->GetDBField('l' . $language_id . '_Subject');
if (!$subject) {
$subject = $object->GetDBField('l' . $default_language_id . '_Subject');
}
$fields_hash['Subject'] = $subject;
// prepare body
$body = $object->GetDBField('l' . $language_id . '_Body');
if (!$body) {
$body = $object->GetDBField('l' . $default_language_id . '_Body');
}
$fields_hash['Body'] = $body;
$email_message_helper =& $this->Application->recallObject('EmailMessageHelper');
/* @var $email_message_helper EmailMessageHelper */
$ret = $email_message_helper->buildTemplate($fields_hash);
// add footer
$footer = $this->_getFooter($language_id, $object->GetDBField('MessageType'));
if ($ret && $footer) {
$ret .= "\r\n" . $footer;
}
return $ret;
}
/**
* Returns email footer
*
* @param int $language_id
* @param string $message_type
* @return string
*/
function _getFooter($language_id, $message_type)
{
static $footer = null;
if (!isset($footer)) {
$default_language_id = $this->Application->GetDefaultLanguageId();
$sql = 'SELECT l' . $language_id . '_Body, l' . $default_language_id . '_Body
FROM ' . $this->Application->getUnitOption('emailevents', 'TableName') . ' em
WHERE Event = "COMMON.FOOTER"';
$footer_data = $this->Conn->GetRow($sql);
$footer = $footer_data['l' . $language_id . '_Body'];
if (!$footer) {
$footer = $footer_data['l' . $default_language_id . '_Body'];
}
if ($message_type == 'text') {
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$footer = $esender->ConvertToText($footer);
}
}
return $footer;
}
/**
* Parse message template and return headers (as array) and message body part
*
* @param string $message
* @param Array $direct_params
* @return Array
*/
function ParseMessageBody($message, $direct_params = Array ())
{
$message_language = $this->_getSendLanguage($direct_params);
$this->_changeLanguage($message_language);
$direct_params['message_text'] = isset($direct_params['message']) ? $direct_params['message'] : ''; // parameter alias
// 1. parse template
$this->Application->InitParser();
$parser_params = $this->Application->Parser->Params; // backup parser params
$this->Application->Parser->SetParams( array_merge($parser_params, $direct_params) );
$message = implode('&|&', explode("\n\n", $message, 2)); // preserves double \n in case when tag is located in subject field
$message = $this->Application->Parser->Parse($message, 'email_template', 0);
$this->Application->Parser->SetParams($parser_params); // restore parser params
// 2. replace line endings, that are send with data submitted via request
$message = str_replace("\r\n", "\n", $message); // possible case
$message = str_replace("\r", "\n", $message); // impossible case, but just in case replace this too
// 3. separate headers from body
$message_headers = Array ();
list($headers, $message_body) = explode('&|&', $message, 2);
$category_helper =& $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$message_body = $category_helper->replacePageIds($message_body);
$headers = explode("\n", $headers);
foreach ($headers as $header) {
$header = explode(':', $header, 2);
$message_headers[ trim($header[0]) ] = trim($header[1]);
}
$this->_changeLanguage();
return Array ($message_headers, $message_body);
}
/**
* Raised when email message should be sent
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnEmailEvent(&$event)
{
$email_event_name = $event->getEventParam('EmailEventName');
if ( strpos($email_event_name, '_') !== false ) {
throw new Exception('<span class="debug_error">Invalid email event name</span> <strong>' . $email_event_name . '</strong>. Use only <strong>UPPERCASE characters</strong> and <strong>dots</strong> as email event names');
}
$object =& $this->_getEmailEvent($event);
if ( !is_object($object) ) {
// email event not found OR it's won't be send under given circumstances
return ;
}
// additional parameters from kApplication->EmailEvent
$send_params = $event->getEventParam('DirectSendParams');
// 1. get information about message sender and recipient
list ($from_email, $from_name) = $this->_processSender($event, $send_params);
list ($to_email, $to_name) = $this->_processRecipients($event, $send_params);
// 2. prepare message to be sent
$message_language = $this->_getSendLanguage($send_params);
$message_template = $this->_getMessageBody($event, $message_language);
if ( !trim($message_template) ) {
trigger_error('Message template is empty', E_USER_WARNING);
return ;
}
list ($message_headers, $message_body) = $this->ParseMessageBody($message_template, $send_params);
if ( !trim($message_body) ) {
trigger_error('Message template is empty after parsing', E_USER_WARNING);
return ;
}
// 3. set headers & send message
$esender =& $this->Application->recallObject('EmailSender');
/* @var $esender kEmailSendingHelper */
$message_subject = isset($message_headers['Subject']) ? $message_headers['Subject'] : 'Mail message';
$esender->SetSubject($message_subject);
if ( $this->Application->isDebugMode() ) {
// set special header with event name, so it will be easier to determine what's actually was received
$message_headers['X-Event-Name'] = $email_event_name . ' - ' . ($object->GetDBField('Type') == EmailEvent::EVENT_TYPE_ADMIN ? 'ADMIN' : 'USER');
}
foreach ($message_headers as $header_name => $header_value) {
$esender->SetEncodedHeader($header_name, $header_value);
}
$esender->CreateTextHtmlPart($message_body, $object->GetDBField('MessageType') == 'html');
$log_fields_hash = Array (
'fromuser' => $from_name . ' (' . $from_email . ')',
'addressto' => $to_name . ' (' . $to_email . ')',
'subject' => $message_subject,
'timestamp' => adodb_mktime(),
'event' => $email_event_name,
'EventParams' => serialize( $this->removeSendingParams($send_params) ),
);
$esender->setLogData($log_fields_hash);
$event->status = $esender->Deliver() ? kEvent::erSUCCESS : kEvent::erFAIL;
}
/**
* Removes parameters, used during e-mail sending
*
* @param Array $params
* @return Array
* @access protected
*/
protected function removeSendingParams($params)
{
$send_keys = Array ('from_email', 'from_name', 'to_email', 'to_name', 'message');
foreach ($send_keys as $send_key) {
unset($params[$send_key]);
}
return $params;
}
function _getSendLanguage($send_params)
{
if (array_key_exists('language_id', $send_params)) {
return $send_params['language_id'];
}
return $this->Application->GetVar('m_lang');
}
function _changeLanguage($language_id = null)
{
static $prev_language_id = null;
if ( !isset($language_id) ) {
// restore language
$language_id = $prev_language_id;
}
$this->Application->SetVar('m_lang', $language_id);
$language =& $this->Application->recallObject('lang.current');
/* @var $language LanguagesItem */
$language->Load($language_id);
$this->Application->Phrases->LanguageId = $language_id;
$this->Application->Phrases->Phrases = Array ();
$prev_language_id = $language_id; // for restoring it later
}
/**
* Process emails from queue
*
* @param kEvent $event
* @todo Move to MailingList
*/
function OnProcessEmailQueue(&$event)
{
$deliver_count = $event->getEventParam('deliver_count');
if ($deliver_count === false) {
$deliver_count = $this->Application->ConfigValue('MailingListSendPerStep');
if ($deliver_count === false) {
$deliver_count = 10; // 10 emails per script run (if not specified directly)
}
}
$processing_type = $this->Application->GetVar('type');
if ($processing_type = 'return_progress') {
$email_queue_progress = $this->Application->RecallVar('email_queue_progress');
if ($email_queue_progress === false) {
$emails_sent = 0;
$sql = 'SELECT COUNT(*)
FROM ' . TABLE_PREFIX . 'EmailQueue
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')';
$total_emails = $this->Conn->GetOne($sql);
$this->Application->StoreVar('email_queue_progress', $emails_sent.':'.$total_emails);
}
else {
list ($emails_sent, $total_emails) = explode(':', $email_queue_progress);
}
}
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'EmailQueue
WHERE (SendRetries < 5) AND (LastSendRetry < ' . strtotime('-2 hours') . ')
LIMIT 0,' . $deliver_count;
$messages = $this->Conn->Query($sql);
$message_count = count($messages);
if (!$message_count) {
// no messages left to send in queue
if ($processing_type = 'return_progress') {
$this->Application->RemoveVar('email_queue_progress');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
return ;
}
$mailing_list_helper =& $this->Application->recallObject('MailingListHelper');
/* @var $mailing_list_helper MailingListHelper */
$mailing_list_helper->processQueue($messages);
if ($processing_type = 'return_progress') {
$emails_sent += $message_count;
if ($emails_sent >= $total_emails) {
$this->Application->RemoveVar('email_queue_progress');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
$this->Application->StoreVar('email_queue_progress', $emails_sent.':'.$total_emails);
$event->status = kEvent::erSTOP;
echo ($emails_sent / $total_emails) * 100;
}
}
/**
* Prefills module dropdown
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
$options = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
continue;
}
$options[$module_name] = $module_name;
}
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Module']['options'] = $options;
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
if ($this->Application->GetVar('regional')) {
$this->Application->setUnitOption($event->Prefix, 'PopulateMlFields', true);
}
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnEdit(&$event)
+ protected function OnEdit(kEvent &$event)
{
parent::OnEdit($event);
// use language from grid, instead of primary language used by default
$event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang'));
}
/**
* Fixes default recipient type
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if (!$this->Application->isDebugMode(false)) {
if ($object->GetDBField('AllowChangingRecipient')) {
$object->SetDBField('RecipientType', EmailEvent::RECIPIENT_TYPE_TO);
}
else {
$object->SetDBField('RecipientType', EmailEvent::RECIPIENT_TYPE_CC);
}
}
// process replacement tags
$records = Array ();
$replacement_tags = $object->GetDBField('ReplacementTags');
$replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array ();
foreach ($replacement_tags as $tag => $replacement) {
$records[] = Array ('Tag' => $tag, 'Replacement' => $replacement);
}
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$xml = $minput_helper->prepareMInputXML($records, Array ('Tag', 'Replacement'));
$object->SetDBField('ReplacementTagsXML', $xml);
}
/**
* Performs custom validation + keep read-only fields
*
* @param kEvent $event
*/
function _itemChanged(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
// validate email subject and body for parsing errors
$this->_validateEmailTemplate($object);
// validate sender and recipient addresses
if ($object->GetDBField('CustomSender')) {
$this->_validateAddress($event, 'Sender');
}
$this->_validateAddress($event, 'Recipient');
if (!$this->Application->isDebugMode(false)) {
// only allow to enable/disable event while in debug mode
$to_restore = Array ('Enabled', 'AllowChangingSender', 'AllowChangingRecipient');
if (!$object->GetOriginalField('AllowChangingSender')) {
$to_restore = array_merge($to_restore, Array ('CustomSender', 'SenderName', 'SenderAddressType', 'SenderAddress'));
}
if (!$object->GetOriginalField('AllowChangingRecipient')) {
$to_restore = array_merge($to_restore, Array ('CustomRecipient'/*, 'Recipients'*/));
}
// prevent specific fields from editing
foreach ($to_restore as $restore_field) {
$original_value = $object->GetOriginalField($restore_field);
if ($object->GetDBField($restore_field) != $original_value) {
$object->SetDBField($restore_field, $original_value);
}
}
}
// process replacement tags
if ( $object->GetDBField('ReplacementTagsXML') ) {
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$replacement_tags = Array ();
$records = $minput_helper->parseMInputXML( $object->GetDBField('ReplacementTagsXML') );
foreach ($records as $record) {
$replacement_tags[ trim($record['Tag']) ] = trim($record['Replacement']);
}
$object->SetDBField('ReplacementTags', $replacement_tags ? serialize($replacement_tags) : NULL);
}
}
/**
* Validates address using given field prefix
*
* @param kEvent $event
* @param string $field_prefix
*/
function _validateAddress(&$event, $field_prefix)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$address_type = $object->GetDBField($field_prefix . 'AddressType');
$object->setRequired($field_prefix . 'Address', $address_type > 0);
$address = $object->GetDBField($field_prefix . 'Address');
if (!$address) {
// don't validate against empty address
return ;
}
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
if (!preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $address)) {
$object->SetError($field_prefix . 'Address', 'invalid_email');
}
break;
case EmailEvent::ADDRESS_TYPE_USER:
$sql = 'SELECT PortalUserId
FROM ' . TABLE_PREFIX . 'Users
WHERE Username = ' . $this->Conn->qstr($address);
if (!$this->Conn->GetOne($sql)) {
$object->SetError($field_prefix . 'Address', 'invalid_user');
}
break;
case EmailEvent::ADDRESS_TYPE_GROUP:
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroups
WHERE Name = ' . $this->Conn->qstr($address);
if (!$this->Conn->GetOne($sql)) {
$object->SetError($field_prefix . 'Address', 'invalid_group');
}
break;
}
}
/**
* Don't allow to enable/disable events in non-debug mode
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->_itemChanged($event);
}
/**
* Don't allow to enable/disable events in non-debug mode
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_itemChanged($event);
}
/**
* Suggest address based on typed address and selected address type
*
* @param kEvent $event
*/
function OnSuggestAddress(&$event)
{
$event->status = kEvent::erSTOP;
$address_type = $this->Application->GetVar('type');
$address = $this->Application->GetVar('value');
$limit = $this->Application->GetVar('limit');
if ( !$limit ) {
$limit = 20;
}
switch ($address_type) {
case EmailEvent::ADDRESS_TYPE_EMAIL:
$field = 'Email';
$table_name = TABLE_PREFIX . 'Users';
break;
case EmailEvent::ADDRESS_TYPE_USER:
$field = 'Username';
$table_name = TABLE_PREFIX . 'Users';
break;
case EmailEvent::ADDRESS_TYPE_GROUP:
$field = 'Name';
$table_name = TABLE_PREFIX . 'UserGroups';
break;
default:
$field = $table_name = '';
break;
}
if ( $field ) {
$sql = 'SELECT DISTINCT ' . $field . '
FROM ' . $table_name . '
WHERE ' . $field . ' LIKE ' . $this->Conn->qstr($address . '%') . '
ORDER BY ' . $field . ' ASC
LIMIT 0,' . $limit;
$data = $this->Conn->GetCol($sql);
}
else {
$data = Array ();
}
$this->Application->XMLHeader();
echo '<suggestions>';
foreach ($data as $item) {
echo '<item>' . htmlspecialchars($item) . '</item>';
}
echo '</suggestions>';
}
/**
* Validates subject and body fields of Email template
* @param kDBItem $object
*/
function _validateEmailTemplate(&$object)
{
$this->parseField($object, 'Subject');
$this->parseField($object, 'Body');
}
/**
* Parses contents of given object field and sets error, when invalid in-portal tags found
* @param kDBItem $object
* @param string $field
* @return void
*/
function parseField(&$object, $field)
{
$this->Application->InitParser();
try {
$this->Application->Parser->CompileRaw($object->GetField($field), 'email_template');
}
catch (ParserException $e) {
if ( $this->Application->isDebugMode() ) {
$this->Application->Debugger->appendHTML('<b style="color: red;">Error in Email Template:</b> ' . $e->getMessage() . ' (line: ' . $e->getLine() . ')');
}
$object->SetError($field, 'parsing_error');
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/page_revisions/page_revision_eh.php
===================================================================
--- branches/5.2.x/core/units/page_revisions/page_revision_eh.php (revision 15064)
+++ branches/5.2.x/core/units/page_revisions/page_revision_eh.php (revision 15065)
@@ -1,365 +1,375 @@
<?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 PageRevisionEventHandler extends kDBEventHandler {
/**
* Checks permissions of user
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnItemBuild' ) {
return true;
}
if ( $event->Name == 'OnGetInfo' || $event->Name == 'OnDiscard' ) {
return $this->Application->isAdminUser;
}
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
if ( $event->Name == 'OnSave' ) {
$perm_status = $this->Application->CheckPermission('CATEGORY.REVISION.ADD', 0) || $this->Application->CheckPermission('CATEGORY.REVISION.ADD.PENDING', 0);
return $perm_helper->finalizePermissionCheck($event, $perm_status);
}
if ( $event->Name == 'OnPublish' || $event->Name == 'OnDecline' ) {
$perm_status = $this->Application->CheckPermission('CATEGORY.REVISION.MODERATE', 0);
return $perm_helper->finalizePermissionCheck($event, $perm_status);
}
return parent::CheckPermission($event);
}
/**
* Lists all current page revisions
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function SetCustomQuery(kEvent &$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
$page_id = $event->getEventParam('page_id');
if ( $this->Application->isAdmin ) {
$user_id = $this->Application->RecallVar('user_id');
}
else {
$user_id = $this->Application->RecallVar('admin_user_id');
}
$object->addFilter('draft_filter', 'IF(%1$s.IsDraft = 1, %1$s.CreatedById = ' . $user_id . ', TRUE)');
if ( $page_id !== false ) {
$object->addFilter('parent_filter', '%1$s.PageId = ' . $page_id);
}
}
/**
* Returns current page revision
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'current' ) {
$page =& $this->Application->recallObject('st.-virtual');
/* @var $page kDBItem */
$page_helper =& $this->Application->recallObject('PageHelper');
/* @var $page_helper PageHelper */
$page_id = $page->GetID();
$revision_clause = $page_helper->getRevsionWhereClause($page_id, $page->GetDBField('LiveRevisionNumber'));
$sql = 'SELECT RevisionId
FROM ' . TABLE_PREFIX . 'PageRevisions
WHERE (PageId = ' . $page_id . ') AND (' . $revision_clause . ')
ORDER BY IsDraft DESC, RevisionNumber DESC';
$id = $this->Conn->GetOne($sql);
if ( $id ) {
return $id;
}
// no revisions -> create live revision
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('PageId', $page_id);
$object->SetDBField('RevisionNumber', 1);
$object->SetDBField('Status', STATUS_ACTIVE);
$object->Create();
return $object->GetID();
}
return parent::getPassedID($event);
}
/**
* Remembers, who created revision
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $this->Application->isAdmin ) {
$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
}
else {
$object->SetDBField('CreatedById', $this->Application->RecallVar('admin_user_id'));
}
}
/**
* Updates revision creation time
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $object->GetDBField('IsDraft') == 0 && $object->GetOriginalField('IsDraft') == 1 ) {
$object->SetDBField('CreatedOn_date', adodb_mktime());
$object->SetDBField('CreatedOn_time', adodb_mktime());
}
}
/**
* Creates new content blocks based on source revision
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
if ( !$object->GetDBField('FromRevisionId') ) {
return ;
}
$content =& $this->Application->recallObject('content.-item', null, Array ('skip_autoload' => true));
/* @var $content kDBItem */
$sql = $content->GetSelectSQL() . '
WHERE pr.RevisionId = ' . $object->GetDBField('FromRevisionId');
$content_blocks = $this->Conn->Query($sql);
foreach ($content_blocks as $content_block) {
$content->LoadFromHash($content_block);
$content->SetDBField('RevisionId', $object->GetID());
$content->Create();
}
}
/**
* Mark revision as current, once it's approved
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemUpdate(&$event)
+ protected function OnAfterItemUpdate(kEvent &$event)
{
parent::OnAfterItemUpdate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$status = $object->GetDBField('Status');
if ( $status != $object->GetOriginalField('Status') && $status == STATUS_ACTIVE ) {
$page =& $this->Application->recallObject('c.revision', null, Array ('skip_autoload' => true));
/* @var $page kDBItem */
- $page->Load( $object->GetDBField('PageId') );
+ $page->Load($object->GetDBField('PageId'));
$page->SetDBField('LiveRevisionNumber', $object->GetDBField('RevisionNumber'));
$page->Update();
}
}
/**
* Returns user, who are editing current page right now
*
* @param kEvent $event
*/
function OnGetInfo(&$event)
{
$event->status = kEvent::erSTOP;
if ( $this->Application->GetVar('ajax') != 'yes' ) {
return ;
}
$page_helper =& $this->Application->recallObject('PageHelper');
/* @var $page_helper PageHelper */
$page_id = $this->Application->GetVar('m_cat_id');
echo json_encode( $page_helper->getPageInfo($page_id) );
}
/**
* Saves user draft into live revision
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
$revision_id = $this->getCurrentDraftRevision($event);
if ( $revision_id ) {
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->Load($revision_id);
$object->SetDBField('IsDraft', 0);
$object->SetDBField('RevisionNumber', $this->getNextAvailableRevision($event));
if ( $this->Application->CheckPermission('CATEGORY.REVISION.ADD', 0) ) {
$object->SetDBField('Status', STATUS_ACTIVE);
}
elseif ( $this->Application->CheckPermission('CATEGORY.REVISION.ADD.PENDING', 0) ) {
$object->SetDBField('Status', STATUS_PENDING);
}
$object->Update();
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Discards user draft
*
* @param kEvent $event
*/
function OnDiscard(&$event)
{
$revision_id = $this->getCurrentDraftRevision($event);
if ( $revision_id ) {
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems($event->Prefix, $event->Special, Array ($revision_id));
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Makes revision live
*
* @param kEvent $event
*/
function OnPublish(&$event)
{
$revision =& $this->Application->recallObject('page-revision.current');
/* @var $revision kDBItem */
if ( !$revision->isLoaded() || $revision->GetDBField('Status') == STATUS_ACTIVE || $revision->GetDBField('IsDraft') ) {
return ;
}
$revision->SetDBField('Status', STATUS_ACTIVE);
$revision->Update();
$event->SetRedirectParam('opener', 'u');
}
/**
* Denies changes made in revision
*
* @param kEvent $event
*/
function OnDecline(&$event)
{
$revision =& $this->Application->recallObject('page-revision.current');
/* @var $revision kDBItem */
if ( !$revision->isLoaded() || $revision->GetDBField('Status') == STATUS_DISABLED || $revision->GetDBField('IsLive') || $revision->GetDBField('IsDraft') ) {
return ;
}
$revision->SetDBField('Status', STATUS_DISABLED);
$revision->Update();
$event->SetRedirectParam('opener', 'u');
}
/**
* Returns revision id of user's draft
*
* @param kEvent $event
* @return int
*/
function getCurrentDraftRevision(&$event)
{
$where_clause = Array (
'IsDraft = 1',
'PageId = ' . $this->Application->GetVar('m_cat_id'),
'CreatedById = ' . $this->Application->RecallVar('user_id'),
);
$sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE (' . implode(') AND (', $where_clause) . ')';
return $this->Conn->GetOne($sql);
}
/**
* Returns next available revision number for current page
*
* @param kEvent $event
* @return int
*/
function getNextAvailableRevision(&$event)
{
$sql = 'SELECT MAX(RevisionNumber)
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE PageId = ' . $this->Application->GetVar('m_cat_id');
$max_revision = (int)$this->Conn->GetOne($sql);
return $max_revision + 1;
}
}
Index: branches/5.2.x/core/units/site_domains/site_domain_eh.php
===================================================================
--- branches/5.2.x/core/units/site_domains/site_domain_eh.php (revision 15064)
+++ branches/5.2.x/core/units/site_domains/site_domain_eh.php (revision 15065)
@@ -1,294 +1,294 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2010 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 SiteDomainEventHandler extends kDBEventHandler {
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent &$event)
{
if ( $event->Name == 'OnItemBuild' ) {
// check permission without using $event->getSection(),
// so first cache rebuild won't lead to "ldefault_Name" field being used
return true;
}
return parent::CheckPermission($event);
}
/**
* Returns ID of site domain, that matches current url
*
* @param kEvent $event
* @return int
* @access public
*/
public function getPassedID(kEvent &$event)
{
if ( $event->Special == 'current' ) {
if ( $this->Application->isAdmin ) {
$event->setEventParam('raise_warnings', 0);
}
else {
if ( PROTOCOL == 'https://' ) {
return $this->querySiteDomain('SSLUrl', rtrim($this->Application->BaseURL(), '/'));
}
return $this->querySiteDomain('DomainName', $_SERVER['HTTP_HOST']);
}
}
return parent::getPassedID($event);
}
function querySiteDomain($field, $value)
{
$site_helper =& $this->Application->recallObject('SiteHelper');
/* @var $site_helper SiteHelper */
$site_domains = $site_helper->getSiteDomains();
$domain_by_name = $site_helper->getDomainByName($field, $value);
$domain_by_ip = $site_helper->getDomainByIP();
if ($domain_by_ip) {
$site_domain = $site_domains[$domain_by_ip];
$redirect_mode = $site_domain['RedirectOnIPMatch'];
if (($redirect_mode == SITE_DOMAIN_REDIRECT_EXTERNAL) && ($domain_by_ip == $domain_by_name)) {
// redirect to external url (when visiting protected domain)
$external_url = $site_domain['ExternalUrl'];
if (preg_match('/^http[s]{0,1}:\/\//', $external_url)) {
$this->Application->Redirect('external:' . $external_url);
}
else {
$this->Application->Redirect('external:' . PROTOCOL . $external_url . $_SERVER['REQUEST_URI']);
}
}
elseif (($redirect_mode == SITE_DOMAIN_REDIRECT_CURRENT) && ($domain_by_ip != $domain_by_name)) {
// redirect to a domain detected by IP (when not already on it)
if ((PROTOCOL == 'https://') && !$site_domain['SSLUrlUsesRegExp'] && $site_domain['SSLUrl']) {
// need to remove sub folder from ssl url
$ssl_url = preg_replace('/^(https:\/\/[^\/]*)(\/.*){0,1}$/', '\\1', $site_domain['SSLUrl']);
$this->Application->Redirect('external:' . $ssl_url . $_SERVER['REQUEST_URI']);
}
elseif ((PROTOCOL == 'http://') && !$site_domain['DomainNameUsesRegExp']) {
$this->Application->Redirect('external:http://' . $site_domain['DomainName'] . $_SERVER['REQUEST_URI']);
}
}
return $domain_by_ip;
}
return $domain_by_name;
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(kEvent &$event)
{
if ( $this->Application->isAdmin ) {
// don't load domain data from cache
parent::LoadItem($event);
return;
}
$object =& $event->getObject();
/* @var $object kDBItem */
$id = (int)$this->getPassedID($event);
if ( $object->isLoaded() && ($object->GetID() == $id) ) {
// object is already loaded by same id
return;
}
$site_helper =& $this->Application->recallObject('SiteHelper');
/* @var $site_helper SiteHelper */
$site_domains = $site_helper->getSiteDomains();
$domain_data = array_key_exists($id, $site_domains) ? $site_domains[$id] : false;
if ( $object->LoadFromHash($domain_data) ) {
$actions =& $this->Application->recallObject('kActions');
/* @var $actions Params */
$actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$object->setID($id);
}
}
/**
* Removes In-Commerce related fields, when it's not installed
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent &$event)
{
parent::OnAfterConfigRead($event);
if (!$this->Application->isModuleEnabled('In-Commerce')) {
$remove_fields = Array (
'BillingCountry', 'ShippingCountry',
'PrimaryCurrencyId', 'Currencies',
'PrimaryPaymentTypeId', 'PaymentTypes'
);
// remove field definitions
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
foreach ($remove_fields as $remove_field) {
unset($fields[$remove_field]);
}
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
// remove grid columns
$grids = $this->Application->getUnitOption($event->Prefix, 'Grids', Array ());
/* @var $grids Array */
foreach ($grids as $grid_name => $grid_info) {
foreach ($remove_fields as $remove_field) {
if (array_key_exists($remove_field, $grid_info['Fields'])) {
unset($grids[$grid_name]['Fields'][$remove_field]);
}
}
}
$this->Application->setUnitOption($event->Prefix, 'Grids', $grids);
}
}
/**
* Delete cached information about site domains
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnSave(&$event)
+ protected function OnSave(kEvent &$event)
{
parent::OnSave($event);
if ( $event->status == kEvent::erSUCCESS ) {
$this->_deleteCache();
}
}
/**
* Deletes cached information about site domains
*/
function _deleteCache()
{
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$this->Application->rebuildCache('master:domains_parsed', kCache::REBUILD_LATER, CacheSettings::$domainsParsedRebuildTime);
}
else {
$this->Application->rebuildDBCache('domains_parsed', kCache::REBUILD_LATER, CacheSettings::$domainsParsedRebuildTime);
}
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls';
$this->Conn->Query($sql);
}
/**
* Sets required fields based on redirect mode
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(kEvent &$event)
{
parent::OnAfterItemLoad($event);
$this->_setRequired($event);
}
/**
* Set's required fields based on redirect mode
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$this->_itemChanged($event);
}
/**
* Set's required fields based on redirect mode
*
* @param kEvent $event
* @return void
* @access protected
*/
- protected function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(kEvent &$event)
{
parent::OnBeforeItemUpdate($event);
$this->_itemChanged($event);
}
/**
* Occurs before item is changed
*
* @param kEvent $event
*/
function _itemChanged(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$email_event_data = $this->Application->GetVar('emailevents_' . $event->Prefix);
$object->SetDBField('DefaultEmailRecipients', $email_event_data[0]['Recipients']);
$this->_setRequired($event);
}
/**
* Set's required fields
*
* @param kEvent $event
*/
function _setRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$redirect_mode = $object->GetDBField('RedirectOnIPMatch');
$object->setRequired('ExternalUrl', $redirect_mode == SITE_DOMAIN_REDIRECT_EXTERNAL);
$object->setRequired('DomainIPRange', $redirect_mode > 0);
}
}
Index: branches/5.2.x/core/units/spam_reports/spam_report_eh.php
===================================================================
--- branches/5.2.x/core/units/spam_reports/spam_report_eh.php (revision 15064)
+++ branches/5.2.x/core/units/spam_reports/spam_report_eh.php (revision 15065)
@@ -1,143 +1,147 @@
<?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 SpamReportEventHandler extends kDBEventHandler {
/**
* Allows to override standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnNewReport' => Array ('self' => true),
'OnDeleteAssocItem' => Array ('self' => 'delete'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Checks permissions
*
* @param kEvent $event
*/
// function CheckPermission(&$event)
// {
// if ( $event->Name == 'OnNewReport' ) {
// $perm_helper =& $this->Application->recallObject('PermissionsHelper');
// /* @var $perm_helper kPermissionsHelper */
//
// return $perm_helper->finalizePermissionCheck($event, $this->Application->LoggedIn());
// }
//
// return parent::CheckPermission($event);
// }
/**
* Prefills missing fields
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(kEvent &$event)
{
parent::OnBeforeItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$item_prefix = $this->Application->GetVar('item_prefix');
$item_id = $this->Application->GetVar($item_prefix . '_id');
if ( $item_id ) {
$object->SetDBField('ItemPrefix', $item_prefix);
$object->SetDBField('ItemId', $item_id);
}
$object->SetDBField('ReportedById', $this->Application->RecallVar('user_id'));
}
/**
* Send e-mail after new spam report was created
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(kEvent &$event)
{
parent::OnAfterItemCreate($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$item_prefix = $object->GetDBField('ItemPrefix');
if ( preg_match('/rev$/', $item_prefix) ) {
$item =& $this->Application->recallObject($item_prefix);
/* @var $item kDBItem */
$object->SetDBField('ItemName', $item->GetDBField('ReviewText'));
}
$this->Application->EmailEventAdmin('SPAM.REPORT');
}
/**
* Sends new spam report
*
* @param kEvent $event
*/
function OnNewReport(&$event)
{
$ajax_form_helper =& $this->Application->recallObject('AjaxFormHelper');
/* @var $ajax_form_helper AjaxFormHelper */
$ajax_form_helper->transitEvent($event, 'OnCreate');
}
/**
* Deletes item, associated with given spam report
*
* @param kEvent $event
*/
function OnDeleteAssocItem(&$event)
{
$temp_handlers = Array ();
$ids = $this->StoreSelectedIDs($event);
$object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
foreach ($ids as $id) {
$object->Load($id);
$item_prefix = $object->GetDBField('ItemPrefix');
if ( !isset($temp_handlers[$item_prefix]) ) {
$temp_handlers[$item_prefix] =& $this->Application->recallObject($item_prefix . '_TempHandler', 'kTempTablesHandler');
}
$temp_handlers[$item_prefix]->DeleteItems($item_prefix, '', Array ($object->GetDBField('ItemId')));
}
$this->clearSelectedIDs($event);
$event->SetRedirectParam('opener', 'u');
}
}
\ No newline at end of file

Event Timeline