Index: trunk/core/kernel/db/db_event_handler.php =================================================================== diff -u -r958 -r1339 --- trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 958) +++ trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 1339) @@ -1,5 +1,8 @@ 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->GetVar($event->getPrefixSpecial().'_id'); - if($ret===false) - { - $ids=$this->Application->GetVar($event->getPrefixSpecial().'_selected_ids'); + //$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 + $ret = $this->Application->GetVar($event->getPrefixSpecial(true).'_id'); + if ($ret) return $ret; // if id was passed explicity as prefix[_special]_id use it, and store it in session + + // 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) 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(); + $this->Application->RemoveVar($prefix_special.'_selected_ids'); + $this->Application->SetVar($prefix_special.'_selected_ids', ''); + $this->Application->RemoveVar($prefix_special.'_id'); // not needed anymore ?? + $this->Application->SetVar($prefix_special.'_id', ''); + //$this->Application->RemoveVar($prefix_special.'_modified'); + } + + /*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(); + + if( $this->UseTempTables($event) ) + { + $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); + + $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->createObject(); - $this->dbBuild(&$object,&$event); + $object =& $event->getObject(); + $this->dbBuild($object,$event); - $sql=$this->getSelectSQL($event,'OnItemPrepareQuery'); + $sql = $this->ItemPrepareQuery($event); + $sql = $this->Application->ReplaceLanguageTags($sql); $object->setSelectSQL($sql); - // 1. set from config what needed - $fields = $this->Application->getUnitOption($event->Prefix,'Fields'); - $object->setConfigFields( array_keys($fields) ); - // 2. loads if allowed $auto_load = $this->Application->getUnitOption($event->Prefix,'AutoLoad'); - if($auto_load) - { - $id = $this->getPassedID(&$event); - $object->Load($id); + if($auto_load) $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'; + } + + /** + * Enter description here... + * + * @param kEvent $event + * @return unknown + */ + function __GetTopmostPrefix(&$event) + { + $current_prefix = $event->Prefix; + while ( $parent_prefix = $this->Application->getUnitOption($current_prefix, 'ParentPrefix') ) { + $current_prefix = $parent_prefix; } - $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnUpdate'); + return $current_prefix; } + function LoadItem(&$event) + { + $object =& $event->getObject(); + if ( $event->getEventParam('ByParent') ) { + $parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix'); + $parent_table_key = $this->Application->getUnitOption($event->Prefix, 'ParentTableKey'); + $parent_object =& $this->Application->recallObject($parent_prefix); + $id = $parent_object->GetDBField($parent_table_key); + $id_field = $this->Application->getUnitOption($event->Prefix, 'ForeignKey'); + } + else { + $id = $this->getPassedID($event); + $id_field = null; + } + $object->Load($id, $id_field); + + $actions =& $this->Application->recallObject('kActions'); + $actions->Set($event->Prefix_Special.'_id', $object->GetId()); + } + /** * Builds list * @@ -83,22 +301,53 @@ */ function OnListBuild(&$event) { - $event->setPseudoClass('_List'); - $object =& $event->createObject(); + //$event->setPseudoClass('_List'); + $object =& $event->getObject(); - $this->dbBuild(&$object,&$event); + $this->dbBuild($object,$event); - $sql=$this->getSelectSQL($event,'OnListPrepareQuery'); + $sql = $this->ListPrepareQuery($event); + $sql = $this->Application->ReplaceLanguageTags($sql); $object->setSelectSQL($sql); - $t=$this->Application->GetVar('t'); - $this->Application->StoreVar('redirect_to',$t); + $object->linkToParent(''); - $this->SetPagination(&$event); - $this->SetSorting(&$event); + $this->AddFilters($event); + $this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex. + $this->SetPagination($event); + $this->SetSorting($event); + + $actions =& $this->Application->recallObject('kActions'); + $actions->Set('remove_specials['.$event->Prefix_Special.']', '0'); + $actions->Set($event->Prefix_Special.'_GoTab', ''); } + + /** + * 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 * @@ -108,22 +357,40 @@ */ function SetPagination(&$event) { + // get PerPage (forced -> session -> config -> 10) $per_page = $event->getEventParam('per_page'); if(!$per_page) { - $per_page=$this->Application->RecallVar($event->Prefix_Special.'_PerPage'); + $per_page_var = $event->getPrefixSpecial().'_PerPage'; + + $per_page = $this->Application->RecallVar($per_page_var); if(!$per_page) { - $per_page=10; + $per_page = $this->Application->ConfigValue($per_page_var); + if(!$per_page) $per_page = 10; } } - $event->setPseudoClass('_List'); - $object =& $event->createObject(); + $object =& $event->getObject(); $object->SetPerPage($per_page); - $object->CountRecs(); - - $object->SetPage( $this->Application->GetLinkedVar( $event->Prefix_Special.'_Page' ) ); + + if( !$event->getEventParam('skip_counting') ) + { + $object->CountRecs(); + + $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1); + + $page = $this->Application->GetLinkedVar($event->getPrefixSpecial(true).'_Page', $event->getPrefixSpecial().'_Page'); + $pages = $object->GetTotalPages(); + + if($page > $pages) + { + $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1); + $page = 1; + } + + $object->SetPage($page); + } } /** @@ -137,20 +404,35 @@ function SetSorting(&$event) { $event->setPseudoClass('_List'); - $object =& $event->createObject(); + $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'); - //Use default if not specified - /*if ( $cur_sort1 === false || $cur_sort1_dir == false ) { - $cur_sort1 = $this->Application->ConfigOption($event->Prefix_Special.'_Sort1'); - $cur_sort1_dir = $this->Application->ConfigOption($event->Prefix_Special.'_Sort1_Dir'); - $cur_sort2 = $this->Application->ConfigOption($event->Prefix_Special.'_Sort2'); - $cur_sort2_dir = $this->Application->ConfigOption($event->Prefix_Special.'_Sort2_Dir'); - }*/ + $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings'); + $sorting_prefix = getArrayValue($list_sortings, $event->Special) ? $event->Special : ''; + + // 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 != '') { @@ -162,14 +444,53 @@ } } + /** - * Some kind of filter processing stuff. - * Not in use by now + * Add filters found in session * + * @param kEvent $event */ - function AddFilters() + 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++; + } + } } /** @@ -180,56 +501,51 @@ */ function OnSetSorting(&$event) { - $this->Application->LinkVar($event->getPrefixSpecial(true).'_Sort1',$event->Prefix_Special.'_Sort1'); - $this->Application->LinkVar($event->getPrefixSpecial(true).'_Sort1_Dir',$event->Prefix_Special.'_Sort1_Dir'); + $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'); - //$event->setPseudoClass('_List'); - //$object =& $event->createObject(); + $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); } /** - * Common builder part for Item & List + * Set sorting directly to session * - * @param Object $object - * @access private + * @param kEvent $event */ - function dbBuild(&$object,&$event) + function OnSetSortingDirect(&$event) { - // set Item & List common parameters from config - $table = $this->Application->getUnitOption($event->Prefix,'TableName'); - $object->setTableName($table); - - $id_field = $this->Application->getUnitOption($event->Prefix,'IDField'); - $object->setIDField($id_field); - - // get selected ids from post & save them to session - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if($items_info) - { - $ids=array_keys($items_info); - $this->Application->SetVar($event->getPrefixSpecial().'_selected_ids',implode(',',$ids)); - } - $this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids'); - - // set's any possible hidden fields needed for both Item & List - $current_event = $this->Application->GetVar($event->Prefix_Special.'_event'); - $this->Application->setEvent($event->Prefix_Special,$current_event); + $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'); } /** - * Returns select query for loading item/list + * Reset grid sorting to default (from config) * * @param kEvent $event - * @param string $event_name - * @return string - * @access protected */ - function getSelectSQL(&$event,$event_name) + function OnResetSorting(&$event) { - $new_event =& $this->inheritEvent(&$event); - $new_event->Name=$event_name; - $this->Application->HandleEvent(&$new_event); - return $event->getEventParam('SQLQuery'); + $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'); } /** @@ -241,11 +557,10 @@ * @param kEvent $event * @access protected */ - function OnItemPrepareQuery(&$event) + function ItemPrepareQuery(&$event) { $sqls = $this->Application->getUnitOption($event->Prefix,'ItemSQLs'); - $sql = isset($sqls[$event->Special])?$sqls[$event->Special]:$sqls['']; - $event->MasterEvent->setEventParam('SQLQuery',$sql); + return isset($sqls[$event->Special]) ? $sqls[$event->Special] : $sqls['']; } /** @@ -257,11 +572,10 @@ * @param kEvent $event * @access protected */ - function OnListPrepareQuery(&$event) + function ListPrepareQuery(&$event) { $sqls = $this->Application->getUnitOption($event->Prefix,'ListSQLs'); - $sql = isset($sqls[$event->Special])?$sqls[$event->Special]:$sqls['']; - $event->MasterEvent->setEventParam('SQLQuery',$sql); + return isset( $sqls[$event->Special] ) ? $sqls[$event->Special] : $sqls['']; } /** @@ -272,22 +586,29 @@ */ function OnCreate(&$event) { - $this->Application->setUnitOption($this->getPrefixSpecial(),'AutoLoad',false); - $object =& $event->createObject(); - $this->prepareObject(&$object,&$event); + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if($items_info) $field_values = array_shift($items_info); $object->SetFieldsFromHash($field_values); - if( $object->Create() ) + $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 ($this->UseTempTables($event)) $object->setTempID(); + $this->customProcessing($event,'after'); $event->status=erSUCCESS; + $event->redirect_params = Array('opener'=>'u'); } else { - $event->status=erFATAL; + $event->status=erFAIL; $event->redirect=false; + $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate'); + $object->setID(0); } } @@ -299,30 +620,31 @@ */ function OnUpdate(&$event) { - $this->Application->setUnitOption($this->getPrefixSpecial(),'AutoLoad',false); - $object =& $event->createObject(); - $this->prepareObject(&$object,&$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->Load($id); $object->SetFieldsFromHash($field_values); + $this->customProcessing($event, 'before'); if( $object->Update($id) ) { + $this->customProcessing($event, 'after'); $event->status=erSUCCESS; } else { - $event->status=erFATAL; + $event->status=erFAIL; $event->redirect=false; break; } } } - + $event->redirect_params = Array('opener'=>'u'); } /** @@ -333,18 +655,17 @@ */ function OnDelete(&$event) { - $this->Application->setUnitOption($this->getPrefixSpecial(),'AutoLoad',false); - $object =& $event->createObject(); - $object->ID=$this->Application->GetVar($event->Prefix_Special.'_id'); + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + $object->ID = $this->getPassedID($event); if( $object->Delete() ) { - $event->status=erSUCCESS; + $event->status = erSUCCESS; } else { - $event->status=erFATAL; - $event->redirect=false; - break; + $event->status = erFAIL; + $event->redirect = false; } } @@ -356,11 +677,14 @@ */ function OnNew(&$event) { - $this->Application->setUnitOption($this->getPrefixSpecial(),'AutoLoad',false); - $object =& $event->createObject(); - $this->prepareObject(&$object,&$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']); + $event->redirect=false; } @@ -372,9 +696,605 @@ */ 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) + { + $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 + }*/ + + $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 + $item_id = $this->getPassedID($event); + if ($item_id == '') { + $event->CallSubEvent('OnPreSaveCreated'); + return; + } + + $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; + } + + /** + * Apply custom processing to item + * + * @param kEvent $event + */ + function customProcessing(&$event, $type) + { + + } + + /** + * 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); + } + + } + + // 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) + { + + } + + + /** + * Occures after an item has been copied to temp + * Id of copied item is passed as event' 'id' param + * + * @param kEvent $event + */ + function OnAfterCopyToTemp(&$event) + { + + } + + /** + * Occures before an item is deleted from live table when copying from temp + * (temp handler deleted all items from live and then copy over all items from temp) + * Id of item being deleted is passed as event' 'id' param + * + * @param kEvent $event + */ + function OnBeforeDeleteFromLive(&$event) + { + + } + + /** + * Occures before an item is copied to live table (after all foreign keys have been updated) + * Id of item being copied is passed as event' 'id' param + * + * @param kEvent $event + */ + function OnBeforeCopyToLive(&$event) + { + + } + + /** + * !!! NOT FULLY IMPLEMENTED - SEE TEMP HANDLER COMMENTS (search by event name)!!! + * Occures after an item has been copied to live table + * Id of copied item is passed as event' 'id' param + * + * @param kEvent $event + */ + function OnAfterCopyToLive(&$event) + { + + } + + /** + * Occures before an item is cloneded + * Id of ORIGINAL item is passed as event' 'id' param + * Do not call object' Update method in this event, just set needed fields! + * + * @param kEvent $event + */ + function OnBeforeClone(&$event) + { + + } + + /** + * Occures after an item has been cloned + * Id of newly created item is passed as event' 'id' param + * + * @param kEvent $event + */ + function OnAfterClone(&$event) + { + + } + + /** + * Ensures that popup will be closed automatically + * and parent window will be refreshed with template + * passed + * + * @param kEvent $event + * @access public + */ + function finalizePopup(&$event, $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); + + $new_level = 'index4.php|'.ltrim($this->Application->BuildEnv($t, Array('m_opener' => 'u'), 'all'), 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); + + if(!$keyword) + { + $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); + $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(); + $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, $key); + } + } + if (count($search_keys) > 0) { + $filter_value = $table_name.'`'.$search_field.'` IN ('.implode(',', $search_keys).')'; + } + + $field_processed = true; + break; + + default: + $field_processed = false; + break; + } + + // if not already processed by formatter, then get clause by field type + + if(!$field_processed) + { + 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': + $keywords = explode(' ',$keyword); + foreach($keywords as $keyword_pos => $keyword_value) + { + $keywords[$keyword_pos] = $table_name.'`'.$search_field.'` LIKE \'%'.trim($keyword_value).'%\''; + } + $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'); + } + + /** + * 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) ); + } + + function OnPreSaveAndOpenTranslator(&$event) + { + $this->Application->SetVar('allow_translation', true); + $event->CallSubEvent('OnPreSave'); + $wnd_name = $this->Application->GetVar('translator_wnd_name'); + if ($event->status == erSUCCESS) { + $t = $this->Application->GetVar('translator_t'); + $object = $this->Application->recallObject($event->getPrefixSpecial()); + $url = $this->Application->HREF($t, '', Array('pass'=>'all', $event->getPrefixSpecial(true).'_id' => $object->GetId())); + $field = $this->Application->GetVar('translator_field'); + $after_script = "openTranslator('".$event->getPrefixSpecial()."', '".$field."', '".$url."', '".$wnd_name."')"; + } + else { + $after_script = "wnd = window.open('', '".$wnd_name."'); wnd.close()"; + } + $this->Application->SetVar('after_script', $after_script); + $event->redirect = false; + } }