Index: branches/RC/core/kernel/db/db_event_handler.php =================================================================== diff -u -N --- branches/RC/core/kernel/db/db_event_handler.php (revision 11933) +++ branches/RC/core/kernel/db/db_event_handler.php (revision 0) @@ -1,2501 +0,0 @@ -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'); - } - - if ($event->Name == 'OnSaveWidths') { - return $this->Application->IsAdmin() && $this->Application->LoggedIn(); - } - - return parent::CheckPermission($event); - } - - /** - * Allows to override standart permission mapping - * - */ - function mapPermissions() - { - parent::mapPermissions(); - $permissions = Array( - 'OnLoad' => Array('self' => 'view', 'subitem' => 'view'), - 'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'), - - 'OnBuild' => Array('self' => true), - - 'OnNew' => Array('self' => 'add', 'subitem' => 'add|edit'), - 'OnCreate' => Array('self' => 'add', 'subitem' => 'add|edit'), - 'OnUpdate' => Array('self' => 'edit', 'subitem' => 'add|edit'), - 'OnSetPrimary' => Array('self' => 'add|edit', 'subitem' => 'add|edit'), - 'OnDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'), - 'OnDeleteAll' => Array('self' => 'delete', 'subitem' => 'add|edit'), - 'OnMassDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'), - 'OnMassClone' => Array('self' => 'add', 'subitem' => 'add|edit'), - - 'OnCut' => array('self'=>'edit', 'subitem' => 'edit'), - 'OnCopy' => array('self'=>'edit', 'subitem' => 'edit'), - 'OnPaste' => array('self'=>'edit', 'subitem' => 'edit'), - - 'OnSelectItems' => Array('self' => 'add|edit', 'subitem' => 'add|edit'), - 'OnProcessSelected' => Array('self' => 'add|edit', 'subitem' => 'add|edit'), - 'OnSelectUser' => Array('self' => 'add|edit', 'subitem' => 'add|edit'), - - 'OnMassApprove' => Array('self' => 'advanced:approve|edit', 'subitem' => 'advanced:approve|add|edit'), - 'OnMassDecline' => Array('self' => 'advanced:decline|edit', 'subitem' => 'advanced:decline|add|edit'), - 'OnMassMoveUp' => Array('self' => 'advanced:move_up|edit', 'subitem' => 'advanced:move_up|add|edit'), - 'OnMassMoveDown' => Array('self' => 'advanced:move_down|edit', 'subitem' => 'advanced:move_down|add|edit'), - - 'OnPreCreate' => Array('self' => 'add|add.pending', 'subitem' => 'edit|edit.pending'), - 'OnEdit' => Array('self' => 'edit|edit.pending', 'subitem' => 'edit|edit.pending'), - - 'OnExport' => Array('self' => 'view|advanced:export'), - 'OnExportBegin' => Array('self' => 'view|advanced:export'), - 'OnExportProgress' => Array('self' => 'view|advanced:export'), - - - 'OnSetAutoRefreshInterval' => Array ('self' => true, 'subitem' => true), - 'OnAutoRefreshToggle' => Array ('self' => true, 'subitem' => true), - - // theese event do not harm, but just in case check them too :) - 'OnCancelEdit' => Array('self' => true, 'subitem' => true), - 'OnCancel' => Array('self' => true, 'subitem' => true), - 'OnReset' => Array('self' => true, 'subitem' => true), - - 'OnSetSorting' => Array('self' => true, 'subitem' => true), - 'OnSetSortingDirect' => Array('self' => true, 'subitem' => true), - 'OnResetSorting' => Array('self' => true, 'subitem' => true), - - 'OnSetFilter' => Array('self' => true, 'subitem' => true), - 'OnApplyFilters' => Array('self' => true, 'subitem' => true), - 'OnRemoveFilters' => Array('self' => true, 'subitem' => true), - 'OnSetFilterPattern' => Array('self' => true, 'subitem' => true), - - 'OnSetPerPage' => Array('self' => true, 'subitem' => true), - 'OnSetPage' => Array('self' => true, 'subitem' => true), - - 'OnSearch' => Array('self' => true, 'subitem' => true), - 'OnSearchReset' => Array('self' => true, 'subitem' => true), - - 'OnGoBack' => Array('self' => true, 'subitem' => true), - - // it checks permission itself since flash uploader does not send cookies - 'OnUploadFile' => Array ('self' => true, 'subitem' => true), - 'OnDeleteFile' => Array ('self' => true, 'subitem' => true), - - 'OnViewFile' => Array ('self' => true, 'subitem' => true), - 'OnSaveWidths' => Array ('self' => true, 'subitem' => true), - - 'OnValidateMInputFields' => Array ('self' => 'view'), - ); - $this->permMapping = array_merge($this->permMapping, $permissions); - } - - function mapEvents() - { - $events_map = Array( - 'OnRemoveFilters' => 'FilterAction', - 'OnApplyFilters' => 'FilterAction', - 'OnMassApprove'=>'iterateItems', - 'OnMassDecline'=>'iterateItems', - 'OnMassMoveUp'=>'iterateItems', - 'OnMassMoveDown'=>'iterateItems', - ); - - $this->eventMethods = array_merge($this->eventMethods, $events_map); - } - - /** - * Returns ID of current item to be edited - * by checking ID passed in get/post as prefix_id - * or by looking at first from selected ids, stored. - * Returned id is also stored in Session in case - * it was explicitly passed as get/post - * - * @param kEvent $event - * @return int - */ - function getPassedID(&$event) - { - if ($event->getEventParam('raise_warnings') === false) { - $event->setEventParam('raise_warnings', 1); - } - - if (preg_match('/^auto-(.*)/', $event->Special, $regs) && $this->Application->prefixRegistred($regs[1])) { - // - returns field DateFormat value from language (LanguageId is extracted from current phrase object) - $main_object =& $this->Application->recallObject($regs[1]); - /* @var $main_object kDBItem */ - - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - return $main_object->GetDBField($id_field); - } - - // 1. get id from post (used in admin) - $ret = $this->Application->GetVar($event->getPrefixSpecial(true).'_id'); - if (($ret !== false) && ($ret != '')) { - return $ret; - } - - // 2. get id from env (used in front) - $ret = $this->Application->GetVar($event->getPrefixSpecial().'_id'); - if (($ret !== false) && ($ret != '')) { - return $ret; - } - - // recall selected ids array and use the first one - $ids = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids'); - if ($ids != '') { - $ids = explode(',',$ids); - if ($ids) { - $ret = array_shift($ids); - } - } - else { // if selected ids are not yet stored - $this->StoreSelectedIDs($event); - return $this->Application->GetVar($event->getPrefixSpecial().'_id'); // StoreSelectedIDs sets this variable - } - - return $ret; - } - - /** - * Prepares and stores selected_ids string - * in Session and Application Variables - * by getting all checked ids from grid plus - * id passed in get/post as prefix_id - * - * @param kEvent $event - * @param Array $direct_ids - * - * @return Array ids stored - */ - function StoreSelectedIDs(&$event, $direct_ids = null) - { - $wid = $this->Application->GetTopmostWid($event->Prefix); - $session_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_'); - - $ids = $event->getEventParam('ids'); - if (isset($direct_ids) || ($ids !== false)) { - // save ids directly if they given - $this->Application->StoreVar($session_name, implode(',', $direct_ids ? $direct_ids : $ids)); - return $direct_ids ? $direct_ids : $ids; - } - - $ret = Array(); - - // May be we don't need this part: ? - $passed = $this->Application->GetVar($event->getPrefixSpecial(true).'_id'); - if($passed !== false && $passed != '') - { - array_push($ret, $passed); - } - - $ids = Array(); - - // get selected ids from post & save them to session - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if($items_info) - { - $id_field = $this->Application->getUnitOption($event->Prefix,'IDField'); - foreach($items_info as $id => $field_values) - { - if( getArrayValue($field_values,$id_field) ) array_push($ids,$id); - } - //$ids=array_keys($items_info); - } - - $ret = array_unique(array_merge($ret, $ids)); - - $this->Application->SetVar($event->getPrefixSpecial().'_selected_ids', implode(',',$ret)); - $this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids', $session_name); - - // This is critical - otherwise getPassedID will return last ID stored in session! (not exactly true) - // this smells... needs to be refactored - $first_id = getArrayValue($ret,0); - if (($first_id === false) && ($event->getEventParam('raise_warnings') == 1)) { - if ($this->Application->isDebugMode()) { - $this->Application->Debugger->appendTrace(); - } - trigger_error('Requested ID for prefix '.$event->getPrefixSpecial().' not passed',E_USER_NOTICE); - } - - $this->Application->SetVar($event->getPrefixSpecial() . '_id', $first_id); - return $ret; - } - - /** - * Returns stored selected ids as an array - * - * @param kEvent $event - * @param bool $from_session return ids from session (written, when editing was started) - * @return array - */ - function getSelectedIDs(&$event, $from_session = false) - { - if ($from_session) { - $wid = $this->Application->GetTopmostWid($event->Prefix); - $var_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_'); - $ret = $this->Application->RecallVar($var_name); - } - else { - $ret = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids'); - } - - return explode(',', $ret); - } - - /** - * Returs associative array of submitted fields for current item - * Could be used while creating/editing single item - - * meaning on any edit form, except grid edit - * - * @param kEvent $event - */ - function getSubmittedFields(&$event) - { - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - $field_values = $items_info ? array_shift($items_info) : Array(); - return $field_values; - } - - /** - * Removes any information about current/selected ids - * from Application variables and Session - * - * @param kEvent $event - */ - function clearSelectedIDs(&$event) - { - $prefix_special = $event->getPrefixSpecial(); - - $ids = implode(',', $this->getSelectedIDs($event, true)); - $event->setEventParam('ids', $ids); - - $wid = $this->Application->GetTopmostWid($event->Prefix); - $session_name = rtrim($prefix_special.'_selected_ids_'.$wid, '_'); - - $this->Application->RemoveVar($session_name); - $this->Application->SetVar($prefix_special.'_selected_ids', ''); - - $this->Application->SetVar($prefix_special.'_id', ''); // $event->getPrefixSpecial(true).'_id' too may be - } - - /*function SetSaveEvent(&$event) - { - $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnUpdate'); - $this->Application->LinkVar($event->Prefix_Special.'_SaveEvent'); - }*/ - - /** - * Common builder part for Item & List - * - * @param kDBBase $object - * @param kEvent $event - * @access private - */ - function dbBuild(&$object, &$event) - { - $object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields') ); - $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); - } - - /** - * Checks, that currently loaded item is allowed for viewing (non permission-based) - * - * @param kEvent $event - * @return bool - */ - function checkItemStatus(&$event) - { - $status_fields = $this->Application->getUnitOption($event->Prefix,'StatusField'); - if (!$status_fields) { - return true; - } - - $status_field = array_shift($status_fields); - if ($status_field == 'Status' || $status_field == 'Enabled') { - $object =& $event->getObject(); - if (!$object->isLoaded()) { - return true; - } - - return $object->GetDBField($status_field) == STATUS_ACTIVE; - } - return true; - } - - /** - * Shows not found template content - * - * @param kEvent $event - * - */ - function _errorNotFound(&$event) - { - if ($event->getEventParam('raise_warnings') === 0) { - // when it's possible, that autoload fails do nothing - return ; - } - - if ($this->Application->isDebugMode()) { - $this->Application->Debugger->appendTrace(); - } - trigger_error('ItemLoad Permission Failed for prefix [' . $event->getPrefixSpecial() . '] in checkItemStatus, leading to "404 Not Found"', E_USER_WARNING); - - header('HTTP/1.0 404 Not Found'); - - while (ob_get_level()) { - ob_end_clean(); - } - - // object is used inside template parsing, so break out any parsing and return error document - $error_template = $this->Application->ConfigValue('ErrorTemplate'); - - $themes_helper =& $this->Application->recallObject('ThemesHelper'); - /* @var $themes_helper kThemesHelper */ - - $this->Application->SetVar('t', $error_template); - $this->Application->SetVar('m_cat_id', $themes_helper->getPageByTemplate($error_template)); - - $this->Application->HTML = $this->Application->ParseBlock( Array ('name' => $error_template) ); - $this->Application->Done(); - exit; - } - - /** - * 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) { - $perm_status = true; - $user_id = $this->Application->RecallVar('user_id'); - $event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true)); - $status_checked = false; - if ($user_id == -1 || $this->CheckPermission($event)) { - // don't autoload item, when user doesn't have view permission - $this->LoadItem($event); - - $status_checked = true; - if ($user_id != -1 && !$this->Application->IsAdmin() && !$this->checkItemStatus($event)) { - $perm_status = false; - } - } - else { - $perm_status = false; - } - - if (!$perm_status) { - // when no permission to view item -> redirect to no pemrission template - if ($this->Application->isDebugMode()) { - $this->Application->Debugger->appendTrace(); - } - trigger_error('ItemLoad Permission Failed for prefix ['.$event->getPrefixSpecial().'] in '.($status_checked ? 'checkItemStatus' : 'CheckPermission').'', E_USER_WARNING); - $next_template = $this->Application->IsAdmin() ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate'); - $this->Application->Redirect($next_template, Array('next_template' => $this->Application->GetVar('t'))); - } - } - - $actions =& $this->Application->recallObject('kActions'); - $actions->Set($event->Prefix_Special.'_GoTab', ''); - - $actions->Set($event->Prefix_Special.'_GoId', ''); - } - - /** - * Build subtables array from configs - * - * @param kEvent $event - */ - function OnTempHandlerBuild(&$event) - { - $object =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - /* @var $object kTempTablesHandler */ - - $object->BuildTables( $event->Prefix, $this->getSelectedIDs($event) ); - } - - /** - * Checks, that object used in event should use temp tables - * - * @param kEvent $event - * @return bool - */ - function UseTempTables(&$event) - { - $top_prefix = $this->Application->GetTopmostPrefix($event->Prefix); // passed parent, not always actual - $special = ($top_prefix == $event->Prefix) ? $event->Special : $this->getMainSpecial($event); - - return $this->Application->IsTempMode($event->Prefix, $special); - } - - /** - * Returns table prefix from event (temp or live) - * - * @param kEvent $event - * @return string - * @todo Needed? Should be refactored (by Alex) - */ - function TablePrefix(&$event) - { - return $this->UseTempTables($event) ? $this->Application->GetTempTablePrefix('prefix:'.$event->Prefix).TABLE_PREFIX : TABLE_PREFIX; - } - - /** - * Load item if id is available - * - * @param kEvent $event - */ - function LoadItem(&$event) - { - $object =& $event->getObject(); - $id = $this->getPassedID($event); - - if ($object->isLoaded() && !is_array($id) && ($object->GetID() == $id)) { - // object is already loaded by same id - return ; - } - - 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(); - /* @var $object kDBList */ - - $this->dbBuild($object,$event); - - $sql = $this->ListPrepareQuery($event); - $sql = $this->Application->ReplaceLanguageTags($sql); - $object->setSelectSQL($sql); - - $object->Counted = false; // when requery="1" should re-count records too! - $object->ClearOrderFields(); // prevents duplicate order fields, when using requery="1" - - $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) - { - $main_special = $event->getEventParam('main_special'); - - if ($main_special === false) { - // main item's special not passed - - if (substr($event->Special, -5) == '-item') { - // temp handler added "-item" to given special -> process that here - return substr($event->Special, 0, -5); - } - - // by default subitem's special is used for main item searching - return $event->Special; - } - - return $main_special; - } - - /** - * Apply any custom changes to list's sql query - * - * @param kEvent $event - * @access protected - * @see OnListBuild - */ - function SetCustomQuery(&$event) - { - - } - - /** - * Set's new perpage for grid - * - * @param kEvent $event - */ - function OnSetPerPage(&$event) - { - $per_page = $this->Application->GetVar($event->getPrefixSpecial(true).'_PerPage'); - $this->Application->StoreVar($event->getPrefixSpecial().'_PerPage', $per_page); - - $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view'); - $this->Application->StorePersistentVar($event->getPrefixSpecial().'_PerPage.'.$view_name, $per_page); - } - - /** - * Occurs when page is changed (only for hooking) - * - * @param kEvent $event - */ - function OnSetPage(&$event) - { - $page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_Page'); - $event->SetRedirectParam($event->getPrefixSpecial().'_Page', $page); - } - - /** - * Set's correct page for list - * based on data provided with event - * - * @param kEvent $event - * @access private - * @see OnListBuild - */ - function SetPagination(&$event) - { - // get PerPage (forced -> session -> config -> 10) - $per_page = $this->getPerPage($event); - - $object =& $event->getObject(); - $object->SetPerPage($per_page); - $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1); - - $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page'); - if (!$page) { - $page = $this->Application->GetVar($event->getPrefixSpecial(true).'_Page'); - } - if (!$page) { - $page = $this->Application->RecallVar($event->getPrefixSpecial().'_Page'); - } - else { - $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page); - } - - if( !$event->getEventParam('skip_counting') ) - { - $pages = $object->GetTotalPages(); - if($page > $pages) - { - $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1); - $page = 1; - } - } - - /*$per_page = $event->getEventParam('per_page'); - if ($per_page == 'list_next') { - - $cur_page = $page; - $cur_per_page = $per_page; - - $object->SetPerPage(1); - - $object =& $this->Application->recallObject($event->Prefix); - $cur_item_index = $object->CurrentIndex; - - $page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1; - $object->SetPerPage(1); - }*/ - - $object->SetPage($page); - } - - /** - * Returns current per-page setting for list - * - * @param kEvent $event - * @return int - */ - function getPerPage(&$event) - { - // 1. per-page is passed as tag parameter to PrintList, InitList, etc. - $per_page = $event->getEventParam('per_page'); - - /*if ($per_page == 'list_next') { - $per_page = ''; - }*/ - - // 2. per-page variable name is store into config variable - $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping'); - if ($config_mapping) { - switch ( $per_page ){ - case 'short_list' : - $per_page = $this->Application->ConfigValue($config_mapping['ShortListPerPage']); - break; - case 'default' : - $per_page = $this->Application->ConfigValue($config_mapping['PerPage']); - break; - } - } - - if (!$per_page) { - // per-page is stored to persistent session - $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view'); - - $storage_prefix = $event->getEventParam('same_special') ? $event->Prefix : $event->getPrefixSpecial(); - $per_page = $this->Application->RecallPersistentVar($storage_prefix.'_PerPage.'.$view_name, ALLOW_DEFAULT_SETTINGS); - - if (!$per_page) { - // per-page is stored to current session - $per_page = $this->Application->RecallVar($storage_prefix.'_PerPage'); - } - - 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) { - // none of checked above per-page locations are useful, then try default value - $default_per_page = $event->getEventParam('default_per_page'); - $per_page = is_numeric($default_per_page) ? $default_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(); - - $storage_prefix = $event->getEventParam('same_special') ? $event->Prefix : $event->Prefix_Special; - $cur_sort1 = $this->Application->RecallVar($storage_prefix.'_Sort1'); - $cur_sort1_dir = $this->Application->RecallVar($storage_prefix.'_Sort1_Dir'); - $cur_sort2 = $this->Application->RecallVar($storage_prefix.'_Sort2'); - $cur_sort2_dir = $this->Application->RecallVar($storage_prefix.'_Sort2_Dir'); - - $sorting_configs = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping'); - $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings'); - $sorting_prefix = getArrayValue($list_sortings, $event->Special) ? $event->Special : ''; - - $tag_sort_by = $event->getEventParam('sort_by'); - if ($tag_sort_by) { - if ($tag_sort_by == 'random') { - $object->AddOrderField('RAND()', ''); - } - else { - $tag_sort_by = explode('|', $tag_sort_by); - foreach ($tag_sort_by as $sorting_element) { - list ($by, $dir) = explode(',', $sorting_element); - $object->AddOrderField($by, $dir); - } - } - } - - if ($sorting_configs && isset ($sorting_configs['DefaultSorting1Field'])){ - $list_sortings[$sorting_prefix]['Sorting'] = Array( - $this->Application->ConfigValue($sorting_configs['DefaultSorting1Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting1Dir']), - $this->Application->ConfigValue($sorting_configs['DefaultSorting2Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting2Dir']), - ); - } - - // Use default if not specified - if ( !$cur_sort1 || !$cur_sort1_dir) - { - if ( $sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting') ) { - reset($sorting); - $cur_sort1 = key($sorting); - $cur_sort1_dir = current($sorting); - if (next($sorting)) { - $cur_sort2 = key($sorting); - $cur_sort2_dir = current($sorting); - } - } - } - - if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) { - foreach ($forced_sorting as $field => $dir) { - $object->AddOrderField($field, $dir); - } - } - - if($cur_sort1 != '' && $cur_sort1_dir != '') - { - $object->AddOrderField($cur_sort1, $cur_sort1_dir); - } - if($cur_sort2 != '' && $cur_sort2_dir != '') - { - $object->AddOrderField($cur_sort2, $cur_sort2_dir); - } - } - - /** - * Add filters found in session - * - * @param kEvent $event - */ - function AddFilters(&$event) - { - $object =& $event->getObject(); - - $edit_mark = rtrim($this->Application->GetSID().'_'.$this->Application->GetTopmostWid($event->Prefix), '_'); - - // add search filter - $filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter'); - if ($filter_data) { - $filter_data = unserialize($filter_data); - foreach ($filter_data as $filter_field => $filter_params) { - $filter_type = ($filter_params['type'] == 'having') ? HAVING_FILTER : WHERE_FILTER; - $filter_value = str_replace(EDIT_MARK, $edit_mark, $filter_params['value']); - $object->addFilter($filter_field, $filter_value, $filter_type, FLT_SEARCH); - } - } - - // add custom filter - $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view'); - $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name); - if ($custom_filters) { - $grid_name = $event->getEventParam('grid'); - $custom_filters = unserialize($custom_filters); - if (isset($custom_filters[$grid_name])) { - foreach ($custom_filters[$grid_name] as $field_name => $field_options) { - list ($filter_type, $field_options) = each($field_options); - if (isset($field_options['value']) && $field_options['value']) { - $filter_type = ($field_options['sql_filter_type'] == 'having') ? HAVING_FILTER : WHERE_FILTER; - $filter_value = str_replace(EDIT_MARK, $edit_mark, $field_options['value']); - $object->addFilter($field_name, $filter_value, $filter_type, FLT_CUSTOM); - } - } - } - } - - $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter'); - if($view_filter) - { - $view_filter = unserialize($view_filter); - $temp_filter =& $this->Application->makeClass('kMultipleFilter'); - $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu'); - - $group_key = 0; $group_count = count($filter_menu['Groups']); - while($group_key < $group_count) - { - $group_info = $filter_menu['Groups'][$group_key]; - - $temp_filter->setType( constant('FLT_TYPE_'.$group_info['mode']) ); - $temp_filter->clearFilters(); - foreach ($group_info['filters'] as $flt_id) - { - $sql_key = getArrayValue($view_filter,$flt_id) ? 'on_sql' : 'off_sql'; - if ($filter_menu['Filters'][$flt_id][$sql_key] != '') - { - $temp_filter->addFilter('view_filter_'.$flt_id, $filter_menu['Filters'][$flt_id][$sql_key]); - } - } - $object->addFilter('view_group_'.$group_key, $temp_filter, $group_info['type'] , FLT_VIEW); - $group_key++; - } - } - } - - /** - * Set's new sorting for list - * - * @param kEvent $event - * @access protected - */ - function OnSetSorting(&$event) - { - $cur_sort1 = $this->Application->RecallVar($event->Prefix_Special.'_Sort1'); - $cur_sort1_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort1_Dir'); - - $use_double_sorting = $this->Application->ConfigValue('UseDoubleSorting'); - - if ($use_double_sorting) { - $cur_sort2 = $this->Application->RecallVar($event->Prefix_Special.'_Sort2'); - $cur_sort2_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort2_Dir'); - } - - $passed_sort1 = $this->Application->GetVar($event->getPrefixSpecial(true).'_Sort1'); - if ($cur_sort1 == $passed_sort1) { - $cur_sort1_dir = $cur_sort1_dir == 'asc' ? 'desc' : 'asc'; - } - else { - if ($use_double_sorting) { - $cur_sort2 = $cur_sort1; - $cur_sort2_dir = $cur_sort1_dir; - } - $cur_sort1 = $passed_sort1; - $cur_sort1_dir = 'asc'; - } - - $this->Application->StoreVar($event->Prefix_Special.'_Sort1', $cur_sort1); - $this->Application->StoreVar($event->Prefix_Special.'_Sort1_Dir', $cur_sort1_dir); - if ($use_double_sorting) { - $this->Application->StoreVar($event->Prefix_Special.'_Sort2', $cur_sort2); - $this->Application->StoreVar($event->Prefix_Special.'_Sort2_Dir', $cur_sort2_dir); - } - } - - /** - * Set sorting directly to session (used for category item sorting (front-end), grid sorting (admin, view menu) - * - * @param kEvent $event - */ - function OnSetSortingDirect(&$event) - { - $combined = $this->Application->GetVar($event->Prefix.'_CombinedSorting'); - if ($combined) { - list($field, $dir) = explode('|', $combined); - $this->Application->StoreVar($event->Prefix.'_Sort1', $field); - $this->Application->StoreVar($event->Prefix.'_Sort1_Dir', $dir); - return ; - } - - $field_pos = $this->Application->GetVar($event->Prefix.'_SortPos'); - $this->Application->LinkVar($event->Prefix.'_Sort'.$field_pos, $event->Prefix.'_Sort'.$field_pos); - $this->Application->LinkVar($event->Prefix.'_Sort'.$field_pos.'_Dir', $event->Prefix.'_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'); - } - - /** - * Sets grid refresh interval - * - * @param kEvent $event - */ - function OnSetAutoRefreshInterval(&$event) - { - $refresh_interval = $this->Application->GetVar('refresh_interval'); - - $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view'); - $this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_interval); - } - - /** - * Changes auto-refresh state for grid - * - * @param kEvent $event - */ - function OnAutoRefreshToggle(&$event) - { - $refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals'); - if (!$refresh_intervals) { - return ; - } - - $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view'); - $auto_refresh = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name); - - if ($auto_refresh === false) { - $refresh_intervals = explode(',', $refresh_intervals); - $this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_intervals[0]); - } - - $this->Application->StorePersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name, $auto_refresh ? 0 : 1); - } - - /** - * Creates needed sql query to load item, - * if no query is defined in config for - * special requested, then use default - * query - * - * @param kEvent $event - * @access protected - */ - function ItemPrepareQuery(&$event) - { - $sqls = $this->Application->getUnitOption($event->Prefix, 'ItemSQLs', Array ()); - $special = array_key_exists($event->Special, $sqls) ? $event->Special : ''; - - if (!array_key_exists($special, $sqls)) { - // preferred special not found in ItemSQLs -> use analog from ListSQLs - return $this->ListPrepareQuery($event); - } - - return $sqls[$special]; - } - - /** - * 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', Array ()); - return $sqls[ array_key_exists($event->Special, $sqls) ? $event->Special : '' ]; - } - - /** - * 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) ); - /* @var $object kDBItem */ - - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if ($items_info) { - list($id,$field_values) = each($items_info); - $object->SetFieldsFromHash($field_values); - } - - $this->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) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - /* @var $temp kTempTablesHandler */ - - $temp->DeleteItems($event->Prefix, $event->Special, Array($this->getPassedID($event))); - } - - /** - * Deletes all records from table - * - * @param kEvent $event - */ - function OnDeleteAll(&$event) - { - $sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . ' - FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName'); - $ids = $this->Conn->GetCol($sql); - - if ($ids) { - $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler'); - /* @var $temp_handler kTempTablesHandler */ - - $temp_handler->DeleteItems($event->Prefix, $event->Special, $ids); - } - } - - /** - * Prepares new kDBItem object - * - * @param kEvent $event - * @access protected - */ - function OnNew(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - /* @var $object kDBItem */ - - $object->Clear(0); - $this->Application->SetVar($event->Prefix_Special.'_SaveEvent', 'OnCreate'); - - if ($event->getEventParam('top_prefix') != $event->Prefix) { - // this is subitem prefix, so use main item special - $table_info = $object->getLinkedInfo( $this->getMainSpecial($event) ); - } - else { - $table_info = $object->getLinkedInfo(); - } - - $object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']); - - $event->redirect = false; - } - - /** - * Cancel's kDBItem Editing/Creation - * - * @param kEvent $event - * @access protected - */ - function OnCancel(&$event) - { - $object =& $event->getObject(Array('skip_autoload' => true)); - - $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); - if ($items_info) { - $delete_ids = Array(); - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - foreach ($items_info as $id => $field_values) { - $object->Load($id); - // record created for using with selector (e.g. Reviews->Select User), and not validated => Delete it - if ($object->isLoaded() && !$object->Validate() && ($id <= 0) ) { - $delete_ids[] = $id; - } - } - - if ($delete_ids) { - $temp->DeleteItems($event->Prefix, $event->Special, $delete_ids); - } - } - - $event->redirect_params = Array('opener'=>'u'); - } - - - /** - * Deletes all selected items. - * Automatically recurse into sub-items using temp handler, and deletes sub-items - * by calling its Delete method if sub-item has AutoDelete set to true in its config file - * - * @param kEvent $event - */ - function OnMassDelete(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $event->status=erSUCCESS; - - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - - $ids = $this->StoreSelectedIDs($event); - - $event->setEventParam('ids', $ids); - $this->customProcessing($event, 'before'); - $ids = $event->getEventParam('ids'); - - if($ids) - { - $temp->DeleteItems($event->Prefix, $event->Special, $ids); - } - $this->clearSelectedIDs($event); - } - - /** - * Sets window id (of first opened edit window) to temp mark in uls - * - * @param kEvent $event - */ - function setTempWindowID(&$event) - { - $prefixes = Array ($event->Prefix, $event->getPrefixSpecial(true)); - - foreach ($prefixes as $prefix) { - $mode = $this->Application->GetVar($prefix . '_mode'); - - if ($mode == 't') { - $wid = $this->Application->GetVar('m_wid'); - $this->Application->SetVar(str_replace('_', '.', $prefix) . '_mode', 't' . $wid); - break; - } - } - } - - /** - * Prepare temp tables and populate it - * with items selected in the grid - * - * @param kEvent $event - */ - function OnEdit(&$event) - { - $this->setTempWindowID($event); - $this->StoreSelectedIDs($event); - $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid'); - $this->Application->RemoveVar($var_name); - - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - /* @var $temp kTempTablesHandler */ - - $temp->PrepareEdit(); - - $event->redirect = false; - } - - /** - * Saves content of temp table into live and - * redirects to event' default redirect (normally grid template) - * - * @param kEvent $event - */ - function OnSave(&$event) - { - $event->CallSubEvent('OnPreSave'); - if ($event->status == erSUCCESS) { - $skip_master = false; - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - - $changes_var_name = $this->Prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix); - - if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - $live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array()); - if ($live_ids === false) { - // coping from table failed, because we have another coping process to same table, that wasn't finished - $event->status = erFAIL; - return ; - } - - // Deleteing files scheduled for delete - $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid'); - $schedule = $this->Application->RecallVar($var_name); - $schedule = $schedule ? unserialize($schedule) : array(); - foreach ($schedule as $data) { - if ($data['action'] == 'delete') { - unlink($data['file']); - } - } - - if ($live_ids) { - // ensure, that newly created item ids are avalable as if they were selected from grid - // NOTE: only works if main item has subitems !!! - $this->StoreSelectedIDs($event, $live_ids); - } - - $this->SaveLoggedChanges($changes_var_name); - } - else { - $this->Application->RemoveVar($changes_var_name); - } - $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', ''); - } - } - - function SaveLoggedChanges($changes_var_name) - { - $ses_log_id = $this->Application->RecallVar('_SessionLogId_'); - if (!$ses_log_id) { - return ; - } - - $changes = $this->Application->RecallVar($changes_var_name); - $changes = $changes ? unserialize($changes) : Array (); - if (!$changes) { - return ; - } - - $add_fields = Array ( - 'PortalUserId' => $this->Application->RecallVar('user_id'), - 'SessionLogId' => $ses_log_id, - ); - - $changelog_table = $this->Application->getUnitOption('change-log', 'TableName'); - $sessionlog_table = $this->Application->getUnitOption('session-log', 'TableName'); - - foreach ($changes as $rec) { - $this->Conn->doInsert(array_merge($rec, $add_fields), $changelog_table); - } - - $sql = 'UPDATE '.$sessionlog_table.' - SET AffectedItems = AffectedItems + '.count($changes).' - WHERE SessionLogId = '.$ses_log_id; - $this->Conn->Query($sql); - - $this->Application->RemoveVar($changes_var_name); - } - - - /** - * 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) - { - $object =& $event->getObject( Array ('raise_warnings' => 0) ); - return !$object->IsLoaded(); - -// $item_id = $this->getPassedID($event); -// return ($item_id == '') ? true : false; - } - - /** - * Saves edited item into temp table - * If there is no id, new item is created in temp table - * - * @param kEvent $event - */ - function OnPreSave(&$event) - { - //$event->redirect = false; - // if there is no id - it means we need to create an item - if (is_object($event->MasterEvent)) { - $event->MasterEvent->setEventParam('IsNew',false); - } - - if ($this->isNewItemCreate($event)) { - $event->CallSubEvent('OnPreSaveCreated'); - if (is_object($event->MasterEvent)) { - $event->MasterEvent->setEventParam('IsNew',true); - } - return; - } - - $object =& $event->getObject( Array('skip_autoload' => true) ); - - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if ($items_info) { - foreach ($items_info as $id => $field_values) { - $object->SetDefaultValues(); - $object->Load($id); - $object->SetFieldsFromHash($field_values); - $this->customProcessing($event, 'before'); - if( $object->Update($id) ) - { - $this->customProcessing($event, 'after'); - $event->status=erSUCCESS; - } - else { - $event->status = erFAIL; - $event->redirect = false; - break; - } - } - } - } - - /** - * [HOOK] Saves subitem - * - * @param kEvent $event - */ - function OnPreSaveSubItem(&$event) - { - $not_created = $this->isNewItemCreate($event); - - $event->CallSubEvent($not_created ? 'OnCreate' : 'OnUpdate'); - if ($event->status == erSUCCESS) { - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $this->Application->SetVar($event->getPrefixSpecial() . '_id', $object->GetID()); - } - - $event->SetRedirectParam('opener', 's'); - } - - /** - * Saves edited item in temp table and loads - * item with passed id in current template - * Used in Prev/Next buttons - * - * @param kEvent $event - */ - function OnPreSaveAndGo(&$event) - { - $event->CallSubEvent('OnPreSave'); - - if ($event->status == erSUCCESS) { - $id = $this->Application->GetVar($event->getPrefixSpecial(true) . '_GoId'); - $event->SetRedirectParam($event->getPrefixSpecial() . '_id', $id); - } - } - - /** - * Saves edited item in temp table and goes - * to passed tabs, by redirecting to it with OnPreSave event - * - * @param kEvent $event - */ - function OnPreSaveAndGoToTab(&$event) - { - $event->CallSubEvent('OnPreSave'); - if ($event->status==erSUCCESS) { - $event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab'); - } - } - - /** - * Saves editable list and goes to passed tab, - * by redirecting to it with empty event - * - * @param kEvent $event - */ - function OnUpdateAndGoToTab(&$event) - { - $event->setPseudoClass('_List'); - $event->CallSubEvent('OnUpdate'); - if ($event->status==erSUCCESS) { - $event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab'); - } - } - - /** - * Prepare temp tables for creating new item - * but does not create it. Actual create is - * done in OnPreSaveCreated - * - * @param kEvent $event - */ - function OnPreCreate(&$event) - { - $this->setTempWindowID($event); - $this->clearSelectedIDs($event); - - $object =& $event->getObject( Array('skip_autoload' => true) ); - - $temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler'); - $temp->PrepareEdit(); - - $object->setID(0); - $this->Application->SetVar($event->getPrefixSpecial().'_id',0); - $this->Application->SetVar($event->getPrefixSpecial().'_PreCreate', 1); - - $event->redirect=false; - } - - /** - * Creates a new item in temp table and - * stores item id in App vars and Session on succsess - * - * @param kEvent $event - */ - function OnPreSaveCreated(&$event) - { - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if($items_info) $field_values = array_shift($items_info); - - $object =& $event->getObject( Array('skip_autoload' => true) ); - $object->SetFieldsFromHash($field_values); - - $this->customProcessing($event, 'before'); - - if( $object->Create() ) - { - $this->customProcessing($event, 'after'); - $event->redirect_params[$event->getPrefixSpecial(true).'_id'] = $object->GetId(); - $event->status=erSUCCESS; - } - else - { - $event->status=erFAIL; - $event->redirect=false; - $object->setID(0); - } - - } - - function OnReset(&$event) - { - //do nothing - should reset :) - if ($this->isNewItemCreate($event)) { - // just reset id to 0 in case it was create - $object =& $event->getObject( Array('skip_autoload' => true) ); - $object->setID(0); - $this->Application->SetVar($event->getPrefixSpecial().'_id',0); - } - } - - /** - * Apply same processing to each item beeing selected in grid - * - * @param kEvent $event - * @access private - */ - function iterateItems(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $object =& $event->getObject( Array('skip_autoload' => true) ); - $ids = $this->StoreSelectedIDs($event); - - if ($ids) { - $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') ); - $order_field = $this->Application->getUnitOption($event->Prefix,'OrderField'); - - if (!$order_field) { - $order_field = 'Priority'; - } - - foreach ($ids as $id) { - $object->Load($id); - - switch ($event->Name) { - case 'OnMassApprove': - $object->SetDBField($status_field, 1); - break; - - case 'OnMassDecline': - $object->SetDBField($status_field, 0); - break; - - case 'OnMassMoveUp': - $object->SetDBField($order_field, $object->GetDBField($order_field) + 1); - break; - - case 'OnMassMoveDown': - $object->SetDBField($order_field, $object->GetDBField($order_field) - 1); - break; - } - - if ($object->Update()) { - $event->status = erSUCCESS; - } - else { - $event->status = erFAIL; - $event->redirect = false; - break; - } - } - } - - $this->clearSelectedIDs($event); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnMassClone(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $event->status = erSUCCESS; - - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - - $ids = $this->StoreSelectedIDs($event); - - if ($ids) { - $temp->CloneItems($event->Prefix, $event->Special, $ids); - } - - $this->clearSelectedIDs($event); - } - - function check_array($records, $field, $value) - { - foreach ($records as $record) { - if ($record[$field] == $value) { - return true; - } - } - return false; - } - - function OnPreSavePopup(&$event) - { - $object =& $event->getObject(); - $this->RemoveRequiredFields($object); - $event->CallSubEvent('OnPreSave'); - - $this->finalizePopup($event); - } - - -/* End of Edit events */ - - // III. Events that allow to put some code before and after Update,Load,Create and Delete methods of item - - /** - * Occurse before loading item, 'id' parameter - * allows to get id of item beeing loaded - * - * @param kEvent $event - * @access public - */ - function OnBeforeItemLoad(&$event) - { - - } - - /** - * Occurse after loading item, 'id' parameter - * allows to get id of item that was loaded - * - * @param kEvent $event - * @access public - */ - function OnAfterItemLoad(&$event) - { - - } - - /** - * Occurse before creating item - * - * @param kEvent $event - * @access public - */ - function OnBeforeItemCreate(&$event) - { - - } - - /** - * Occurse after creating item - * - * @param kEvent $event - * @access public - */ - function OnAfterItemCreate(&$event) - { - - } - - /** - * Occurse before updating item - * - * @param kEvent $event - * @access public - */ - function OnBeforeItemUpdate(&$event) - { - - } - - /** - * Occurse after updating item - * - * @param kEvent $event - * @access public - */ - function OnAfterItemUpdate(&$event) - { - - } - - /** - * Occurse before deleting item, id of item beeing - * deleted is stored as 'id' event param - * - * @param kEvent $event - * @access public - */ - function OnBeforeItemDelete(&$event) - { - - } - - /** - * Occurse after deleting item, id of deleted item - * is stored as 'id' param of event - * - * @param kEvent $event - * @access public - */ - function OnAfterItemDelete(&$event) - { - - } - - /** - * Occurs after successful item validation - * - * @param kEvent $event - */ - function OnAfterItemValidate(&$event) - { - - } - - /** - * Occures after an item has been copied to temp - * Id of copied item is passed as event' 'id' param - * - * @param kEvent $event - */ - function OnAfterCopyToTemp(&$event) - { - - } - - /** - * Occures before an item is deleted from live table when copying from temp - * (temp handler deleted all items from live and then copy over all items from temp) - * Id of item being deleted is passed as event' 'id' param - * - * @param kEvent $event - */ - function OnBeforeDeleteFromLive(&$event) - { - - } - - /** - * Occures before an item is copied to live table (after all foreign keys have been updated) - * Id of item being copied is passed as event' 'id' param - * - * @param kEvent $event - */ - function OnBeforeCopyToLive(&$event) - { - - } - - /** - * !!! NOT FULLY IMPLEMENTED - SEE TEMP HANDLER COMMENTS (search by event name)!!! - * Occures after an item has been copied to live table - * Id of copied item is passed as event' 'id' param - * - * @param kEvent $event - */ - function OnAfterCopyToLive(&$event) - { - - } - - /** - * Occures before an item is cloneded - * Id of ORIGINAL item is passed as event' 'id' param - * Do not call object' Update method in this event, just set needed fields! - * - * @param kEvent $event - */ - function OnBeforeClone(&$event) - { - - } - - /** - * Occures after an item has been cloned - * Id of newly created item is passed as event' 'id' param - * - * @param kEvent $event - */ - function OnAfterClone(&$event) - { - - } - - /** - * Occures after list is queried - * - * @param kEvent $event - */ - function OnAfterListQuery(&$event) - { - - } - - /** - * Ensures that popup will be closed automatically - * and parent window will be refreshed with template - * passed - * - * @param kEvent $event - * @access public - */ - function finalizePopup(&$event) - { - $event->SetRedirectParam('opener', 'u'); - } - - /** - * Create search filters based on search query - * - * @param kEvent $event - * @access protected - */ - function OnSearch(&$event) - { - $event->setPseudoClass('_List'); - - $search_helper =& $this->Application->recallObject('SearchHelper'); - /* @var $search_helper kSearchHelper */ - - $search_helper->performSearch($event); - } - - /** - * Clear search keywords - * - * @param kEvent $event - * @access protected - */ - function OnSearchReset(&$event) - { - $search_helper =& $this->Application->recallObject('SearchHelper'); - /* @var $search_helper kSearchHelper */ - - $search_helper->resetSearch($event); - } - - /** - * Set's new filter value (filter_id meaning from config) - * - * @param kEvent $event - */ - function OnSetFilter(&$event) - { - $filter_id = $this->Application->GetVar('filter_id'); - $filter_value = $this->Application->GetVar('filter_value'); - - $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter'); - $view_filter = $view_filter ? unserialize($view_filter) : Array(); - - $view_filter[$filter_id] = $filter_value; - - $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) ); - } - - function OnSetFilterPattern(&$event) - { - $filters = $this->Application->GetVar($event->getPrefixSpecial(true).'_filters'); - if (!$filters) return ; - - $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter'); - $view_filter = $view_filter ? unserialize($view_filter) : Array(); - - $filters = explode(',', $filters); - foreach ($filters as $a_filter) { - list($id, $value) = explode('=', $a_filter); - $view_filter[$id] = $value; - } - $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) ); - $event->redirect = false; - } - - /** - * Add/Remove all filters applied to list from "View" menu - * - * @param kEvent $event - */ - function FilterAction(&$event) - { - $view_filter = Array(); - $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu'); - switch ($event->Name) - { - case 'OnRemoveFilters': - $filter_value = 1; - break; - - case 'OnApplyFilters': - $filter_value = 0; - break; - } - - foreach($filter_menu['Filters'] as $filter_key => $filter_params) - { - if(!$filter_params) continue; - $view_filter[$filter_key] = $filter_value; - } - $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) ); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnPreSaveAndOpenTranslator(&$event) - { - $this->Application->SetVar('allow_translation', true); - $object =& $event->getObject(); - $this->RemoveRequiredFields($object); - $event->CallSubEvent('OnPreSave'); - - if ($event->status == erSUCCESS) { - - $resource_id = $this->Application->GetVar('translator_resource_id'); - if ($resource_id) { - $t_prefixes = explode(',', $this->Application->GetVar('translator_prefixes')); - - $cdata =& $this->Application->recallObject($t_prefixes[1], null, Array('skip_autoload' => true)); - $cdata->Load($resource_id, 'ResourceId'); - if (!$cdata->isLoaded()) { - $cdata->SetDBField('ResourceId', $resource_id); - $cdata->Create(); - } - $this->Application->SetVar($cdata->getPrefixSpecial().'_id', $cdata->GetID()); - } - - $event->redirect = $this->Application->GetVar('translator_t'); - $event->redirect_params = Array('pass'=>'all,trans,'.$this->Application->GetVar('translator_prefixes'), - $event->getPrefixSpecial(true).'_id' => $object->GetID(), - 'trans_event' => 'OnLoad', - 'trans_prefix' => $this->Application->GetVar('translator_prefixes'), - 'trans_field' => $this->Application->GetVar('translator_field'), - 'trans_multi_line' => $this->Application->GetVar('translator_multi_line'), - ); - - // 1. SAVE LAST TEMPLATE TO SESSION (really needed here, because of tweaky redirect) - $last_template = $this->Application->RecallVar('last_template'); - preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets); - $this->Application->StoreVar('return_template', $this->Application->GetVar('t')); - } - } - - function RemoveRequiredFields(&$object) - { - // making all field non-required to achieve successful presave - foreach($object->Fields as $field => $options) - { - if(isset($options['required'])) - { - unset($object->Fields[$field]['required']); - } - } - } - - /** - * Saves selected user in needed field - * - * @param kEvent $event - */ - function OnSelectUser(&$event) - { - $items_info = $this->Application->GetVar('u'); - if ($items_info) { - $user_id = array_shift( array_keys($items_info) ); - - $object =& $event->getObject(); - $this->RemoveRequiredFields($object); - - $is_new = !$object->isLoaded(); - $is_main = substr($this->Application->GetVar($event->Prefix.'_mode'), 0, 1) == 't'; - - if ($is_new) { - $new_event = $is_main ? 'OnPreCreate' : 'OnNew'; - $event->CallSubEvent($new_event); - $event->redirect = true; - } - - $object->SetDBField($this->Application->RecallVar('dst_field'), $user_id); - - if ($is_new) { - $object->Create(); - if (!$is_main && $object->IsTempTable()) { - $object->setTempID(); - } - } - else { - $object->Update(); - } - } - - $event->SetRedirectParam($event->getPrefixSpecial().'_id', $object->GetID()); - $this->finalizePopup($event); - } - - -/** EXPORT RELATED **/ - - /** - * Shows export dialog - * - * @param kEvent $event - */ - function OnExport(&$event) - { - $selected_ids = $this->StoreSelectedIDs($event); - - if (implode(',', $selected_ids) == '') { - // K4 fix when no ids found bad selected ids array is formed - $selected_ids = false; - } - - $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' ); - - $this->Application->LinkVar('export_finish_t'); - $this->Application->LinkVar('export_progress_t'); - $this->Application->StoreVar('export_oroginal_special', $event->Special); - - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - - /*list ($index_file, $env) = explode('|', $this->Application->RecallVar('last_template')); - $finish_url = $this->Application->BaseURL('/admin').$index_file.'?'.ENV_VAR_NAME.'='.$env; - $this->Application->StoreVar('export_finish_url', $finish_url);*/ - - $redirect_params = Array ( - $this->Prefix . '.export_event' => 'OnNew', - 'pass' => 'all,' . $this->Prefix . '.export' - ); - - $event->setRedirectParams($redirect_params); - } - - /** - * Apply some special processing to - * object beeing recalled before using - * it in other events that call prepareObject - * - * @param Object $object - * @param kEvent $event - * @access protected - */ - function prepareObject(&$object, &$event) - { - if ($event->Special == 'export' || $event->Special == 'import') - { - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - /* @var $export_helper kCatDBItemExportHelper */ - - $export_helper->prepareExportColumns($event); - } - } - - /** - * Returns specific to each item type columns only - * - * @param kEvent $event - * @return Array - */ - function getCustomExportColumns(&$event) - { - return Array(); - } - - /** - * Export form validation & processing - * - * @param kEvent $event - */ - function OnExportBegin(&$event) - { - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - /* @var $export_helper kCatDBItemExportHelper */ - $export_helper->OnExportBegin($event); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnExportCancel(&$event) - { - $this->OnGoBack($event); - } - - /** - * Allows configuring export options - * - * @param kEvent $event - */ - function OnBeforeExportBegin(&$event) - { - - } - - function OnDeleteExportPreset(&$event) - { - $object =& $event->GetObject(); - - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if($items_info) - { - list($id,$field_values) = each($items_info); - $preset_key = $field_values['ExportPresets']; - - $export_settings = $this->Application->RecallPersistentVar('export_settings'); - if (!$export_settings) return ; - $export_settings = unserialize($export_settings); - if (!isset($export_settings[$event->Prefix])) return ; - - $to_delete = ''; - $export_presets = array(''=>''); - foreach ($export_settings[$event->Prefix] as $key => $val) { - if (implode('|', $val['ExportColumns']) == $preset_key) { - $to_delete = $key; - break; - } - } - if ($to_delete) { - unset($export_settings[$event->Prefix][$to_delete]); - $this->Application->StorePersistentVar('export_settings', serialize($export_settings)); - } - } - } - - /** - * Saves changes & changes language - * - * @param kEvent $event - */ - function OnPreSaveAndChangeLanguage(&$event) - { - $event->CallSubEvent('OnPreSave'); - - if ($event->status == erSUCCESS) { - $this->Application->SetVar('m_lang', $this->Application->GetVar('language')); - - $pass_vars = Array ('st_id', 'cms_id'); - foreach ($pass_vars as $pass_var) { - $data = $this->Application->GetVar($pass_var); - if ($data) { - $event->SetRedirectParam($pass_var, $data); - } - } - } - } - - /** - * Used to save files uploaded via swfuploader - * - * @param kEvent $event - */ - function OnUploadFile(&$event) - { - $event->status = erSTOP; - define('DBG_SKIP_REPORTING', 1); - echo "Flash requires that we output something or it won't fire the uploadSuccess event"; - - if (!$this->Application->HttpQuery->Post) { - // Variables {field, id, flashsid} are always submitted through POST! - // When file size is larger, then "upload_max_filesize" (in php.ini), - // then theese variables also are not submitted -> handle such case. - header('HTTP/1.0 413 File size exceeds allowed limit'); - return ; - } - - if (!$this->_checkFlashUploaderPermission($event)) { - // 403 Forbidden - header('HTTP/1.0 403 You don\'t have permissions to upload'); - return ; - } - - $value = $this->Application->GetVar('Filedata'); - - if (!$value || ($value['error'] != UPLOAD_ERR_OK)) { - // 413 Request Entity Too Large (file uploads disabled OR uploaded file was - // to large for web server to accept, see "upload_max_filesize" in php.ini) - header('HTTP/1.0 413 File size exceeds allowed limit'); - return ; - } - - $tmp_path = defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/'; - $fname = $value['name']; - $id = $this->Application->GetVar('id'); - if ($id) { - $fname = $id.'_'.$fname; - } - - $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); - $upload_dir = $fields[ $this->Application->GetVar('field') ]['upload_dir']; - - if (!is_writable($tmp_path) || !is_writable(FULL_PATH . $upload_dir)) { - // 500 Internal Server Error - // check both temp and live upload directory - header('HTTP/1.0 500 Write permissions not set on the server'); - return ; - } - - move_uploaded_file($value['tmp_name'], $tmp_path.$fname); - } - - /** - * Checks, that flash uploader is allowed to perform upload - * - * @param kEvent $event - * @return bool - */ - function _checkFlashUploaderPermission(&$event) - { - // Flash uploader does NOT send correct cookies, so we need to make our own check - $cookie_name = 'adm_' . $this->Application->ConfigValue('SessionCookieName'); - $this->Application->HttpQuery->Cookie['cookies_on'] = 1; - $this->Application->HttpQuery->Cookie[$cookie_name] = $this->Application->GetVar('flashsid'); - - // this prevents session from auto-expiring when KeepSessionOnBrowserClose & FireFox is used - $this->Application->HttpQuery->Cookie[$cookie_name . '_live'] = $this->Application->GetVar('flashsid'); - - $admin_ses =& $this->Application->recallObject('Session.admin'); - /* @var $admin_ses Session */ - - $backup_user_id = $this->Application->RecallVar('user_id'); // 1. backup user - $this->Application->StoreVar('user_id', $admin_ses->RecallVar('user_id')); // 2. fake user_id - - $check_event = new kEvent($event->getPrefixSpecial() . ':OnProcessSelected'); // 3. event, that have "add|edit" rule - $allowed_to_upload = $this->CheckPermission($check_event); // 4. check permission - - $this->Application->StoreVar('user_id', $backup_user_id); // 5. restore user id - - return $allowed_to_upload; - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnDeleteFile(&$event) - { - $event->status = erSTOP; - - if (strpos($this->Application->GetVar('file'), '../') !== false) { - return ; - } - - $object =& $event->getObject( Array ('skip_autoload' => true) ); - $options = $object->GetFieldOptions( $this->Application->GetVar('field') ); - - $var_name = $event->getPrefixSpecial() . '_file_pending_actions' . $this->Application->GetVar('m_wid'); - $schedule = $this->Application->RecallVar($var_name); - $schedule = $schedule ? unserialize($schedule) : Array (); - $schedule[] = Array ('action' => 'delete', 'file' => $path = FULL_PATH . $options['upload_dir'] . $this->Application->GetVar('file')); - $this->Application->StoreVar($var_name, serialize($schedule)); - $this->Application->Session->SaveData(); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnViewFile(&$event) - { - if (strpos($this->Application->GetVar('file'), '../') !== false) return ; - if ($this->Application->GetVar('tmp')) { - $path = (defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/').$this->Application->GetVar('id').'_'.$this->Application->GetVar('file'); - } - else { - $object =& $event->getObject(array('skip_autoload'=>true)); - $options = $object->GetFieldOptions($this->Application->GetVar('field')); - - $path = FULL_PATH.$options['upload_dir'].$this->Application->GetVar('file'); - } - - $path = str_replace('/', DIRECTORY_SEPARATOR, $path); - $type = mime_content_type($path); - - header('Content-Length: '.filesize($path)); - header('Content-Type: '.$type); - - safeDefine('DBG_SKIP_REPORTING',1); - - readfile($path); - exit(); - } - - /** - * Validates MInput control fields - * - * @param kEvent $event - */ - function OnValidateMInputFields(&$event) - { - $minput_helper =& $this->Application->recallObject('MInputHelper'); - /* @var $minput_helper MInputHelper */ - - $minput_helper->OnValidateMInputFields($event); - } - - /** - * Returns auto-complete values for ajax-dropdown - * - * @param kEvent $event - */ - function OnSuggestValues(&$event) - { - $this->Application->XMLHeader(); - - $field = $this->Application->GetVar('field'); - $cur_value = $this->Application->GetVar('cur_value'); - if (!$field || !$cur_value) { - exit; - } - - $limit = $this->Application->GetVar('limit'); - if (!$limit) { - $limit = 20; - } - - $object =& $event->getObject(); - $sql = 'SELECT DISTINCT '.$field.' - FROM '.$object->TableName.' - WHERE '.$field.' LIKE '.$this->Conn->qstr($cur_value.'%').' - ORDER BY '.$field.' - LIMIT 0,' . $limit; - - $data = $this->Conn->GetCol($sql); - - echo ''; - foreach ($data as $item) { - echo '' . htmlspecialchars($item) . ''; - } - echo ''; - - $event->status = erSTOP; - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnSaveWidths(&$event) - { - $event->status = erSTOP; - - $lang =& $this->Application->recallObject('lang.current'); -// header('Content-type: text/xml; charset='.$lang->GetDBField('Charset')); - - $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); - /* @var $picker_helper kColumnPickerHelper */ - $picker_helper->PreparePicker($event->getPrefixSpecial(), $this->Application->GetVar('grid_name')); - - $picker_helper->SaveWidths($event->getPrefixSpecial(), $this->Application->GetVar('widths')); - - echo 'OK'; - } - - /** - * Called from CSV import script after item fields - * are set and validated, but before actual item create/update. - * If event status is erSUCCESS, line will be imported, - * else it will not be imported but added to skipped lines - * and displayed in the end of import. - * Event status is preset from import script. - * - * @param kEvent $event - */ - function OnBeforeCSVLineImport(&$event) - { - // abstract, for hooking - } - - } - - -?> \ No newline at end of file