processOpener(); $events = $this->getEvents(); $all_passed = $this->getAllPassed($events); // set "all_passed" before kApplication::GetTopmostPrefix method call ! $this->Application->SetVar('all_passed', implode(',', $all_passed)); foreach ($events as $prefix_special => $event_name) { $event =& $this->runEvent($prefix_special, $event_name); if ( $event->status == kEvent::erSTOP ) { // event requested to stop processing at this point kUtil::safeDefine('DBG_SKIP_REPORTING', 1); $this->Application->Session->SaveData(); exit; } if ( $event->status == kEvent::erPERM_FAIL ) { $this->processPermissionError($event); } if ( ($event->status == kEvent::erSUCCESS || $event->status == kEvent::erPERM_FAIL) && $this->canRedirect($event) ) { $this->performRedirect($event); } } $this->Application->SetVar('events', $events); $this->Application->SetVar('passed', implode(',', $all_passed)); } /** * Returns event names, given in request (post, get) * * @return Array * @access protected */ protected function getEvents() { $post_events = $this->getEventsFromPost(); return $post_events ? $post_events : $this->getEventsFromGet(); } /** * Get all passed prefixes * * @param Array $events * @return Array * @access protected */ protected function getAllPassed($events) { $ret = explode(',', $this->Application->GetVar('passed')); foreach ($events as $prefix_special => $event_name) { if (!$event_name) { continue; } if ($this->Application->isAdmin) { array_push($ret, $prefix_special); } else { // don't add special on Front-end because of category item list special is autogenerated $prefix_special = explode('.', $prefix_special); array_push($ret, $prefix_special[0]); } } return $ret; } /** * Creates and runs event. Returns false, when prefix of given event isn't registered * * @param string $prefix_special * @param string $event_name * * @return kEvent|false * @access protected */ protected function &runEvent($prefix_special, $event_name) { $event = new kEvent($prefix_special . ':' . $event_name); if ( preg_match('/(.*?)-(.*)/', $event->Prefix, $regs) && $this->Application->prefixRegistred($regs[1]) ) { // this is event from cloned config -> load parent config to create valid clone $this->Application->UnitConfigReader->loadConfig($regs[1]); $this->Application->UnitConfigReader->runAfterConfigRead($regs[1]); } if ( !$this->Application->EventManager->verifyEventPrefix($event, true) ) { $false = false; return $false; } $event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true)); $event_handler =& $this->Application->recallObject($event->Prefix . '_EventHandler'); /* @var $event_handler kEventHandler */ if ( ($this->Application->RecallVar('user_id') == USER_ROOT) || $event_handler->CheckPermission($event) ) { $this->Application->HandleEvent($event); } return $event; } /** * Processes case, when event finished with permission error * * @param kEvent $event * @access protected */ protected function processPermissionError(&$event) { // should do redirect but to no_permissions template $event->redirect = $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate'); $event->SetRedirectParam('pass', 'm'); $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $event->SetRedirectParam( 'm_cat_id', $themes_helper->getPageByTemplate($event->redirect) ); // restore stuff, that processOpener() changed $wid = $this->Application->GetVar('m_wid'); $this->Application->RestoreVar( rtrim('opener_stack_' . $wid, '_') ); // don't save last_template, because no_permission template does js history.back and could cause invalid opener_stack content $this->Application->SetVar('skip_last_template', 1); } /** * Performs redirect after event execution * * @param kEvent $event * @access protected */ protected function performRedirect(&$event) { // we need to pass category if the action was submitted to self-template, with the category passed // and it has not explicitly set redirect template or pass_cateogry param if ( $this->samePageRedirect($event) && ($event->getEventParam('pass_category') === false) && $this->Application->GetVar('m_cat_id') ) { $event->SetRedirectParam('pass_category', 1); } $wid = $this->Application->GetVar('m_wid'); if ($wid && $event->getRedirectParam('opener') == 'u') { $event->SetRedirectParam('opener', 's'); // because Application->HREF will react differently when 'opener' = 'u' $event->redirect = defined('CLOSE_POPUP_TPL') ? CLOSE_POPUP_TPL : 'incs/close_popup'; } $this->Application->Redirect($event->redirect, $event->getRedirectParams(), '', $event->redirectScript); } /** * Checks, if redirect can be made * * @param kEvent $event * @return bool * @access protected */ protected function canRedirect(&$event) { return $this->samePageRedirect($event) || strlen($event->redirect) > 0; } /** * Checks, that current template will be displayed after redirect * * @param kEvent $event * @return bool * @access protected */ protected function samePageRedirect(&$event) { return $event->redirect === true || $event->redirect == $this->Application->GetVar('t'); } /** * Returns event names given in GET * * @return Array * @access protected */ protected function getEventsFromGet() { $events = Array (); $discovered_units = $this->Application->HttpQuery->getDiscoveredUnits(false); foreach ($discovered_units as $prefix_special => $query_string) { $query_string = array_flip($query_string); if ( !isset($query_string['event']) ) { continue; } $event_name = $this->Application->GetVar($prefix_special . '_event'); // we need to check for pre 5.1.0 url format, because of "PerPage" // query string part (that was added in place of "event" query // string part) is available only since 5.1.0 version if ($event_name && !is_numeric($event_name)) { $events[$prefix_special] = $event_name; } } return $events; } /** * Returns event names given in POST * * @return Array * @access protected */ protected function getEventsFromPost() { $ret = Array (); $events = $this->Application->GetVar('events'); if (!$events) { return Array (); } foreach ($events as $prefix_special => $event_name) { if (!$event_name) { continue; } if ( is_array($event_name) ) { // HTML-input names like "events[prefix.special][event_name]", input value don't matter $event_name = key($event_name); $this->Application->SetVar($prefix_special . '_event', $event_name); } // HTML-input names like "events[prefix.special]", input value is event name $ret[$prefix_special] = $event_name; } return $ret; } /** * Processes window opener stack * * @access protected */ protected function processOpener() { $wid = $this->Application->GetVar('m_wid'); $opener_action = $this->Application->GetVar('m_opener'); $opener_stack = $this->Application->RecallVar(rtrim('opener_stack_'.$wid, '_')); $opener_stack = $opener_stack ? unserialize($opener_stack) : Array(); switch ($opener_action) { case 'r': // "reset" opener stack $opener_stack = Array (); break; case 'd': // "down/push" new template to opener stack, deeplevel++ if ( $this->Application->GetVar('front') ) { $front_session =& $this->Application->recallObject('Session.front'); /* @var $front_session Session */ array_push( $opener_stack, '../' . $front_session->RecallVar('last_template') ); } else { array_push( $opener_stack, $this->Application->RecallVar('last_template') ); } break; case 'u': // "up/pop" last template from opener stack, deeplevel-- array_pop($opener_stack); break; case 'p': // pop-up - generate new wid $parent_wid = $this->Application->GetVar('m_wid'); // window_id of popup's parent window $popup_wid = (int)$this->Application->RecallVar('last_wid') + 1; $this->Application->StoreVar('last_wid', $popup_wid); $this->Application->SetVar('m_wid', $popup_wid); if ( $this->Application->GetVar('front') ) { $front_session =& $this->Application->recallObject('Session.front'); /* @var $front_session Session */ $last_template = '../' . $front_session->RecallVar( rtrim('last_template_popup_' . $parent_wid, '_') ); } else { if ( $this->Application->GetVar('merge_opener_stack') ) { // get last template from parent (that was closed) window opener stack $parent_opener_stack_name = rtrim('opener_stack_' . $parent_wid, '_'); $parent_opener_stack = unserialize( $this->Application->RecallVar($parent_opener_stack_name) ); $last_template = array_pop($parent_opener_stack); if ($parent_opener_stack) { $this->Application->StoreVar( $parent_opener_stack_name, serialize($parent_opener_stack) ); } else { $this->Application->RemoveVar( $parent_opener_stack_name ); } } else { $last_template = $this->Application->RecallVar( rtrim('last_template_popup_' . $parent_wid, '_') ); } } $opener_stack = Array ($last_template); $this->Application->SetVar('m_opener', 's'); $wid = $popup_wid; /*// store window relations $window_relations = $this->Application->RecallVar('window_relations'); $window_relations = $window_relations ? unserialize($window_relations) : Array (); $window_relations[$popup_wid] = $parent_wid; $this->Application->StoreVar('window_relations', serialize($window_relations));*/ break; default: // "s/0," stay on same deep level break; } $this->Application->SetVar('m_opener', 's'); $this->Application->StoreVar(rtrim('opener_stack_' . $wid, '_'), serialize($opener_stack), !$opener_stack); // empty stack is optional } /** * Allows to add new element to opener stack * * @param string $template * @param Array $params * @param string $pass * @access public */ public function openerStackPush($template, $params, $pass = 'all', $wid = null) { if (!isset($wid)) { $wid = $this->Application->GetVar('m_wid'); } /*// get parent window wid, when this was popup $window_relations = $this->Application->RecallVar('window_relations'); $window_relations = $window_relations ? unserialize($window_relations) : Array (); $wid = array_key_exists($wid, $window_relations) ? $window_relations[$wid] : false;*/ // get opener stack $stack_name = rtrim('opener_stack_' . $wid, '_'); $opener_stack = $this->Application->RecallVar($stack_name); $opener_stack = $opener_stack ? unserialize($opener_stack) : Array (); // change opener stack $default_params = Array ('m_opener' => 'u', '__URLENCODE__' => 1); if (!$this->Application->ConfigValue('UsePopups') && $wid) { // remove wid to show combined header block in editing window $default_params['m_wid'] = ''; // move last popup's opener stack elemenent to main window's opener stack if ($opener_stack) { list ($index_file, $env) = explode('|', $opener_stack[ count($opener_stack) - 1 ], 2); $main_params = $this->Application->HttpQuery->processQueryString($env, 'pass'); $main_template = $main_params['t']; unset($main_params['t']); $main_params = array_merge($main_params, $default_params); $this->openerStackPush($main_template, $main_params, $main_params['pass'], ''); } } $redirect_params = array_merge($default_params, $params); $new_level = $this->Application->BuildEnv($template, $redirect_params, $pass, true); array_push($opener_stack, 'index.php|' . ltrim($new_level, ENV_VAR_NAME . '=') ); $this->Application->StoreVar($stack_name, serialize($opener_stack)); } /** * Allows to change last element in opener stack * * @param string $template * @param Array $params * @param string $pass * @access public */ public function openerStackChange($params = Array(), $pass_events = true, $wid = null) { if (!isset($wid)) { $wid = $this->Application->GetVar('m_wid'); } // get opener stack $stack_name = rtrim('opener_stack_' . $wid, '_'); $opener_stack = $this->Application->RecallVar($stack_name); $opener_stack = $opener_stack ? unserialize($opener_stack) : Array (); // change opener stack list ($index_file, $env) = explode('|', $opener_stack[ count($opener_stack) - 1 ], 2); $vars = $this->Application->HttpQuery->processQueryString($env, 'pass'); $vars = array_merge($vars, $params); // save opener stack $new_level = $this->Application->BuildEnv($vars['t'], $vars, $vars['pass'], $pass_events, false); $opener_stack[ count($opener_stack) - 1 ] = $index_file . '|' . $new_level; $this->Application->StoreVar($stack_name, serialize($opener_stack)); } }