Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Feb 6, 9:31 AM

in-portal

Index: branches/unlabeled/unlabeled-1.82.2/core/kernel/db/db_event_handler.php
===================================================================
--- branches/unlabeled/unlabeled-1.82.2/core/kernel/db/db_event_handler.php (nonexistent)
+++ branches/unlabeled/unlabeled-1.82.2/core/kernel/db/db_event_handler.php (revision 7666)
@@ -0,0 +1,2046 @@
+<?php
+
+ define('EH_CUSTOM_PROCESSING_BEFORE',1);
+ define('EH_CUSTOM_PROCESSING_AFTER',2);
+
+ /**
+ * Note:
+ * 1. When adressing variables from submit containing
+ * Prefix_Special as part of their name use
+ * $event->getPrefixSpecial(true) instead of
+ * $event->Prefix_Special as usual. This is due PHP
+ * is converting "." symbols in variable names during
+ * submit info "_". $event->getPrefixSpecial optional
+ * 1st parameter returns correct corrent Prefix_Special
+ * for variables beeing submitted such way (e.g. variable
+ * name that will be converted by PHP: "users.read_only_id"
+ * will be submitted as "users_read_only_id".
+ *
+ * 2. When using $this->Application-LinkVar on variables submitted
+ * from form which contain $Prefix_Special then note 1st item. Example:
+ * LinkVar($event->getPrefixSpecial(true).'_varname',$event->Prefix_Special.'_varname')
+ *
+ */
+
+
+ /**
+ * EventHandler that is used to process
+ * any database related events
+ *
+ */
+ class kDBEventHandler extends kEventHandler {
+
+ /**
+ * Description
+ *
+ * @var kDBConnection
+ * @access public
+ */
+ var $Conn;
+
+ /**
+ * Adds ability to address db connection
+ *
+ * @return kDBEventHandler
+ * @access public
+ */
+ function kDBEventHandler()
+ {
+ parent::kBase();
+ $this->Conn =& $this->Application->GetADODBConnection();
+ }
+
+ /**
+ * Checks permissions of user
+ *
+ * @param kEvent $event
+ */
+ function CheckPermission(&$event)
+ {
+ if (!$this->Application->IsAdmin()) {
+ $allow_events = Array('OnSearch', 'OnSearchReset', 'OnNew');
+ if (in_array($event->Name, $allow_events)) {
+ // allow search on front
+ return true;
+ }
+ }
+
+ $section = $event->getSection();
+ 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');
+ }
+
+ return parent::CheckPermission($event);
+ }
+
+ /**
+ * Allows to override standart permission mapping
+ *
+ */
+ function mapPermissions()
+ {
+ parent::mapPermissions();
+ $permissions = Array(
+ 'OnLoad' => Array('self' => 'view', 'subitem' => 'view'),
+
+ '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'),
+ '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'),
+ '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'),
+
+
+ // 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),
+
+ '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),
+
+ 'OnSearch' => Array('self' => true, 'subitem' => true),
+ 'OnSearchReset' => Array('self' => true, 'subitem' => true),
+
+ 'OnGoBack' => Array('self' => true, 'subitem' => true),
+ );
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ function mapEvents()
+ {
+ $events_map = Array(
+ 'OnRemoveFilters' => 'FilterAction',
+ 'OnApplyFilters' => 'FilterAction',
+ 'OnMassApprove'=>'iterateItems',
+ 'OnMassDecline'=>'iterateItems',
+ 'OnMassMoveUp'=>'iterateItems',
+ 'OnMassMoveDown'=>'iterateItems',
+ );
+
+ $this->eventMethods = array_merge($this->eventMethods, $events_map);
+ }
+
+ /**
+ * Returns ID of current item to be edited
+ * by checking ID passed in get/post as prefix_id
+ * or by looking at first from selected ids, stored.
+ * Returned id is also stored in Session in case
+ * it was explicitly passed as get/post
+ *
+ * @param kEvent $event
+ * @return int
+ */
+ function getPassedID(&$event)
+ {
+ if ($event->getEventParam('raise_warnings') === false) {
+ $event->setEventParam('raise_warnings', 1);
+ }
+
+ // 1. get id from post (used in admin)
+ $ret = $this->Application->GetVar($event->getPrefixSpecial(true).'_id');
+ if($ret) return $ret;
+
+ // 2. get id from env (used in front)
+ $ret = $this->Application->GetVar($event->getPrefixSpecial().'_id');
+ if($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(true).'_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 $ids
+ *
+ * @return Array ids stored
+ */
+ function StoreSelectedIDs(&$event, $ids = null)
+ {
+ $wid = $this->Application->GetTopmostWid($event->Prefix);
+ $session_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
+
+ if (isset($ids)) {
+ // save ids directly if they given
+ $this->Application->StoreVar($session_name, implode(',', $ids));
+ return $ids;
+ }
+
+ $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);
+
+ // 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 <b>'.$event->getPrefixSpecial().'</b> <span class="debug_error">not passed</span>',E_USER_NOTICE);
+ }
+ $this->Application->SetVar($event->getPrefixSpecial(true).'_id', $first_id);
+ return $ret;
+ }
+
+ /**
+ * Returns stored selected ids as an array
+ *
+ * @param kEvent $event
+ * @param bool $from_session return ids from session (written, when editing was started)
+ * @return array
+ */
+ function getSelectedIDs(&$event, $from_session = false)
+ {
+ if ($from_session) {
+ $wid = $this->Application->GetTopmostWid($event->Prefix);
+ $var_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
+ $ret = $this->Application->RecallVar($var_name);
+ }
+ else {
+ $ret = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids');
+ }
+
+ return explode(',', $ret);
+ }
+
+ /**
+ * Returs associative array of submitted fields for current item
+ * Could be used while creating/editing single item -
+ * meaning on any edit form, except grid edit
+ *
+ * @param kEvent $event
+ */
+ function getSubmittedFields(&$event)
+ {
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ $field_values = $items_info ? array_shift($items_info) : Array();
+ return $field_values;
+ }
+
+ /**
+ * Removes any information about current/selected ids
+ * from Application variables and Session
+ *
+ * @param kEvent $event
+ */
+ function clearSelectedIDs(&$event)
+ {
+ $prefix_special = $event->getPrefixSpecial();
+
+ $ids = implode(',', $this->getSelectedIDs($event, true));
+ $event->setEventParam('ids', $ids);
+
+ $wid = $this->Application->GetTopmostWid($event->Prefix);
+ $session_name = rtrim($prefix_special.'_selected_ids_'.$wid, '_');
+
+ $this->Application->RemoveVar($session_name);
+ $this->Application->SetVar($prefix_special.'_selected_ids', '');
+
+ $this->Application->SetVar($prefix_special.'_id', ''); // $event->getPrefixSpecial(true).'_id' too may be
+ }
+
+ /*function SetSaveEvent(&$event)
+ {
+ $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnUpdate');
+ $this->Application->LinkVar($event->Prefix_Special.'_SaveEvent');
+ }*/
+
+ /**
+ * Common builder part for Item & List
+ *
+ * @param kDBBase $object
+ * @param kEvent $event
+ * @access private
+ */
+ function dbBuild(&$object, &$event)
+ {
+ $object->Configure();
+ $this->PrepareObject($object, $event);
+
+ // force live table if specified or is original item
+ $live_table = $event->getEventParam('live_table') || $event->Special == 'original';
+
+ if( $this->UseTempTables($event) && !$live_table )
+ {
+ $object->SwitchToTemp();
+ }
+
+ // This strange constuction creates hidden field for storing event name in form submit
+ // It pass SaveEvent to next screen, otherwise after unsuccsefull create it will try to update rather than create
+ $current_event = $this->Application->GetVar($event->Prefix_Special.'_event');
+// $this->Application->setEvent($event->Prefix_Special, $current_event);
+ $this->Application->setEvent($event->Prefix_Special, '');
+
+ $save_event = $this->UseTempTables($event) && $this->Application->GetTopmostPrefix($event->Prefix) == $event->Prefix ? 'OnSave' : 'OnUpdate';
+ $this->Application->SetVar($event->Prefix_Special.'_SaveEvent',$save_event);
+ }
+
+ /**
+ * Builds item (loads if needed)
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnItemBuild(&$event)
+ {
+ $object =& $event->getObject();
+ $this->dbBuild($object,$event);
+
+ $sql = $this->ItemPrepareQuery($event);
+ $sql = $this->Application->ReplaceLanguageTags($sql);
+ $object->setSelectSQL($sql);
+
+ // 2. loads if allowed
+ $auto_load = $this->Application->getUnitOption($event->Prefix,'AutoLoad');
+ $skip_autload = $event->getEventParam('skip_autoload');
+
+ if($auto_load && !$skip_autload) $this->LoadItem($event);
+
+ $actions =& $this->Application->recallObject('kActions');
+ $actions->Set($event->Prefix_Special.'_GoTab', '');
+
+ $actions->Set($event->Prefix_Special.'_GoId', '');
+ }
+
+ /**
+ * Build subtables array from configs
+ *
+ * @param kEvent $event
+ */
+ function OnTempHandlerBuild(&$event)
+ {
+ $object =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ /* @var $object kTempTablesHandler */
+
+ $object->BuildTables( $event->Prefix, $this->getSelectedIDs($event) );
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ * @return unknown
+ */
+ function UseTempTables(&$event)
+ {
+ $object = &$event->getObject();
+ $top_prefix = $this->Application->GetTopmostPrefix($event->Prefix);
+
+ $var_names = Array (
+ $top_prefix,
+ rtrim($top_prefix.'_'.$event->Special, '_'),
+ rtrim($top_prefix.'.'.$event->Special, '.'),
+ );
+ $var_names = array_unique($var_names);
+
+ $temp_mode = false;
+ foreach ($var_names as $var_name) {
+ $value = $this->Application->GetVar($var_name.'_mode');
+ if (substr($value, 0, 1) == 't') {
+ $temp_mode = true;
+ break;
+ }
+ }
+
+ return $temp_mode;
+ }
+
+ /**
+ * Returns table prefix from event (temp or live)
+ *
+ * @param kEvent $event
+ * @return string
+ * @todo Needed? Should be refactored (by Alex)
+ */
+ function TablePrefix(&$event)
+ {
+ return $this->UseTempTables($event) ? $this->Application->GetTempTablePrefix('prefix:'.$event->Prefix).TABLE_PREFIX : TABLE_PREFIX;
+ }
+
+ /**
+ * Load item if id is available
+ *
+ * @param kEvent $event
+ */
+ function LoadItem(&$event)
+ {
+ $object =& $event->getObject();
+ $id = $this->getPassedID($event);
+ if ($object->Load($id) )
+ {
+ $actions =& $this->Application->recallObject('kActions');
+ $actions->Set($event->Prefix_Special.'_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);
+ }
+ }
+
+ /**
+ * Builds list
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnListBuild(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBList */
+
+ $this->dbBuild($object,$event);
+
+ $sql = $this->ListPrepareQuery($event);
+ $sql = $this->Application->ReplaceLanguageTags($sql);
+ $object->setSelectSQL($sql);
+
+ $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);
+
+// $object->CalculateTotals(); // Now called in getTotals to avoid extra query
+
+ $actions =& $this->Application->recallObject('kActions');
+ $actions->Set('remove_specials['.$event->Prefix_Special.']', '0');
+ $actions->Set($event->Prefix_Special.'_GoTab', '');
+ }
+
+
+ /**
+ * Get's special of main item for linking with subitem
+ *
+ * @param kEvent $event
+ * @return string
+ */
+ function getMainSpecial(&$event)
+ {
+ $special = $event->getEventParam('main_special');
+ if($special === false || $special == '$main_special')
+ {
+ $special = $event->Special;
+ }
+ return $special;
+ }
+
+ /**
+ * Apply any custom changes to list's sql query
+ *
+ * @param kEvent $event
+ * @access protected
+ * @see OnListBuild
+ */
+ function SetCustomQuery(&$event)
+ {
+
+ }
+
+ /**
+ * Set's new perpage for grid
+ *
+ * @param kEvent $event
+ */
+ function OnSetPerPage(&$event)
+ {
+ $per_page = $this->Application->GetVar($event->getPrefixSpecial(true).'_PerPage');
+ $this->Application->StoreVar($event->getPrefixSpecial().'_PerPage', $per_page);
+
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
+ $this->Application->StorePersistentVar($event->getPrefixSpecial().'_PerPage.'.$view_name, $per_page);
+ }
+
+ /**
+ * Set's correct page for list
+ * based on data provided with event
+ *
+ * @param kEvent $event
+ * @access private
+ * @see OnListBuild
+ */
+ function SetPagination(&$event)
+ {
+ // get PerPage (forced -> session -> config -> 10)
+ $per_page = $this->getPerPage($event);
+
+ $object =& $event->getObject();
+ $object->SetPerPage($per_page);
+ $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1);
+
+ $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page');
+ if (!$page) {
+ $page = $this->Application->GetVar($event->getPrefixSpecial(true).'_Page');
+ }
+ if (!$page) {
+ $page = $this->Application->RecallVar($event->getPrefixSpecial().'_Page');
+ }
+ else {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page);
+ }
+
+ if( !$event->getEventParam('skip_counting') )
+ {
+ $pages = $object->GetTotalPages();
+ if($page > $pages)
+ {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1);
+ $page = 1;
+ }
+ }
+
+ /*$per_page = $event->getEventParam('per_page');
+ if ($per_page == 'list_next') {
+
+ $cur_page = $page;
+ $cur_per_page = $per_page;
+
+ $object->SetPerPage(1);
+
+ $object =& $this->Application->recallObject($event->Prefix);
+ $cur_item_index = $object->CurrentIndex;
+
+ $page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1;
+ $object->SetPerPage(1);
+ }*/
+
+ $object->SetPage($page);
+ }
+
+ /**
+ * Returns current per-page setting for list
+ *
+ * @param kEvent $event
+ * @return int
+ */
+ function getPerPage(&$event)
+ {
+ // 1. per-page is passed as tag parameter to PrintList, InitList, etc.
+ $per_page = $event->getEventParam('per_page');
+
+ /*if ($per_page == 'list_next') {
+ $per_page = '';
+ }*/
+
+ // 2. per-page variable name is store into config variable
+ $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
+ if ($config_mapping) {
+ 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;
+ }
+ }
+
+ if (!$per_page) {
+ // per-page is stored to persistent session
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
+ $per_page = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_PerPage.'.$view_name);
+
+ if (!$per_page) {
+ // per-page is stored to current session
+ $per_page = $this->Application->RecallVar($event->getPrefixSpecial().'_PerPage');
+ }
+
+ if (!$per_page) {
+ if ($config_mapping) {
+ if (!isset($config_mapping['PerPage'])) {
+ trigger_error('Incorrect mapping of <span class="debug_error">PerPage</span> key in config for prefix <b>'.$event->Prefix.'</b>', E_USER_WARNING);
+ }
+ $per_page = $this->Application->ConfigValue($config_mapping['PerPage']);
+ }
+ if (!$per_page) {
+ // none of checked above per-page locations are useful, then try default value
+ $per_page = 10;
+ }
+ }
+ }
+
+ return $per_page;
+ }
+
+ /**
+ * Set's correct sorting for list
+ * based on data provided with event
+ *
+ * @param kEvent $event
+ * @access private
+ * @see OnListBuild
+ */
+ function SetSorting(&$event)
+ {
+ $event->setPseudoClass('_List');
+ $object =& $event->getObject();
+
+ $cur_sort1 = $this->Application->RecallVar($event->Prefix_Special.'_Sort1');
+ $cur_sort1_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort1_Dir');
+ $cur_sort2 = $this->Application->RecallVar($event->Prefix_Special.'_Sort2');
+ $cur_sort2_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort2_Dir');
+
+
+ $sorting_configs = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
+ $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings');
+ $sorting_prefix = getArrayValue($list_sortings, $event->Special) ? $event->Special : '';
+
+ $tag_sort_by = $event->getEventParam('sort_by');
+ if ($tag_sort_by) {
+ if ($tag_sort_by == 'random') {
+ $by = 'RAND()';
+ $dir = '';
+ }
+ else {
+ list($by, $dir) = explode(',', $tag_sort_by);
+ }
+ $object->AddOrderField($by, $dir);
+ }
+
+ if ($sorting_configs && isset ($sorting_configs['DefaultSorting1Field'])){
+ $list_sortings[$sorting_prefix]['Sorting'] = Array(
+ $this->Application->ConfigValue($sorting_configs['DefaultSorting1Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting1Dir']),
+ $this->Application->ConfigValue($sorting_configs['DefaultSorting2Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting2Dir']),
+ );
+ }
+
+ // Use default if not specified
+ if ( !$cur_sort1 || !$cur_sort1_dir)
+ {
+ if ( $sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting') ) {
+ reset($sorting);
+ $cur_sort1 = key($sorting);
+ $cur_sort1_dir = current($sorting);
+ if (next($sorting)) {
+ $cur_sort2 = key($sorting);
+ $cur_sort2_dir = current($sorting);
+ }
+ }
+ }
+
+ if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) {
+ foreach ($forced_sorting as $field => $dir) {
+ $object->AddOrderField($field, $dir);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ /**
+ * Add filters found in session
+ *
+ * @param kEvent $event
+ */
+ function AddFilters(&$event)
+ {
+ $object =& $event->getObject();
+
+ $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') ? HAVING_FILTER : WHERE_FILTER;
+ $filter_value = str_replace(EDIT_MARK, $edit_mark, $filter_params['value']);
+ $object->addFilter($filter_field, $filter_value, $filter_type, 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') ? HAVING_FILTER : WHERE_FILTER;
+ $filter_value = str_replace(EDIT_MARK, $edit_mark, $field_options['value']);
+ $object->addFilter($field_name, $filter_value, $filter_type, FLT_CUSTOM);
+ }
+ }
+ }
+ }
+
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
+ if($view_filter)
+ {
+ $view_filter = unserialize($view_filter);
+ $temp_filter =& $this->Application->makeClass('kMultipleFilter');
+ $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('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'] , FLT_VIEW);
+ $group_key++;
+ }
+ }
+ }
+
+ /**
+ * Set's new sorting for list
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnSetSorting(&$event)
+ {
+ $cur_sort1 = $this->Application->RecallVar($event->Prefix_Special.'_Sort1');
+ $cur_sort1_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort1_Dir');
+
+ $use_double_sorting = $this->Application->ConfigValue('UseDoubleSorting') !== false ? $this->Application->ConfigValue('UseDoubleSorting') : true;
+
+ if ($use_double_sorting) {
+ $cur_sort2 = $this->Application->RecallVar($event->Prefix_Special.'_Sort2');
+ $cur_sort2_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort2_Dir');
+ }
+
+ $passed_sort1 = $this->Application->GetVar($event->getPrefixSpecial(true).'_Sort1');
+ if ($cur_sort1 == $passed_sort1) {
+ $cur_sort1_dir = $cur_sort1_dir == 'asc' ? 'desc' : 'asc';
+ }
+ else {
+ if ($use_double_sorting) {
+ $cur_sort2 = $cur_sort1;
+ $cur_sort2_dir = $cur_sort1_dir;
+ }
+ $cur_sort1 = $passed_sort1;
+ $cur_sort1_dir = 'asc';
+ }
+
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort1', $cur_sort1);
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort1_Dir', $cur_sort1_dir);
+ if ($use_double_sorting) {
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort2', $cur_sort2);
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort2_Dir', $cur_sort2_dir);
+ }
+ }
+
+ /**
+ * Set sorting directly to session
+ *
+ * @param kEvent $event
+ */
+ function OnSetSortingDirect(&$event)
+ {
+ $combined = $this->Application->GetVar($event->getPrefixSpecial(true).'_CombinedSorting');
+ if ($combined) {
+ list($field,$dir) = explode('|',$combined);
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort1', $field);
+ $this->Application->StoreVar($event->Prefix_Special.'_Sort1_Dir', $dir);
+ return;
+ }
+
+ $field_pos = $this->Application->GetVar($event->getPrefixSpecial(true).'_SortPos');
+ $this->Application->LinkVar( $event->getPrefixSpecial(true).'_Sort'.$field_pos, $event->Prefix_Special.'_Sort'.$field_pos);
+ $this->Application->LinkVar( $event->getPrefixSpecial(true).'_Sort'.$field_pos.'_Dir', $event->Prefix_Special.'_Sort'.$field_pos.'_Dir');
+ }
+
+ /**
+ * Reset grid sorting to default (from config)
+ *
+ * @param kEvent $event
+ */
+ function OnResetSorting(&$event)
+ {
+ $this->Application->RemoveVar($event->Prefix_Special.'_Sort1');
+ $this->Application->RemoveVar($event->Prefix_Special.'_Sort1_Dir');
+ $this->Application->RemoveVar($event->Prefix_Special.'_Sort2');
+ $this->Application->RemoveVar($event->Prefix_Special.'_Sort2_Dir');
+ }
+
+ /**
+ * Creates needed sql query to load item,
+ * if no query is defined in config for
+ * special requested, then use default
+ * query
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function ItemPrepareQuery(&$event)
+ {
+ $sqls = $this->Application->getUnitOption($event->Prefix,'ItemSQLs');
+ return isset($sqls[$event->Special]) ? $sqls[$event->Special] : $sqls[''];
+ }
+
+ /**
+ * Creates needed sql query to load list,
+ * if no query is defined in config for
+ * special requested, then use default
+ * query
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function ListPrepareQuery(&$event)
+ {
+ $sqls = $this->Application->getUnitOption($event->Prefix,'ListSQLs');
+ return isset( $sqls[$event->Special] ) ? $sqls[$event->Special] : $sqls[''];
+ }
+
+ /**
+ * Apply custom processing to item
+ *
+ * @param kEvent $event
+ */
+ function customProcessing(&$event, $type)
+ {
+
+ }
+
+ /* Edit Events mostly used in Admin */
+
+ /**
+ * Creates new kDBItem
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnCreate(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if($items_info)
+ {
+ list($id,$field_values) = each($items_info);
+ $object->SetFieldsFromHash($field_values);
+ }
+
+ $this->customProcessing($event,'before');
+
+ //look at kDBItem' Create for ForceCreateId description, it's rarely used and is NOT set by default
+ if( $object->Create($event->getEventParam('ForceCreateId')) )
+ {
+ if( $object->IsTempTable() ) $object->setTempID();
+ $this->customProcessing($event,'after');
+ $event->status=erSUCCESS;
+ $event->redirect_params = Array('opener'=>'u');
+ }
+ else
+ {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate');
+ $object->setID($id);
+ }
+ }
+
+ /**
+ * Updates kDBItem
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnUpdate(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if($items_info)
+ {
+ foreach($items_info as $id => $field_values)
+ {
+ $object->Load($id);
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
+ if( $object->Update($id) )
+ {
+ $this->customProcessing($event, 'after');
+ $event->status=erSUCCESS;
+ }
+ else
+ {
+ $event->status=erFAIL;
+ $event->redirect=false;
+ break;
+ }
+ }
+ }
+ $event->redirect_params = Array('opener'=>'u');
+ }
+
+ /**
+ * Delete's kDBItem object
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnDelete(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object->ID = $this->getPassedID($event);
+ if( $object->Delete() )
+ {
+ $event->status = erSUCCESS;
+ }
+ else
+ {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ }
+ }
+
+ /**
+ * Prepares new kDBItem object
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnNew(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object->setID(0);
+ $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate');
+
+ $table_info = $object->getLinkedInfo();
+ $object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']);
+
+ $event->redirect = false;
+ }
+
+ /**
+ * Cancel's kDBItem Editing/Creation
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnCancel(&$event)
+ {
+ $object =& $event->getObject(Array('skip_autoload' => true));
+
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+ if ($items_info) {
+ $delete_ids = Array();
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', '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->DeleteItems($event->Prefix, $event->Special, $delete_ids);
+ }
+ }
+
+ $event->redirect_params = Array('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
+ */
+ function OnMassDelete(&$event)
+ {
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ return;
+ }
+
+ $event->status=erSUCCESS;
+
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ $ids = $this->StoreSelectedIDs($event);
+
+ $event->setEventParam('ids', $ids);
+ $this->customProcessing($event, 'before');
+ $ids = $event->getEventParam('ids');
+
+ if($ids)
+ {
+ $temp->DeleteItems($event->Prefix, $event->Special, $ids);
+ }
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Sets window id (of first opened edit window) to temp mark in uls
+ *
+ * @param kEvent $event
+ */
+ function setTempWindowID(&$event)
+ {
+ $mode = $this->Application->GetVar($event->Prefix.'_mode');
+ if ($mode == 't') {
+ $wid = $this->Application->GetVar('m_wid');
+ $this->Application->SetVar($event->Prefix.'_mode', 't'.$wid);
+ }
+ }
+
+ /**
+ * Prepare temp tables and populate it
+ * with items selected in the grid
+ *
+ * @param kEvent $event
+ */
+ function OnEdit(&$event)
+ {
+ $this->setTempWindowID($event);
+ $this->StoreSelectedIDs($event);
+
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ /* @var $temp kTempTablesHandler */
+
+ $temp->PrepareEdit();
+
+ $event->redirect=false;
+ }
+
+ /**
+ * Saves content of temp table into live and
+ * redirects to event' default redirect (normally grid template)
+ *
+ * @param kEvent $event
+ */
+ function OnSave(&$event)
+ {
+ $event->CallSubEvent('OnPreSave');
+ if ($event->status == erSUCCESS) {
+ $skip_master = false;
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ $live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array());
+ if ($live_ids) {
+ // ensure, that newly created item ids are avalable as if they were selected from grid
+ // NOTE: only works if main item has subitems !!!
+ $this->StoreSelectedIDs($event, $live_ids);
+ }
+ }
+ $this->clearSelectedIDs($event);
+
+ $event->redirect_params = Array('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', '');
+ }
+ }
+
+ /**
+ * Cancels edit
+ * Removes all temp tables and clears selected ids
+ *
+ * @param kEvent $event
+ */
+ function OnCancelEdit(&$event)
+ {
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ $temp->CancelEdit();
+
+ $this->clearSelectedIDs($event);
+ $event->redirect_params = Array('opener'=>'u');
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
+ }
+
+
+ /**
+ * Allows to determine if we are creating new item or editing already created item
+ *
+ * @param kEvent $event
+ * @return bool
+ */
+ function isNewItemCreate(&$event)
+ {
+ $event->setEventParam('raise_warnings', 0);
+ $object =& $event->getObject();
+ return !$object->IsLoaded();
+
+// $item_id = $this->getPassedID($event);
+// return ($item_id == '') ? true : false;
+ }
+
+ /**
+ * Saves edited item into temp table
+ * If there is no id, new item is created in temp table
+ *
+ * @param kEvent $event
+ */
+ function OnPreSave(&$event)
+ {
+ //$event->redirect = false;
+ // if there is no id - it means we need to create an item
+ if (is_object($event->MasterEvent)) {
+ $event->MasterEvent->setEventParam('IsNew',false);
+ }
+
+ if ($this->isNewItemCreate($event)) {
+ $event->CallSubEvent('OnPreSaveCreated');
+ if (is_object($event->MasterEvent)) {
+ $event->MasterEvent->setEventParam('IsNew',true);
+ }
+ return;
+ }
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info) {
+ foreach ($items_info as $id => $field_values) {
+ $object->SetDefaultValues();
+ $object->Load($id);
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
+ if( $object->Update($id) )
+ {
+ $this->customProcessing($event, 'after');
+ $event->status=erSUCCESS;
+ }
+ else {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Saves edited item in temp table and loads
+ * item with passed id in current template
+ * Used in Prev/Next buttons
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndGo(&$event)
+ {
+ $event->CallSubEvent('OnPreSave');
+ if ($event->status==erSUCCESS) {
+ $event->redirect_params[$event->getPrefixSpecial(true).'_id'] = $this->Application->GetVar($event->Prefix_Special.'_GoId');
+ }
+ }
+
+ /**
+ * Saves edited item in temp table and goes
+ * to passed tabs, by redirecting to it with OnPreSave event
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndGoToTab(&$event)
+ {
+ $event->CallSubEvent('OnPreSave');
+ if ($event->status==erSUCCESS) {
+ $event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
+ }
+ }
+
+ /**
+ * Saves editable list and goes to passed tab,
+ * by redirecting to it with empty event
+ *
+ * @param kEvent $event
+ */
+ function OnUpdateAndGoToTab(&$event)
+ {
+ $event->setPseudoClass('_List');
+ $event->CallSubEvent('OnUpdate');
+ if ($event->status==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
+ */
+ function OnPreCreate(&$event)
+ {
+ $this->setTempWindowID($event);
+ $this->clearSelectedIDs($event);
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
+ $temp->PrepareEdit();
+
+ $object->setID(0);
+ $this->Application->SetVar($event->getPrefixSpecial().'_id',0);
+ $this->Application->SetVar($event->getPrefixSpecial().'_PreCreate', 1);
+
+ $event->redirect=false;
+ }
+
+ /**
+ * Creates a new item in temp table and
+ * stores item id in App vars and Session on succsess
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveCreated(&$event)
+ {
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if($items_info) $field_values = array_shift($items_info);
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object->SetFieldsFromHash($field_values);
+
+ $this->customProcessing($event, 'before');
+
+ if( $object->Create() )
+ {
+ $this->customProcessing($event, 'after');
+ $event->redirect_params[$event->getPrefixSpecial(true).'_id'] = $object->GetId();
+ $event->status=erSUCCESS;
+ }
+ else
+ {
+ $event->status=erFAIL;
+ $event->redirect=false;
+ $object->setID(0);
+ }
+
+ }
+
+ function OnReset(&$event)
+ {
+ //do nothing - should reset :)
+ if ($this->isNewItemCreate($event)) {
+ // just reset id to 0 in case it was create
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object->setID(0);
+ $this->Application->SetVar($event->getPrefixSpecial().'_id',0);
+ }
+ }
+
+ /**
+ * Apply same processing to each item beeing selected in grid
+ *
+ * @param kEvent $event
+ * @access private
+ */
+ function iterateItems(&$event)
+ {
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ return;
+ }
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $ids = $this->StoreSelectedIDs($event);
+
+ if ($ids) {
+ $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') );
+
+ 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('Priority', $object->GetDBField('Priority') + 1);
+ break;
+
+ case 'OnMassMoveDown':
+ $object->SetDBField('Priority', $object->GetDBField('Priority') - 1);
+ break;
+ }
+
+ if ($object->Update()) {
+ $event->status = erSUCCESS;
+ }
+ else {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function OnMassClone(&$event)
+ {
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ return;
+ }
+
+ $event->status = erSUCCESS;
+
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ $ids = $this->StoreSelectedIDs($event);
+
+ if ($ids) {
+ $temp->CloneItems($event->Prefix, $event->Special, $ids);
+ }
+
+ $this->clearSelectedIDs($event);
+ }
+
+ function check_array($records, $field, $value)
+ {
+ foreach ($records as $record) {
+ if ($record[$field] == $value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function OnPreSavePopup(&$event)
+ {
+ $object =& $event->getObject();
+ $this->RemoveRequiredFields($object);
+ $event->CallSubEvent('OnPreSave');
+
+ $this->finalizePopup($event);
+ }
+
+
+/* End of Edit events */
+
+ // III. Events that allow to put some code before and after Update,Load,Create and Delete methods of item
+
+ /**
+ * Occurse before loading item, 'id' parameter
+ * allows to get id of item beeing loaded
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnBeforeItemLoad(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse after loading item, 'id' parameter
+ * allows to get id of item that was loaded
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnAfterItemLoad(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse before creating item
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnBeforeItemCreate(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse after creating item
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnAfterItemCreate(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse before updating item
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnBeforeItemUpdate(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse after updating item
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnAfterItemUpdate(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse before deleting item, id of item beeing
+ * deleted is stored as 'id' event param
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnBeforeItemDelete(&$event)
+ {
+
+ }
+
+ /**
+ * Occurse after deleting item, id of deleted item
+ * is stored as 'id' param of event
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function OnAfterItemDelete(&$event)
+ {
+
+ }
+
+ /**
+ * Occurs after successful item validation
+ *
+ * @param kEvent $event
+ */
+ function OnAfterItemValidate(&$event)
+ {
+
+ }
+
+ /**
+ * Occures after an item has been copied to temp
+ * Id of copied item is passed as event' 'id' param
+ *
+ * @param kEvent $event
+ */
+ function OnAfterCopyToTemp(&$event)
+ {
+
+ }
+
+ /**
+ * Occures before an item is deleted from live table when copying from temp
+ * (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
+ */
+ function OnBeforeDeleteFromLive(&$event)
+ {
+
+ }
+
+ /**
+ * Occures before an item is copied to live table (after all foreign keys have been updated)
+ * Id of item being copied is passed as event' 'id' param
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeCopyToLive(&$event)
+ {
+
+ }
+
+ /**
+ * !!! NOT FULLY IMPLEMENTED - SEE TEMP HANDLER COMMENTS (search by event name)!!!
+ * Occures after an item has been copied to live table
+ * Id of copied item is passed as event' 'id' param
+ *
+ * @param kEvent $event
+ */
+ function OnAfterCopyToLive(&$event)
+ {
+
+ }
+
+ /**
+ * Occures before an item is cloneded
+ * Id of ORIGINAL item is passed as event' 'id' param
+ * Do not call object' Update method in this event, just set needed fields!
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeClone(&$event)
+ {
+
+ }
+
+ /**
+ * Occures after an item has been cloned
+ * Id of newly created item is passed as event' 'id' param
+ *
+ * @param kEvent $event
+ */
+ function OnAfterClone(&$event)
+ {
+
+ }
+
+ /**
+ * Ensures that popup will be closed automatically
+ * and parent window will be refreshed with template
+ * passed
+ *
+ * @param kEvent $event
+ * @access public
+ */
+ function finalizePopup(&$event)
+ {
+ $event->SetRedirectParam('opener', 'u');
+
+
+
+ /*return ;
+
+ // 2. substitute opener
+ $opener_stack = $this->Application->RecallVar('opener_stack');
+ $opener_stack = $opener_stack ? unserialize($opener_stack) : Array();
+ //array_pop($opener_stack);
+
+ $t = $this->Application->RecallVar('return_template');
+ $this->Application->RemoveVar('return_template');
+
+ // restore original "m" prefix all params, that have values before opening selector
+ $return_m = $this->Application->RecallVar('return_m');
+ $this->Application->RemoveVar('return_m');
+ $this->Application->HttpQuery->parseEnvPart($return_m);
+
+ $pass_events = $event->getEventParam('pass_events');
+ $redirect_params = array_merge_recursive2($event->redirect_params, Array('m_opener' => 'u', '__URLENCODE__' => 1));
+
+ $new_level = 'index.php|'.ltrim($this->Application->BuildEnv($t, $redirect_params, 'all', $pass_events), ENV_VAR_NAME.'=');
+ array_push($opener_stack, $new_level);
+ $this->Application->StoreVar('opener_stack', serialize($opener_stack));*/
+ }
+
+
+ /**
+ * Create search filters based on search query
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnSearch(&$event)
+ {
+ $event->setPseudoClass('_List');
+
+ $search_helper =& $this->Application->recallObject('SearchHelper');
+ $search_helper->performSearch($event);
+ }
+
+ /**
+ * Clear search keywords
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnSearchReset(&$event)
+ {
+ $search_helper =& $this->Application->recallObject('SearchHelper');
+ $search_helper->resetSearch($event);
+ }
+
+ /**
+ * Set's new filter value (filter_id meaning from config)
+ *
+ * @param kEvent $event
+ */
+ function OnSetFilter(&$event)
+ {
+ $filter_id = $this->Application->GetVar('filter_id');
+ $filter_value = $this->Application->GetVar('filter_value');
+
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
+ $view_filter = $view_filter ? unserialize($view_filter) : Array();
+
+ $view_filter[$filter_id] = $filter_value;
+
+ $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
+ }
+
+ function OnSetFilterPattern(&$event)
+ {
+ $filters = $this->Application->GetVar($event->getPrefixSpecial(true).'_filters');
+ if (!$filters) return ;
+
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
+ $view_filter = $view_filter ? unserialize($view_filter) : Array();
+
+ $filters = explode(',', $filters);
+ foreach ($filters as $a_filter) {
+ list($id, $value) = explode('=', $a_filter);
+ $view_filter[$id] = $value;
+ }
+ $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
+ $event->redirect = false;
+ }
+
+ /**
+ * Add/Remove all filters applied to list from "View" menu
+ *
+ * @param kEvent $event
+ */
+ function FilterAction(&$event)
+ {
+ $view_filter = Array();
+ $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
+ switch ($event->Name)
+ {
+ case 'OnRemoveFilters':
+ $filter_value = 1;
+ break;
+
+ case 'OnApplyFilters':
+ $filter_value = 0;
+ break;
+ }
+
+ foreach($filter_menu['Filters'] as $filter_key => $filter_params)
+ {
+ if(!$filter_params) continue;
+ $view_filter[$filter_key] = $filter_value;
+ }
+ $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndOpenTranslator(&$event)
+ {
+ $this->Application->SetVar('allow_translation', true);
+ $object =& $event->getObject();
+ $this->RemoveRequiredFields($object);
+ $event->CallSubEvent('OnPreSave');
+
+ if ($event->status == 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));
+ $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');
+ $event->redirect_params = Array('pass'=>'all,trans,'.$this->Application->GetVar('translator_prefixes'),
+ $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'),
+ );
+
+ // 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'));
+ }
+ }
+
+ function RemoveRequiredFields(&$object)
+ {
+ // making all field non-required to achieve successful presave
+ foreach($object->Fields as $field => $options)
+ {
+ if(isset($options['required']))
+ {
+ unset($object->Fields[$field]['required']);
+ }
+ }
+ }
+
+ /**
+ * Dynamically fills customdata config
+ *
+ * @param kEvent $event
+ */
+ function OnCreateCustomFields(&$event)
+ {
+ $main_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
+ if (!$main_prefix) return false;
+ $item_type = $this->Application->getUnitOption($main_prefix, 'ItemType');
+ if (!$item_type) {
+ // no main config of such type
+ return false;
+ }
+
+ // 1. get custom field information
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'CustomField
+ WHERE Type = '.$item_type.'
+ ORDER BY CustomFieldId';
+ $custom_fields = $this->Conn->Query($sql, 'CustomFieldId');
+ if (!$custom_fields) {
+ // config doesn't have custom fields
+ return false;
+ }
+
+ // 2. create fields (for customdata item)
+ $fields = $this->Application->getUnitOption($event->Prefix, 'Fields', Array());
+ $field_options = Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'not_null' => 1, 'db_type' => 'text', 'default' => '');
+ foreach ($custom_fields as $custom_id => $custom_params) {
+ if (isset($fields['cust_'.$custom_id])) continue;
+ $fields['cust_'.$custom_id] = $field_options;
+ }
+ $this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
+
+ // 3. create virtual & calculated fields (for main item)
+ $calculated_fields = Array();
+ $virtual_fields = $this->Application->getUnitOption($main_prefix, 'VirtualFields', Array());
+
+ $cf_helper =& $this->Application->recallObject('InpCustomFieldsHelper');
+ $field_options = Array('type' => 'string', 'not_null' => 1, 'default' => '');
+ $ml_formatter =& $this->Application->recallObject('kMultiLanguage');
+
+ foreach ($custom_fields as $custom_id => $custom_params) {
+ switch ($custom_params['ElementType']) {
+ case 'date':
+ case 'datetime':
+ unset($field_options['options']);
+ $field_options['formatter'] = 'kDateFormatter';
+ break;
+
+ case 'select':
+ case 'radio':
+ if ($custom_params['ValueList']) {
+ $field_options['options'] = $cf_helper->GetValuesHash($custom_params['ValueList']);
+ $field_options['formatter'] = 'kOptionsFormatter';
+ }
+ break;
+
+ default:
+ unset($field_options['options'], $field_options['formatter']);
+ break;
+ }
+
+ $custom_name = $custom_params['FieldName'];
+ $calculated_fields['cust_'.$custom_name] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id);
+ if (!isset($virtual_fields['cust_'.$custom_name])) {
+ $virtual_fields['cust_'.$custom_name] = Array();
+ }
+ $virtual_fields['cust_'.$custom_name] = array_merge_recursive2($field_options, $virtual_fields['cust_'.$custom_name]);
+ $custom_fields[$custom_id] = $custom_name;
+ }
+
+ $config_calculated_fields = $this->Application->getUnitOption($main_prefix, 'CalculatedFields', Array());
+ foreach ($config_calculated_fields as $special => $special_fields) {
+ $config_calculated_fields[$special] = array_merge_recursive2($config_calculated_fields[$special], $calculated_fields);
+ }
+ $this->Application->setUnitOption($main_prefix, 'CalculatedFields', $config_calculated_fields);
+
+ $this->Application->setUnitOption($main_prefix, 'CustomFields', $custom_fields);
+ $this->Application->setUnitOption($main_prefix, 'VirtualFields', $virtual_fields);
+ }
+
+ /**
+ * Saves selected user in needed field
+ *
+ * @param kEvent $event
+ */
+ function OnSelectUser(&$event)
+ {
+ $items_info = $this->Application->GetVar('u');
+ if ($items_info) {
+ $user_id = array_shift( array_keys($items_info) );
+
+ $object =& $event->getObject();
+ $this->RemoveRequiredFields($object);
+
+ $is_new = !$object->isLoaded();
+ $is_main = substr($this->Application->GetVar($event->Prefix.'_mode'), 0, 1) == 't';
+
+ if ($is_new) {
+ $new_event = $is_main ? 'OnPreCreate' : 'OnNew';
+ $event->CallSubEvent($new_event);
+ }
+
+ $object->SetDBField($this->Application->RecallVar('dst_field'), $user_id);
+
+ if ($is_new) {
+ $object->Create();
+ if (!$is_main && $object->IsTempTable()) {
+ $object->setTempID();
+ }
+ }
+ else {
+ $object->Update();
+ }
+ }
+
+ $event->SetRedirectParam($event->getPrefixSpecial().'_id', $object->GetID());
+ $this->finalizePopup($event);
+ }
+
+
+/** EXPORT RELATED **/
+
+ /**
+ * Shows export dialog
+ *
+ * @param kEvent $event
+ */
+ function OnExport(&$event)
+ {
+ $this->StoreSelectedIDs($event);
+ $selected_ids = $this->getSelectedIDs($event);
+
+ if (implode(',', $selected_ids) == '') {
+ // K4 fix when no ids found bad selected ids array is formed
+ $selected_ids = false;
+ }
+
+ $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
+
+ $export_t = $this->Application->GetVar('export_template');
+ $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');
+ $event->redirect = $export_t ? $export_t : $export_helper->getModuleFolder($event).'/export';
+
+ list($index_file, $env) = explode('|', $this->Application->RecallVar('last_template'));
+ $finish_url = $this->Application->BaseURL('/admin').$index_file.'?'.ENV_VAR_NAME.'='.$env;
+ $this->Application->StoreVar('export_finish_url', $finish_url);
+
+ $redirect_params = Array(
+ $this->Prefix.'.export_event' => 'OnNew',
+ 'pass' => 'all,'.$this->Prefix.'.export');
+
+ $event->setRedirectParams($redirect_params);
+ }
+
+ /**
+ * Apply some special processing to
+ * object beeing recalled before using
+ * it in other events that call prepareObject
+ *
+ * @param Object $object
+ * @param kEvent $event
+ * @access protected
+ */
+ function prepareObject(&$object, &$event)
+ {
+ if ($event->Special == 'export' || $event->Special == 'import')
+ {
+ $export_helper =& $this->Application->recallObject('CatItemExportHelper');
+ $export_helper->prepareExportColumns($event);
+ }
+ }
+
+ /**
+ * Returns specific to each item type columns only
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function getCustomExportColumns(&$event)
+ {
+ return Array();
+ }
+
+ /**
+ * Export form validation & processing
+ *
+ * @param kEvent $event
+ */
+ function OnExportBegin(&$event)
+ {
+ $export_helper =& $this->Application->recallObject('CatItemExportHelper');
+ /* @var $export_helper kCatDBItemExportHelper */
+ $export_helper->OnExportBegin($event);
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function OnExportCancel(&$event)
+ {
+ $this->OnGoBack($event);
+ }
+
+ /**
+ * Allows configuring export options
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeExportBegin(&$event)
+ {
+
+ }
+
+ function OnDeleteExportPreset(&$event)
+ {
+ $object =& $event->GetObject();
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if($items_info)
+ {
+ list($id,$field_values) = each($items_info);
+ $preset_key = $field_values['ExportPresets'];
+
+ $user =& $this->Application->recallObject('u');
+ $export_settings = $user->getPersistantVar('export_settings');
+ if (!$export_settings) return ;
+ $export_settings = unserialize($export_settings);
+ if (!isset($export_settings[$event->Prefix])) return ;
+
+ $to_delete = '';
+ $export_presets = array(''=>'');
+ foreach ($export_settings[$event->Prefix] as $key => $val) {
+ if (implode('|', $val['ExportColumns']) == $preset_key) {
+ $to_delete = $key;
+ break;
+ }
+ }
+ if ($to_delete) {
+ unset($export_settings[$event->Prefix][$to_delete]);
+ $user->setPersistantVar('export_settings', serialize($export_settings));
+ }
+ }
+ }
+
+ /**
+ * Saves changes & changes language
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndChangeLanguage(&$event)
+ {
+ $event->CallSubEvent('OnPreSave');
+
+ if ($event->status == erSUCCESS) {
+ $this->Application->SetVar('m_lang', $this->Application->GetVar('language'));
+ }
+ }
+
+ }
+
+
+?>
\ No newline at end of file
Property changes on: branches/unlabeled/unlabeled-1.82.2/core/kernel/db/db_event_handler.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.82
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property

Event Timeline