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(); } 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) { //$ret = $this->Application->GetLinkedVar($event->getPrefixSpecial(true).'_id', $event->getPrefixSpecial().'_id'); // ?? We don't need to store selected id in session, as long as we have pass=all by default, which // means that main item id will be passed to all sub-item screens by default // another prove of that is that sub-items relay on main item '_mode' = 't' for switching to temp tables // Also having id in session raised problems with the id of deleted item stuck in session // 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 */ 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) { /*if ($event->getPrefixSpecial() == 'lang.current ') { $this->Application->Debugger->appendTrace(); }*/ trigger_error('Requested ID for prefix '.$event->getPrefixSpecial().' not passed',E_USER_NOTICE); } $this->Application->SetVar($event->getPrefixSpecial(true).'_id', $first_id); } /** * 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); $live_table = $event->getEventParam('live_table'); 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($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) ? kTempTablesHandler::GetTempTablePrefix().TABLE_PREFIX : TABLE_PREFIX; } 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() ); } 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(); $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); } // $page = $this->Application->GetLinkedVar($event->getPrefixSpecial(true).'_Page', $event->getPrefixSpecial().'_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 PerPage key in config for prefix '.$event->Prefix.'', 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) { $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $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) { $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $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) { $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $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) { $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $object->setID(0); $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate'); $table_info = $object->getLinkedInfo(); $object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']); $this->Application->setUnitOption($event->Prefix,'AutoLoad',true); $event->redirect = false; } /** * Cancel's kDBItem Editing/Creation * * @param kEvent $event * @access protected */ function OnCancel(&$event) { $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', 0)) { 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'); // newly created item /*if($this->getPassedID($event) == 0) { $master_id = $temp->CopyMasterToOriginal(); $temp->UpdateForeignKeys($master_id); // save linked field values $skip_master = true; //we've already copied master table to get the id }*/ if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 0)) { $temp->SaveEdit($skip_master); } $this->clearSelectedIDs($event); $event->redirect_params = Array('opener'=>'u'); $this->Application->RemoveVar($event->getPrefixSpecial().'_modified'); } } /** * 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'); } /** * 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); } $item_id = $this->getPassedID($event); if($item_id == '') { $event->CallSubEvent('OnPreSaveCreated'); if (is_object($event->MasterEvent)) { $event->MasterEvent->setEventParam('IsNew',true); } return; } $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $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); if( $object->Update($id) ) { $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); $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $object =& $event->getObject(); $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) { $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if($items_info) $field_values = array_shift($items_info); $object =& $event->getObject(); $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, $main_prefix, $t) { $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); $pass_events = $event->getEventParam('pass_events'); $new_level = 'index4.php|'.ltrim($this->Application->BuildEnv($t, Array('m_opener' => 'u'), '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(); $keyword = $this->Application->GetVar( $event->getPrefixSpecial(true).'_search_keyword'); $this->Application->StoreVar( $event->getPrefixSpecial().'_search_keyword', $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( !$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(); 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 $keyword = trim($keyword); $keyword = str_replace(Array('"',"'"),'',$keyword); $filter_value = ''; $table_name = ($filter_type == 'where') ? '`'.$object->TableName.'`.' : ''; // 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) { array_push($search_keys, $this->Conn->qstr($field_value)); } else { $use_phrases = getArrayValue($object->Fields[$search_field], 'use_phrases'); foreach($object->Fields[$search_field]['options'] as $key => $val) { $pattern = '#'.$keyword.'#i'; if ( preg_match($pattern, $use_phrases ? $this->Application->Phrase($val) : $val) ) { array_push($search_keys, $this->Conn->qstr($key)); } } } if (count($search_keys) > 0) { $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 && $keyword) { switch($field_type) { case 'int': case 'integer': case 'numeric': if( !is_numeric($keyword) ) break; $filter_value = $table_name.'`'.$search_field.'` = \''.$keyword.'\''; break; case 'double': case 'float': case 'real': if( !is_numeric($keyword) ) break; $filter_value = 'ABS('.$table_name.'`'.$search_field.'` - \''.str_replace(',','.',$keyword).'\') <= 0.0001'; break; case 'string': $like_keyword = preg_replace( '/\'(.*)\'/U', '\\1', $this->Conn->qstr( str_replace('\\','\\\\', $keyword) ) ); $keywords = explode(' ', $like_keyword); foreach($keywords as $keyword_pos => $keyword_value) { $keyword_value = trim($keyword_value); if($keyword_value) { $keywords[$keyword_pos] = $table_name.'`'.$search_field.'` LIKE \'%'.$keyword_value.'%\''; } else { unset($keywords[$keyword_pos]); } } $filter_value = '('.implode(') OR (',$keywords).')'; 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) { $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'), ); } } 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']); } } } } ?>