Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Tue, Jun 24, 11:28 PM

in-portal

Index: branches/unlabeled/unlabeled-1.75.2/core/kernel/db/db_event_handler.php
===================================================================
--- branches/unlabeled/unlabeled-1.75.2/core/kernel/db/db_event_handler.php (nonexistent)
+++ branches/unlabeled/unlabeled-1.75.2/core/kernel/db/db_event_handler.php (revision 6453)
@@ -0,0 +1,1864 @@
+<?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'),
+
+ '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'),
+ 'OnEdit' => Array('self' => 'edit|edit.pending'),
+
+
+
+
+ // theese event do not harm, but just in case check them too :)
+ 'OnCancelEdit' => Array('self' => true, 'subitem' => true),
+ 'OnCancel' => 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),
+
+ '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');
+
+ $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
+ * @return Array ids stored
+ */
+ function StoreSelectedIDs(&$event)
+ {
+ $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');
+
+ // 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
+ * @return array
+ */
+ function getSelectedIDs(&$event)
+ {
+ return explode(',', $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids'));
+ }
+
+ /**
+ * 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 = $this->Application->RecallVar($prefix_special.'_selected_ids');
+ $event->setEventParam('ids', $ids);
+
+ $this->Application->RemoveVar($prefix_special.'_selected_ids');
+ $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');
+ $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);
+
+ return (
+ $this->Application->GetVar(rtrim($top_prefix.'_'.$event->Special, '_')) == 't'
+ ||
+ $this->Application->GetVar(rtrim($top_prefix.'.'.$event->Special, '.')) == 't'
+ ||
+ $this->Application->GetVar($top_prefix.'_mode') == 't'
+ );
+ }
+
+ /**
+ * 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().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();
+
+ $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 );
+ }
+
+ /**
+ * 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);
+ }
+
+ function getPerPage(&$event)
+ {
+ $per_page = $event->getEventParam('per_page');
+
+ /* if ($per_page == 'list_next') {
+ $per_page = '';
+ }*/
+
+ $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_var = $event->getPrefixSpecial().'_PerPage';
+
+ $per_page = $this->Application->RecallVar($per_page_var);
+ 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) $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) {
+ list($by, $dir) = explode(',', $tag_sort_by);
+ if ($by == 'random') $by = 'RAND()';
+ $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();
+
+ $search_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter');
+ if($search_filter)
+ {
+ $search_filter = unserialize($search_filter);
+ foreach($search_filter as $search_field => $filter_params)
+ {
+ $filter_type = ($filter_params['type'] == 'having') ? HAVING_FILTER : WHERE_FILTER;
+ $object->addFilter($search_field, $filter_params['value'], $filter_type, FLT_SEARCH);
+ }
+ }
+
+ $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');
+ $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 {
+ $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);
+ $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');
+
+ $this->StoreSelectedIDs($event);
+
+ $event->setEventParam('ids', $this->getSelectedIDs($event) );
+ $this->customProcessing($event, 'before');
+ $ids = $event->getEventParam('ids');
+
+ if($ids)
+ {
+ $temp->DeleteItems($event->Prefix, $event->Special, $ids);
+ }
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Prepare temp tables and populate it
+ * with items selected in the grid
+ *
+ * @param kEvent $event
+ */
+ function OnEdit(&$event)
+ {
+ $this->StoreSelectedIDs($event);
+
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', '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->Application->StoreVar($event->getPrefixSpecial().'_selected_ids', implode(',', $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);
+ $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->clearSelectedIDs($event);
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
+ $temp->PrepareEdit();
+
+ $object->setID(0);
+
+ $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);
+ }
+
+ }
+
+/* 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)
+ {
+
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ * @param string $search_field
+ * @param string $type
+ * @param string $value
+ * @param string $formatter_class
+ */
+ function processRangeField(&$event, $search_field, $type, $value, $formatter_class)
+ {
+ $field = $search_field.'_'.$type;
+ $lang_current =& $this->Application->recallObject('lang.current');
+
+ $object =& $event->getObject();
+ $dt_separator = getArrayValue( $object->GetFieldOptions($search_field), 'date_time_separator' );
+ if(!$dt_separator) $dt_separator = ' ';
+
+ $time = ($type == 'datefrom') ? adodb_mktime(0,0,0) : adodb_mktime(23,59,59);
+ $time = adodb_date( $lang_current->GetDBField('InputTimeFormat'), $time);
+ $full_value = $value.$dt_separator.$time;
+
+ $formatter =& $this->Application->recallObject($formatter_class);
+
+ $value_ts = $formatter->Parse($full_value, $search_field, $object);
+ $pseudo = getArrayValue($object->FieldErrors, $search_field, 'pseudo');
+ if($pseudo)
+ {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_'.$field.'_error', $pseudo);
+ return -1;
+ }
+ return $value_ts;
+ }
+
+
+ /**
+ * 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->redirect = 'incs/close_popup';
+
+ // 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');
+ $object =& $event->getObject();
+
+ $search_keyword = $this->Application->GetVar( $event->getPrefixSpecial(true).'_search_keyword');
+ $this->Application->StoreVar( $event->getPrefixSpecial().'_search_keyword', $search_keyword);
+ $search_keyword = str_replace('*', '%', $search_keyword);
+
+ $custom_filters = $this->Application->RecallVar( $event->getPrefixSpecial().'_custom_filters');
+ $custom_filters = $custom_filters ? unserialize($custom_filters) : Array();
+
+ $submit_custom_filters = $this->Application->GetVar('custom_filters');
+
+ if ($submit_custom_filters) {
+ $submit_custom_filters = getArrayValue($submit_custom_filters, $event->getPrefixSpecial() );
+
+ if ($submit_custom_filters) {
+ foreach ($submit_custom_filters as $cf_name => $cf_value) {
+ if ($cf_value) {
+ $custom_filters[$cf_name] = $cf_value;
+ }
+ else {
+ unset($custom_filters[$cf_name]);
+ }
+ }
+ }
+ }
+ $this->Application->StoreVar($event->getPrefixSpecial().'_custom_filters', serialize($custom_filters) );
+
+ if( !$search_keyword && !count($custom_filters) )
+ {
+ $this->OnSearchReset($event);
+ return true;
+ }
+
+ $grid_name = $this->Application->GetVar('grid_name');
+ $grids = $this->Application->getUnitOption($event->Prefix,'Grids');
+ $search_fields = array_keys($grids[$grid_name]['Fields']);
+
+ $search_filter = Array();
+ $search_helper =& $this->Application->recallObject('SearchHelper');
+ $search_keywords = $search_helper->splitKeyword($search_keyword);
+
+ foreach($search_fields as $search_field)
+ {
+ $filter_type = isset($object->VirtualFields[$search_field]) ? 'having' : 'where';
+ $field_type = getArrayValue($object->Fields[$search_field],'type');
+ if(!$field_type) $field_type = 'string'; // default LIKE filter for all fields without type
+
+ $filter_value = '';
+
+ if (preg_match('/(.*)\.(.*)/', $search_field, $regs)) {
+ $table_name = '`'.$regs[1].'`.';
+ $search_field = $regs[2];
+ }
+ elseif ($filter_type == 'where') {
+ $table_name = '`'.$object->TableName.'`.';
+ }
+
+ $table_name = ($filter_type == 'where') ? $table_name : '';
+
+ // get field clause by formatter name and/or parameters
+ $formatter = getArrayValue($object->Fields[$search_field],'formatter');
+ switch($formatter)
+ {
+ case 'kOptionsFormatter':
+ $search_keys = Array();
+
+ $field_value = getArrayValue($custom_filters, $search_field);
+ if ($field_value !== false) {
+ // if keyword passed through advanced search filter (e.g. on Visits lists section)
+ array_push($search_keys, $this->Conn->qstr($field_value));
+ }
+ else {
+ // if keywords passed through simple search filter (on each grid)
+ $use_phrases = getArrayValue($object->Fields[$search_field], 'use_phrases');
+ $field_options = $object->GetFieldOptions($search_field);
+ foreach ($field_options['options'] as $key => $val) {
+ foreach ($search_keywords as $keyword => $sign) {
+ $pattern = '#'.$keyword.'#i';
+ if (!preg_match($pattern, $use_phrases ? $this->Application->Phrase($val) : $val)) {
+ if ($sign == '+') {
+ $filter_value = $table_name.'`'.$search_field.'` = NULL';
+ break;
+ }
+ else {
+ continue;
+ }
+ }
+
+ if ($sign == '+' || $sign == '') {
+ $search_keys[$key] = $this->Conn->qstr($key);
+ }
+ elseif($sign == '-') {
+ // if same value if found as exclusive too, then remove from search result
+ unset($search_keys[$key]);
+ }
+ }
+ }
+ }
+
+ if ($search_keys) {
+ $filter_value = $table_name.'`'.$search_field.'` IN ('.implode(',', $search_keys).')';
+ }
+
+ $field_processed = true;
+ break;
+
+ case 'kDateFormatter':
+ $custom_filter = getArrayValue($object->Fields[$search_field], 'custom_filter');
+ if(!$custom_filter)
+ {
+ $field_processed = false;
+ break;
+ }
+
+ $filter_value = Array();
+
+ $field_value = getArrayValue($custom_filters, $search_field.'_datefrom');
+ if($field_value)
+ {
+ $value = $this->processRangeField($event, $search_field, 'datefrom', $field_value, $formatter);
+ $filter_value[] = $table_name.'`'.$search_field.'` >= '.$value;
+ }
+
+ $field_value = getArrayValue($custom_filters, $search_field.'_dateto');
+ if($field_value)
+ {
+ $value = $this->processRangeField($event, $search_field, 'dateto', $field_value, $formatter);
+ $filter_value[] = $table_name.'`'.$search_field.'` <= '.$value;
+ }
+
+ $filter_value = $filter_value ? '('.implode(') AND (', $filter_value).')' : '';
+
+ $field_processed = true;
+ break;
+
+ default:
+ $field_processed = false;
+ break;
+ }
+
+ // if not already processed by formatter, then get clause by field type
+
+ if (!$field_processed && $search_keywords) {
+ switch($field_type)
+ {
+ case 'int':
+ case 'integer':
+ case 'numeric':
+ $search_keys = Array();
+ foreach ($search_keywords as $keyword => $sign) {
+ if (!is_numeric($keyword) || ($sign == '-')) continue;
+ $search_keys[] = $this->Conn->qstr($keyword);
+ }
+
+ if ($search_keys) {
+ $filter_value = $table_name.'`'.$search_field.'` IN ('.implode(',', $search_keys).')';
+ }
+ break;
+
+ case 'double':
+ case 'float':
+ case 'real':
+ $search_keys = Array();
+ foreach ($search_keywords as $keyword => $sign) {
+ $keyword = str_replace(',', '.', $keyword);
+ if (!is_numeric($keyword) || ($sign == '-')) continue;
+ $search_keys[] = 'ABS('.$table_name.'`'.$search_field.'` - '.$this->Conn->qstr($keyword).') <= 0.0001';
+ }
+
+ if ($search_keys) {
+ $filter_value = '('.implode(') OR (', $search_keys).')';
+ }
+ break;
+
+ case 'string':
+ $filter_value = $search_helper->buildWhereClause($search_keyword, Array($table_name.'`'.$search_field.'`'));
+ break;
+ }
+ }
+
+ if ($filter_value) {
+ $search_filter[$search_field] = Array('type' => $filter_type, 'value' => $filter_value);
+ }
+ }
+
+ $this->Application->StoreVar($event->getPrefixSpecial().'_search_filter', serialize($search_filter) );
+ }
+
+ /**
+ * Clear search keywords
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnSearchReset(&$event)
+ {
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_search_filter');
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_search_keyword');
+
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_custom_filters');
+ }
+
+ /**
+ * 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) );
+ }
+
+ /**
+ * 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 = $this->Application->getUnitOption($main_prefix.'.', 'CalculatedFields', 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;
+ }
+ $this->Application->setUnitOption($main_prefix, 'CustomFields', $custom_fields);
+ $this->Application->setUnitOption($main_prefix.'.', 'CalculatedFields', $calculated_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 = $this->Application->GetVar($event->Prefix.'_mode') == '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);
+ }
+
+ }
+
+
+?>
\ No newline at end of file
Property changes on: branches/unlabeled/unlabeled-1.75.2/core/kernel/db/db_event_handler.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.75
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property

Event Timeline