From be4ff3c091cff13af49041b59f12f97a466b0040 Mon Sep 17 00:00:00 2001 From: Thomas Steur Date: Mon, 1 Feb 2016 14:52:20 +0000 Subject: show error message in case we deactivate a plugin because of missing dependencies --- core/Notification/Manager.php | 59 ++++++++++++++++++++++++++++++++----------- core/Plugin/Manager.php | 11 ++++++++ libs/README.md | 1 + libs/Zend/Session.php | 13 ++++++++++ 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/core/Notification/Manager.php b/core/Notification/Manager.php index e7eafec49e..bdf1f130dd 100644 --- a/core/Notification/Manager.php +++ b/core/Notification/Manager.php @@ -23,6 +23,11 @@ class Manager */ private static $session = null; + /** + * @var Notification[] + */ + private static $notifications = array(); + /** * Posts a notification that will be shown in Piwik's status bar. If a notification with the same ID * has been posted and has not been closed/removed, it will be replaced with `$notification`. @@ -105,12 +110,21 @@ class Manager private static function addNotification($id, Notification $notification) { - if (!self::isEnabled()) { - return; - } + self::saveNotificationAcrossUiRequestsIfNeeded($id, $notification); - $session = static::getSession(); - $session->notifications[$id] = $notification; + // we store all kinda notifications here so in case the session is not enabled or disabled later there is still + // a chance it gets delivered to the UI during the same request. + self::$notifications[$id] = $notification; + } + + private static function saveNotificationAcrossUiRequestsIfNeeded($id, Notification $notification) + { + $isPersistent = $notification->type === Notification::TYPE_PERSISTENT; + + if ($isPersistent && self::isSessionEnabled()) { + $session = static::getSession(); + $session->notifications[$id] = $notification; + } } private static function removeOldestNotificationsIfThereAreTooMany() @@ -126,28 +140,43 @@ class Manager private static function getAllNotifications() { - if (!self::isEnabled()) { + if (!self::isSessionEnabled()) { return array(); } - $session = static::getSession(); + $notifications = self::$notifications; + + foreach ($notifications as $id => $notification) { + // we copy them over to the session if possible and persist it in case the session was not yet + // writable / enabled at the time the notification was added. + self::saveNotificationAcrossUiRequestsIfNeeded($id, $notification); + } - return $session->notifications; + if (self::isSessionEnabled()) { + $session = static::getSession(); + foreach ($session->notifications as $id => $notification) { + $notifications[$id] = $notification; + } + } + + return $notifications; } private static function removeNotification($id) { - if (!self::isEnabled()) { - return; + if (array_key_exists($id, self::$notifications)) { + unset(self::$notifications[$id]); } - $session = static::getSession(); - if (array_key_exists($id, $session->notifications)) { - unset($session->notifications[$id]); + if (self::isSessionEnabled()) { + $session = static::getSession(); + if (array_key_exists($id, $session->notifications)) { + unset($session->notifications[$id]); + } } } - private static function isEnabled() + private static function isSessionEnabled() { return Session::isWritable() && Session::isReadable(); } @@ -161,7 +190,7 @@ class Manager static::$session = new SessionNamespace('notification'); } - if (empty(static::$session->notifications) && self::isEnabled()) { + if (empty(static::$session->notifications) && self::isSessionEnabled()) { static::$session->notifications = array(); } diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 63a3e0aaaf..2b552f48e0 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -18,9 +18,11 @@ use Piwik\Container\StaticContainer; use Piwik\EventDispatcher; use Piwik\Filesystem; use Piwik\Log; +use Piwik\Notification; use Piwik\Piwik; use Piwik\Plugin; use Piwik\PluginDeactivatedException; +use Piwik\Session; use Piwik\Theme; use Piwik\Tracker; use Piwik\Translation\Translator; @@ -828,6 +830,15 @@ class Manager if ($newPlugin->hasMissingDependencies()) { $this->deactivatePlugin($pluginName); + + // add this state we do not know yet whether current user has super user access. We do not even know + // if someone is actually logged in. + $message = sprintf('We disabled the plugin %s as it has missing dependencies.', $pluginName); + $message .= ' Please contact your Piwik administrator.'; + + $notification = new Notification($message); + $notification->context = Notification::CONTEXT_ERROR; + Notification\Manager::notify('PluginManager_PluginDeactivated', $notification); continue; } diff --git a/libs/README.md b/libs/README.md index f5a061a1dc..083684c962 100644 --- a/libs/README.md +++ b/libs/README.md @@ -30,3 +30,4 @@ third-party libraries: - ZF-10871 - undefined variables when socket support disabled - fix #6980 ("Array to string conversion") in `Zend/Session/Exception.php` - fix Zend/Validate using deprecated iconv_set_encoding() + - Make sure sessions work when storing notifications diff --git a/libs/Zend/Session.php b/libs/Zend/Session.php index b5177c18fd..8b55a17b6d 100644 --- a/libs/Zend/Session.php +++ b/libs/Zend/Session.php @@ -491,6 +491,10 @@ class Zend_Session extends Zend_Session_Abstract self::regenerateId(); } + if (isset($_SESSION['data']) && is_string($_SESSION['data'])) { + $_SESSION = unserialize(base64_decode($_SESSION['data'])); + } + // run validators if they exist if (isset($_SESSION['__ZF']['VALID'])) { self::_processValidators(); @@ -688,8 +692,17 @@ class Zend_Session extends Zend_Session_Abstract parent::$_writable = false; } + if (isset($_SESSION)) { + $sessionBkp = $_SESSION; + $_SESSION = array('data' => base64_encode(serialize($_SESSION))); + } + session_write_close(); self::$_writeClosed = true; + + if (isset($sessionBkp)) { + $_SESSION = $sessionBkp; + } } -- cgit v1.2.3