diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index d4fcb7a8d..df6dce1a1 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -122,7 +122,6 @@ class ActionController extends Zend_Controller_Action ->_setInvokeArgs($invokeArgs); $this->_helper = new Zend_Controller_Action_HelperBroker($this); - $this->handlerBrowserWindows(); $moduleName = $this->getModuleName(); $this->view->defaultTitle = static::DEFAULT_TITLE; $this->view->translationDomain = $moduleName !== 'default' ? $moduleName : 'icinga'; @@ -229,25 +228,12 @@ class ActionController extends Zend_Controller_Action public function Window() { if ($this->window === null) { - $this->window = new Window( - $this->_request->getHeader('X-Icinga-WindowId', Window::UNDEFINED) - ); + $this->window = Window::getInstance(); } + return $this->window; } - protected function handlerBrowserWindows() - { - if ($this->isXhr()) { - $id = $this->_request->getHeader('X-Icinga-WindowId', null); - - if ($id === Window::UNDEFINED) { - $this->window = new Window($id); - $this->_response->setHeader('X-Icinga-WindowId', Window::generateId()); - } - } - } - protected function reloadCss() { $this->reloadCss = true; diff --git a/library/Icinga/Web/Request.php b/library/Icinga/Web/Request.php index 4a3246d5f..064ce6335 100644 --- a/library/Icinga/Web/Request.php +++ b/library/Icinga/Web/Request.php @@ -114,12 +114,7 @@ class Request extends Zend_Controller_Request_Http */ public function protectId($id) { - if (! isset($this->uniqueId)) { - $windowId = $this->getHeader('X-Icinga-WindowId'); - $this->uniqueId = empty($windowId) ? Window::generateId() : $windowId; - } - - return $id . '-' . $this->uniqueId; + return $id . '-' . Window::getInstance()->getContainerId(); } public function getPost($key = null, $default = null) diff --git a/library/Icinga/Web/Response.php b/library/Icinga/Web/Response.php index 88d9e2302..d869f8f09 100644 --- a/library/Icinga/Web/Response.php +++ b/library/Icinga/Web/Response.php @@ -61,6 +61,13 @@ class Response extends Zend_Controller_Response_Http */ protected $rerenderLayout = false; + /** + * Whether to send the current window ID to the client + * + * @var bool + */ + protected $overrideWindowId = false; + /** * Get the auto-refresh interval * @@ -237,6 +244,29 @@ class Response extends Zend_Controller_Response_Http return $this; } + /** + * Get whether to send the current window ID to the client + * + * @return bool + */ + public function getOverrideWindowId() + { + return $this->overrideWindowId; + } + + /** + * Set whether to send the current window ID to the client + * + * @param bool $overrideWindowId + * + * @return $this + */ + public function setOverrideWindowId($overrideWindowId = true) + { + $this->overrideWindowId = $overrideWindowId; + return $this; + } + /** * Entry point for HTTP responses in JSON format * @@ -262,6 +292,9 @@ class Response extends Zend_Controller_Response_Http $this->setHeader('X-Icinga-Rerender-Layout', 'yes', true); } } + if ($this->getOverrideWindowId()) { + $this->setHeader('X-Icinga-WindowId', Window::getInstance()->getId(), true); + } if ($this->getRerenderLayout()) { $this->setHeader('X-Icinga-Container', 'layout', true); } diff --git a/library/Icinga/Web/Window.php b/library/Icinga/Web/Window.php index e6f1a05e1..158483a06 100644 --- a/library/Icinga/Web/Window.php +++ b/library/Icinga/Web/Window.php @@ -3,29 +3,63 @@ namespace Icinga\Web; -use Icinga\Web\Session; +use Icinga\Application\Icinga; +use Icinga\Web\Session\SessionNamespace; class Window { const UNDEFINED = 'undefined'; + /** @var Window */ + protected static $window; + + /** @var string */ protected $id; + /** @var string */ + protected $containerId; + public function __construct($id) { - $this->id = $id; + $parts = explode('_', $id, 2); + if (isset($parts[1])) { + $this->id = $parts[0]; + $this->containerId = $id; + } else { + $this->id = $id; + } } + /** + * Get whether the window's ID is undefined + * + * @return bool + */ public function isUndefined() { return $this->id === self::UNDEFINED; } + /** + * Get the window's ID + * + * @return string + */ public function getId() { return $this->id; } + /** + * Get the container's ID + * + * @return string + */ + public function getContainerId() + { + return $this->containerId ?: $this->id; + } + /** * Return a window-aware session by using the given prefix * @@ -38,29 +72,54 @@ class Window { $session = Session::getSession(); - $identifier = $prefix . '_' . $this->id; + $identifier = $prefix . '_' . $this->getId(); if ($reset && $session->hasNamespace($identifier)) { $session->removeNamespace($identifier); } + $namespace = $session->getNamespace($identifier); $nsUndef = $prefix . '_' . self::UNDEFINED; - if (!$reset && $this->id !== self::UNDEFINED && $session->hasNamespace($nsUndef)) { - // We do not have any window-id on the very first request. Now we add + if (! $reset && ! $this->isUndefined() && $session->hasNamespace($nsUndef)) { + // We may not have any window-id on the very first request. Now we add // all values from the namespace, that has been created in this case, // to the new one and remove it afterwards. foreach ($session->getNamespace($nsUndef) as $name => $value) { $namespace->set($name, $value); } + $session->removeNamespace($nsUndef); } return $namespace; } + /** + * Generate a random string + * + * @return string + */ public static function generateId() { $letters = 'abcefghijklmnopqrstuvwxyz'; return substr(str_shuffle($letters), 0, 12); } + + /** + * @return Window + */ + public static function getInstance() + { + if (! isset(static::$window)) { + $id = Icinga::app()->getRequest()->getHeader('X-Icinga-WindowId'); + if (empty($id) || $id === static::UNDEFINED) { + Icinga::app()->getResponse()->setOverrideWindowId(); + $id = static::generateId(); + } + + static::$window = new Window($id); + } + + return static::$window; + } }