processed ) { return; } $this->dumpRequest(); $this->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)); $this->processed = true; } /** * Dumps user request to debugger (only when enabled) * * @return void * @access protected */ protected function dumpRequest() { if ( defined('DEBUG_MODE') && $this->Application->isDebugMode() && kUtil::constOn('DBG_SHOW_HTTPQUERY') ) { $this->Application->Debugger->appendHTML('HTTPQuery:'); $this->Application->Debugger->dumpVars($this->Application->HttpQuery->_Params); } } /** * 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->SetRedirectParam('opener', 's'); // stay on same page after event is called $event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true)); /** @var kEventHandler $event_handler */ $event_handler = $this->Application->recallObject($event->Prefix . '_EventHandler'); if ( $this->Application->permissionCheckingDisabled() || $event_handler->CheckPermission($event) ) { $this->Application->HandleEvent($event); $this->Application->notifyEventSubscribers($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'); /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); $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_category 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'); $redirect_params = $event->getRedirectParams(); if ( $wid && $event->getRedirectParam('opener') == 'u' ) { // update last element in current opener stack unset($redirect_params['opener']); $redirect_template = is_string($event->redirect) ? $event->redirect : null; $this->openerStackChange($redirect_template, $redirect_params); // reset opener, because kApplication::HREF will react differently when 'opener' => 'u' $event->SetRedirectParam('opener', 's'); $event->redirect = defined('CLOSE_POPUP_TPL') ? CLOSE_POPUP_TPL : 'incs/close_popup'; } if ( $event->getRedirectParam('pass') === false ) { // pass all discovered units to redirected page unless developer decided otherwise $event->SetRedirectParam('pass', 'all'); } $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() { /** @var kOpenerStack $opener_stack */ $opener_stack = $this->Application->makeClass('kOpenerStack'); switch ( $this->Application->GetVar('m_opener') ) { case 'r': $opener_stack->reset(); break; case 'd': // "down/push" new template to opener stack, deeplevel++ if ( $this->Application->GetVar('front') ) { /** @var Session $front_session */ $front_session = $this->Application->recallObject('Session.front'); $opener_stack->pushRaw( '../' . $front_session->RecallVar('last_template') ); } else { $opener_stack->pushRaw( $this->Application->RecallVar('last_template') ); } break; case 'u': // "up/pop" last template from opener stack, deeplevel-- $opener_stack->pop(); 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); /** @var kOpenerStack $popup_opener_stack */ $popup_opener_stack = $this->Application->makeClass('kOpenerStack', Array ($popup_wid)); $popup_opener_stack->pushRaw( $this->getLastTemplate($parent_wid) ); $popup_opener_stack->save(); $this->Application->SetVar('m_opener', 's'); /*// 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));*/ return; break; default: // "s/0," stay on same deep level break; } $this->Application->SetVar('m_opener', 's'); $opener_stack->save(); } /** * Returns last template from window with given id * * @param int $window_id * @return string * @access protected */ protected function getLastTemplate($window_id) { if ( $this->Application->GetVar('front') ) { /** @var Session $front_session */ $front_session = $this->Application->recallObject('Session.front'); return '../' . $front_session->RecallVar( rtrim('last_template_popup_' . $window_id, '_') ); } if ( $this->Application->GetVar('merge_opener_stack') ) { // get last template from parent (that was closed) window opener stack /** @var kOpenerStack $parent_opener_stack */ $parent_opener_stack = $this->Application->makeClass('kOpenerStack', Array ($window_id)); $last_template = $parent_opener_stack->pop(true); $parent_opener_stack->save(true); } else { $last_template = $this->Application->RecallVar( rtrim('last_template_popup_' . $window_id, '_') ); } return $last_template; } /** * Allows to add new element to opener stack * * @param string $template * @param Array $params * @param int $wid * @access public */ public function openerStackPush($template = '', $params = Array (), $wid = null) { if ( !isset($params['pass']) ) { $params['pass'] = 'all'; } /*// get parent window wid, when this was popup $window_relations = $this->Application->RecallVar('window_relations'); $window_relations = $window_relations ? unserialize($window_relations) : Array (); $wid = isset($window_relations[$wid]) ? $window_relations[$wid] : false;*/ /** @var kOpenerStack $opener_stack */ $opener_stack = $this->Application->makeClass('kOpenerStack', Array ($wid)); // change opener stack $default_params = Array ('m_opener' => 'u'); if ( !$this->Application->ConfigValue('UsePopups') && $opener_stack->getWindowID() ) { // remove wid to show combined header block in editing window $default_params['m_wid'] = ''; list ($last_template, $last_params, ) = $opener_stack->get(kOpenerStack::LAST_ELEMENT); // move last popup's opener stack element to main window's opener stack if ( $last_params ) { $last_params = array_merge($last_params, $default_params); $this->openerStackPush($last_template, $last_params, ''); } } $params = array_merge($default_params, $params); $opener_stack->push($template, $params, 'index.php'); $opener_stack->save(); } /** * Allows to change last element in opener stack * * @param string $new_template * @param Array $new_params * @access protected */ protected function openerStackChange($new_template = null, $new_params = null) { /** @var kOpenerStack $opener_stack */ $opener_stack = $this->Application->makeClass('kOpenerStack'); list ($template, $params, $index_file) = $opener_stack->pop(); if ( isset($new_template) ) { $template = $new_template; } if ( isset($new_params) ) { $params = array_merge($params, $new_params); } if ( !isset($params['pass_events']) ) { // don't pass events, unless requested $params['pass_events'] = false; } $opener_stack->push($template, $params, $index_file); $opener_stack->save(); } }