From a9d032329cf2bb357a12c06fb43d3cce6d50311c Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Fri, 6 Mar 2015 13:21:31 -0500 Subject: [PATCH] Centralized cookie handling, with new config options. - Thanks to Ere Maijala for initial inspiration and subsequent feedback. --- config/vufind/config.ini | 18 +- module/VuFind/config/module.config.php | 5 +- module/VuFind/src/VuFind/Auth/Factory.php | 4 +- module/VuFind/src/VuFind/Auth/Manager.php | 21 +- module/VuFind/src/VuFind/Bootstrapper.php | 5 +- module/VuFind/src/VuFind/Cart.php | 48 ++--- .../VuFind/src/VuFind/Controller/Factory.php | 14 ++ .../VuFind/Controller/UpgradeController.php | 6 +- module/VuFind/src/VuFind/Cookie/Container.php | 49 ++--- .../src/VuFind/Cookie/CookieManager.php | 185 ++++++++++++++++++ module/VuFind/src/VuFind/Service/Factory.php | 55 +++++- .../src/VuFindTest/Auth/ManagerTest.php | 3 +- .../unit-tests/src/VuFindTest/CartTest.php | 52 +++-- .../src/VuFindTheme/Initializer.php | 15 +- 14 files changed, 379 insertions(+), 101 deletions(-) create mode 100644 module/VuFind/src/VuFind/Cookie/CookieManager.php diff --git a/config/vufind/config.ini b/config/vufind/config.ini index d642050dc8b..5bb59850880 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -89,9 +89,6 @@ showBookBag = false bookBagMaxSize = 100 ; Display bulk items (export, save, etc.) and checkboxes on search result screens? showBulkOptions = false -; Set the domain used for cart-related cookies (sometimes useful for sharing the -; cookies across subdomains) -;bookBagCookieDomain = ".example.edu" ; Generator value to display in an HTML header <meta> tag: generator = "VuFind 2.3.1" @@ -113,6 +110,21 @@ lifetime = 3600 ; Session lasts for 1 hour ;memcache_port = 11211 ;memcache_connection_timeout = 1 +; This section controls how VuFind creates cookies (to store session IDs, bookbag +; contents, theme/language settings, etc.) +[Cookies] +; In case there are multiple VuFind instances on the same server and they should not +; share cookies/sessions, this option can be enabled to limit the session to the +; current path. Default is false, which will place cookies at the root directory. +;limit_by_path = true +; If VuFind is only accessed via HTTPS, this setting can be enabled to disallow +; the browser from ever sending cookies over an unencrypted connection (i.e. +; before being redirected to HTTPS). Default is false. +;only_secure = true +; Set the domain used for cookies (sometimes useful for sharing the cookies across +; subdomains); by default, cookies will be restricted to the current hostname. +;domain = ".example.edu" + ; Please set the ILS that VuFind will interact with. ; ; Available drivers: Aleph, Amicus, ClaviusSQL, Evergreen, Horizon (basic database diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index ff53d0003f7..800c7834ba1 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -66,6 +66,7 @@ $config = [ 'collection' => 'VuFind\Controller\Factory::getCollectionController', 'collections' => 'VuFind\Controller\Factory::getCollectionsController', 'record' => 'VuFind\Controller\Factory::getRecordController', + 'upgrade' => 'VuFind\Controller\Factory::getUpgradeController', ], 'invokables' => [ 'ajax' => 'VuFind\Controller\AjaxController', @@ -99,7 +100,6 @@ $config = [ 'summon' => 'VuFind\Controller\SummonController', 'summonrecord' => 'VuFind\Controller\SummonrecordController', 'tag' => 'VuFind\Controller\TagController', - 'upgrade' => 'VuFind\Controller\UpgradeController', 'web' => 'VuFind\Controller\WebController', 'worldcat' => 'VuFind\Controller\WorldcatController', 'worldcatrecord' => 'VuFind\Controller\WorldcatrecordController', @@ -139,6 +139,7 @@ $config = [ 'VuFind\ContentCoversPluginManager' => 'VuFind\Service\Factory::getContentCoversPluginManager', 'VuFind\ContentExcerptsPluginManager' => 'VuFind\Service\Factory::getContentExcerptsPluginManager', 'VuFind\ContentReviewsPluginManager' => 'VuFind\Service\Factory::getContentReviewsPluginManager', + 'VuFind\CookieManager' => 'VuFind\Service\Factory::getCookieManager', 'VuFind\DateConverter' => 'VuFind\Service\Factory::getDateConverter', 'VuFind\DbAdapter' => 'VuFind\Service\Factory::getDbAdapter', 'VuFind\DbAdapterFactory' => 'VuFind\Service\Factory::getDbAdapterFactory', @@ -172,6 +173,7 @@ $config = [ 'VuFind\SearchResultsPluginManager' => 'VuFind\Service\Factory::getSearchResultsPluginManager', 'VuFind\SearchSpecsReader' => 'VuFind\Service\Factory::getSearchSpecsReader', 'VuFind\SearchStats' => 'VuFind\Service\Factory::getSearchStats', + 'VuFind\SessionManager' => 'VuFind\Service\Factory::getSessionManager', 'VuFind\SessionPluginManager' => 'VuFind\Service\Factory::getSessionPluginManager', 'VuFind\SMS' => 'VuFind\SMS\Factory', 'VuFind\Solr\Writer' => 'VuFind\Service\Factory::getSolrWriter', @@ -181,7 +183,6 @@ $config = [ 'VuFind\WorldCatUtils' => 'VuFind\Service\Factory::getWorldCatUtils', ], 'invokables' => [ - 'VuFind\SessionManager' => 'Zend\Session\SessionManager', 'VuFind\Search' => 'VuFindSearch\Service', 'VuFind\Search\Memory' => 'VuFind\Search\Memory', 'VuFind\HierarchicalFacetHelper' => 'VuFind\Search\Solr\HierarchicalFacetHelper' diff --git a/module/VuFind/src/VuFind/Auth/Factory.php b/module/VuFind/src/VuFind/Auth/Factory.php index 9358d3157b6..3c0d1df9300 100644 --- a/module/VuFind/src/VuFind/Auth/Factory.php +++ b/module/VuFind/src/VuFind/Auth/Factory.php @@ -108,16 +108,16 @@ class Factory // here may interfere with UI rendering. If we ignore it now, it will // still get handled appropriately later in processing. error_log($e->getMessage()); - $catalog = null; // avoid unset variable notice } // Load remaining dependencies: $userTable = $sm->get('VuFind\DbTablePluginManager')->get('user'); $sessionManager = $sm->get('VuFind\SessionManager'); $pm = $sm->get('VuFind\AuthPluginManager'); + $cookies = $sm->get('VuFind\CookieManager'); // Build the object: - return new Manager($config, $userTable, $sessionManager, $pm, $catalog); + return new Manager($config, $userTable, $sessionManager, $pm, $cookies); } /** diff --git a/module/VuFind/src/VuFind/Auth/Manager.php b/module/VuFind/src/VuFind/Auth/Manager.php index 8da987b076b..ac0e2cc6f1a 100644 --- a/module/VuFind/src/VuFind/Auth/Manager.php +++ b/module/VuFind/src/VuFind/Auth/Manager.php @@ -26,7 +26,8 @@ * @link http://www.vufind.org Main Page */ namespace VuFind\Auth; -use VuFind\Db\Row\User as UserRow, VuFind\Db\Table\User as UserTable, +use VuFind\Cookie\CookieManager, + VuFind\Db\Row\User as UserRow, VuFind\Db\Table\User as UserTable, VuFind\Exception\Auth as AuthException, Zend\Config\Config, Zend\Session\SessionManager; @@ -97,6 +98,13 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface */ protected $pluginManager; + /** + * Cookie Manager + * + * @var CookieManager + */ + protected $cookieManager; + /** * Cache for current logged in user object * @@ -111,15 +119,18 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface * @param UserTable $userTable User table gateway * @param SessionManager $sessionManager Session manager * @param PluginManager $pm Authentication plugin manager + * @param CookieManager $cookieManager Cookie manager */ public function __construct(Config $config, UserTable $userTable, - SessionManager $sessionManager, PluginManager $pm + SessionManager $sessionManager, PluginManager $pm, + CookieManager $cookieManager ) { // Store dependencies: $this->config = $config; $this->userTable = $userTable; $this->sessionManager = $sessionManager; $this->pluginManager = $pm; + $this->cookieManager = $cookieManager; // Set up session: $this->session = new \Zend\Session\Container('Account'); @@ -348,7 +359,7 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface // Clear out the cached user object and session entry. $this->currentUser = false; unset($this->session->userId); - setcookie('loggedOut', 1, null, '/'); + $this->cookieManager->set('loggedOut', 1); // Destroy the session for good measure, if requested. if ($destroy) { @@ -370,7 +381,7 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface */ public function userHasLoggedOut() { - return isset($_COOKIE['loggedOut']) && $_COOKIE['loggedOut']; + return (bool)$this->cookieManager->get('loggedOut'); } /** @@ -426,7 +437,7 @@ class Manager implements \ZfcRbac\Identity\IdentityProviderInterface { $this->currentUser = $user; $this->session->userId = $user->id; - setcookie('loggedOut', '', time() - 3600, '/'); // clear logged out cookie + $this->cookieManager->clear('loggedOut'); } /** diff --git a/module/VuFind/src/VuFind/Bootstrapper.php b/module/VuFind/src/VuFind/Bootstrapper.php index b352f21ffb6..8f31b5d13f6 100644 --- a/module/VuFind/src/VuFind/Bootstrapper.php +++ b/module/VuFind/src/VuFind/Bootstrapper.php @@ -308,10 +308,12 @@ class Bootstrapper // Setup Translator $request = $event->getRequest(); + $sm = $event->getApplication()->getServiceManager(); if (($language = $request->getPost()->get('mylang', false)) || ($language = $request->getQuery()->get('lng', false)) ) { - setcookie('language', $language, null, '/'); + $cookieManager = $sm->get('VuFind\CookieManager'); + $cookieManager->set('language', $language); } elseif (!empty($request->getCookie()->language)) { $language = $request->getCookie()->language; } else { @@ -324,7 +326,6 @@ class Bootstrapper $language = $config->Site->language; } - $sm = $event->getApplication()->getServiceManager(); try { $sm->get('VuFind\Translator') ->addTranslationFile('ExtendedIni', null, 'default', $language) diff --git a/module/VuFind/src/VuFind/Cart.php b/module/VuFind/src/VuFind/Cart.php index 3385de5a128..2e6b8d2195c 100644 --- a/module/VuFind/src/VuFind/Cart.php +++ b/module/VuFind/src/VuFind/Cart.php @@ -26,6 +26,7 @@ * @link http://vufind.org/wiki/vufind2:developer_manual Wiki */ namespace VuFind; +use VuFind\Cookie\CookieManager; /** * Cart Class @@ -69,11 +70,11 @@ class Cart protected $recordLoader; /** - * Domain context for cookies (null for default) + * Cookie manager * - * @var string + * @var CookieManager */ - protected $cookieDomain; + protected $cookieManager; const CART_COOKIE = 'vufind_cart'; const CART_COOKIE_SOURCES = 'vufind_cart_src'; @@ -82,24 +83,22 @@ class Cart /** * Constructor * - * @param \VuFind\Record\Loader $loader Object for loading records - * @param int $maxSize Maximum size of cart contents - * @param bool $active Is cart enabled? - * @param array $cookies Current cookie values (leave null - * to use $_COOKIE superglobal) - * @param string $cookieDomain Domain context for cookies - * (optional) + * @param \VuFind\Record\Loader $loader Object for loading records + * @param CookieManager $cookieManager Cookie manager + * @param int $maxSize Maximum size of cart contents + * @param bool $active Is cart enabled? */ public function __construct(\VuFind\Record\Loader $loader, - $maxSize = 100, $active = true, $cookies = null, $cookieDomain = null + \VuFind\Cookie\CookieManager $cookieManager, + $maxSize = 100, $active = true ) { $this->recordLoader = $loader; + $this->cookieManager = $cookieManager; $this->maxSize = $maxSize; $this->active = $active; - $this->cookieDomain = $cookieDomain; // Initialize contents - $this->init(null === $cookies ? $_COOKIE : $cookies); + $this->init($this->cookieManager->getCookies()); } /** @@ -292,24 +291,9 @@ class Cart // Save the cookies: $cookie = implode(self::CART_COOKIE_DELIM, $ids); - $this->setCookie(self::CART_COOKIE, $cookie, 0, '/', $this->cookieDomain); - $cookie = implode(self::CART_COOKIE_DELIM, $sources); - $this->setCookie( - self::CART_COOKIE_SOURCES, $cookie, 0, '/', $this->cookieDomain - ); - } - - /** - * Set a cookie (wrapper in case Zend Framework offers a better abstraction - * of cookie handling in the future). - * - * @return bool - */ - protected function setCookie() - { - // @codeCoverageIgnoreStart - return call_user_func_array('setcookie', func_get_args()); - // @codeCoverageIgnoreEnd + $this->cookieManager->set(self::CART_COOKIE, $cookie, 0); + $srcCookie = implode(self::CART_COOKIE_DELIM, $sources); + $this->cookieManager->set(self::CART_COOKIE_SOURCES, $srcCookie, 0); } /** @@ -319,7 +303,7 @@ class Cart */ public function getCookieDomain() { - return $this->cookieDomain; + return $this->cookieManager->getDomain(); } /** diff --git a/module/VuFind/src/VuFind/Controller/Factory.php b/module/VuFind/src/VuFind/Controller/Factory.php index 79163b4087d..ba2f465c499 100644 --- a/module/VuFind/src/VuFind/Controller/Factory.php +++ b/module/VuFind/src/VuFind/Controller/Factory.php @@ -96,4 +96,18 @@ class Factory $sm->getServiceLocator()->get('VuFind\Config')->get('config') ); } + + /** + * Construct the UpgradeController. + * + * @param ServiceManager $sm Service manager. + * + * @return UpgradeController + */ + public static function getUpgradeController(ServiceManager $sm) + { + return new UpgradeController( + $sm->getServiceLocator()->get('VuFind\CookieManager') + ); + } } \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Controller/UpgradeController.php b/module/VuFind/src/VuFind/Controller/UpgradeController.php index 26117f86fae..86cab730e63 100644 --- a/module/VuFind/src/VuFind/Controller/UpgradeController.php +++ b/module/VuFind/src/VuFind/Controller/UpgradeController.php @@ -66,14 +66,16 @@ class UpgradeController extends AbstractBase /** * Constructor + * + * @param \VuFind\Cookie\CookieManager $cookieManager Cookie manager */ - public function __construct() + public function __construct(\VuFind\Cookie\CookieManager $cookieManager) { // We want to use cookies for tracking the state of the upgrade, since the // session is unreliable -- if the user upgrades a configuration that uses // a different session handler than the default one, we'll lose track of our // upgrade state in the middle of the process! - $this->cookie = new CookieContainer('vfup'); + $this->cookie = new CookieContainer('vfup', $cookieManager); // ...however, once the configuration piece of the upgrade is done, we can // safely use the session for storing some values. We'll use this for the diff --git a/module/VuFind/src/VuFind/Cookie/Container.php b/module/VuFind/src/VuFind/Cookie/Container.php index b1778220063..5f6601af9bf 100644 --- a/module/VuFind/src/VuFind/Cookie/Container.php +++ b/module/VuFind/src/VuFind/Cookie/Container.php @@ -47,14 +47,24 @@ class Container */ protected $groupName; + /** + * Cookie manager. + * + * @var CookieManager + */ + protected $manager; + /** * Constructor * - * @param string $groupName Prefix to use for cookie values. + * @param string $groupName Prefix to use for cookie values. + * @param CookieManager $manager Cookie manager. */ - public function __construct($groupName) + public function __construct($groupName, CookieManager $manager = null) { $this->groupName = $groupName; + $this->manager = (null === $manager) + ? new CookieManager($_COOKIE) : $manager; } /** @@ -65,7 +75,7 @@ class Container public function getAllValues() { $retVal = []; - foreach ($_COOKIE as $key => $value) { + foreach ($this->manager->getCookies() as $key => $value) { if (substr($key, 0, strlen($this->groupName)) == $this->groupName) { $retVal[substr($key, strlen($this->groupName))] = $value; } @@ -83,7 +93,8 @@ class Container */ public function & __get($var) { - return $_COOKIE[$this->groupName . $var]; + $val = $this->manager->get($this->groupName . $var); + return $val; } /** @@ -97,18 +108,7 @@ class Container */ public function __set($var, $value) { - $_COOKIE[$this->groupName . $var] = $value; - if (is_array($value)) { - $i = 0; - foreach ($value as $curr) { - setcookie( - $this->groupName . $var . '[' . $i . ']', $curr, null, '/' - ); - $i++; - } - } else { - setcookie($this->groupName . $var, $value, null, '/'); - } + $this->manager->set($this->groupName . $var, $value); } /** @@ -121,7 +121,7 @@ class Container */ public function __isset($var) { - return isset($_COOKIE[$this->groupName . $var]); + return null !== $this->manager->get($this->groupName . $var); } /** @@ -134,19 +134,6 @@ class Container */ public function __unset($var) { - $isArray = is_array($_COOKIE[$this->groupName . $var]); - if ($isArray) { - $count = count($_COOKIE[$this->groupName . $var]); - } - unset($_COOKIE[$this->groupName . $var]); - if ($isArray) { - for ($i = 0; $i < $count; $i++) { - setcookie( - $this->groupName . $var . '[' . $i . ']', '', time() - 3600, '/' - ); - } - } else { - setcookie($this->groupName . $var, '', time() - 3600, '/'); - } + $this->manager->clear($this->groupName . $var); } } \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Cookie/CookieManager.php b/module/VuFind/src/VuFind/Cookie/CookieManager.php new file mode 100644 index 00000000000..20a5af45e9b --- /dev/null +++ b/module/VuFind/src/VuFind/Cookie/CookieManager.php @@ -0,0 +1,185 @@ +<?php +/** + * Cookie Manager + * + * PHP version 5 + * + * Copyright (C) Villanova University 2015. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind2 + * @package Cookie + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/vufind2:developer_manual Wiki + */ +namespace VuFind\Cookie; + +/** + * Cookie Manager + * + * @category VuFind2 + * @package Cookie + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/vufind2:developer_manual Wiki + */ +class CookieManager +{ + /** + * Cookie base path + * + * @var string + */ + protected $path; + + /** + * Cookie domain + * + * @var string + */ + protected $domain; + + /** + * Are cookies secure only? + * + * @var bool + */ + protected $secure; + + /** + * Constructor + * + * @param array $cookies Cookie array to manipulate (e.g. $_COOKIE) + * @param string $path Cookie base path (default = /) + * @param string $domain Cookie domain + * @param bool $secure Are cookies secure only? (default = false) + */ + public function __construct($cookies, $path = '/', $domain = null, + $secure = false + ) { + $this->cookies = $cookies; + $this->path = $path; + $this->domain = $domain; + $this->secure = $secure; + } + + /** + * Get all cookie values. + * + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * Get the cookie domain. + * + * @return string + */ + public function getDomain() + { + return $this->domain; + } + + /** + * Get the cookie path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Are cookies set to "secure only" mode? + * + * @return bool + */ + public function isSecure() + { + return $this->secure; + } + + /** + * Set a cookie. + * + * @param string $key Name of cookie to set + * @param mixed $value Value to set + * @param int $expire Cookie expiration time + * + * @return bool + */ + public function set($key, $value, $expire = 0) + { + if (is_array($value)) { + $success = true; + foreach ($value as $i => $curr) { + $lastSuccess = setcookie( + $key . '[' . $i . ']', $curr, $expire, + $this->path, $this->domain, $this->secure + ); + if (!$lastSuccess) { + $success = false; + } + } + } else { + $success = setcookie( + $key, $value, $expire, $this->path, $this->domain, $this->secure + ); + } + if ($success) { + $this->cookies[$key] = $value; + } + return $success; + } + + /** + * Clear a cookie. + * + * @param string $key Name of cookie to unset + * + * @return bool + */ + public function clear($key) + { + $value = $this->get($key); + if (is_array($value)) { + $success = true; + foreach (array_keys($value) as $i) { + if (!$this->clear($key . '[' . $i . ']')) { + $success = false; + } + } + return $success; + } + return $this->set($key, null, time() - 3600); + } + + /** + * Retrieve a cookie value (or null if unset). + * + * @param string $key Name of cookie to retrieve + * + * @return mixed + */ + public function get($key) + { + return isset($this->cookies[$key]) ? $this->cookies[$key] : null; + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Service/Factory.php b/module/VuFind/src/VuFind/Service/Factory.php index 8cf7fd106c4..bcecfa33eee 100644 --- a/module/VuFind/src/VuFind/Service/Factory.php +++ b/module/VuFind/src/VuFind/Service/Factory.php @@ -94,10 +94,9 @@ class Factory ? (bool)$config->Site->showBookBag : false; $size = isset($config->Site->bookBagMaxSize) ? $config->Site->bookBagMaxSize : 100; - $domain = isset($config->Site->bookBagCookieDomain) - ? $config->Site->bookBagCookieDomain : null; return new \VuFind\Cart( - $sm->get('VuFind\RecordLoader'), $size, $active, $_COOKIE, $domain + $sm->get('VuFind\RecordLoader'), $sm->get('VuFind\CookieManager'), + $size, $active ); } @@ -176,6 +175,31 @@ class Factory return static::getGenericPluginManager($sm, 'Content\Reviews'); } + /** + * Construct the cookie manager. + * + * @param ServiceManager $sm Service manager. + * + * @return \VuFind\Cookie\CookieManager + */ + public static function getCookieManager(ServiceManager $sm) + { + $config = $sm->get('VuFind\Config')->get('config'); + $path = '/'; + if (isset($config->Cookies->limit_by_path) + && $config->Cookies->limit_by_path + ) { + $path = $sm->get('Request')->getBasePath(); + } + $secure = isset($config->Cookies->only_secure) + ? $config->Cookies->only_secure + : false; + $domain = isset($config->Cookies->domain) + ? $config->Cookies->domain + : null; + return new \VuFind\Cookie\CookieManager($_COOKIE, $path, $domain, $secure); + } + /** * Construct the date converter. * @@ -665,6 +689,31 @@ class Factory ); } + /** + * Construct the Session Manager. + * + * @param ServiceManager $sm Service manager. + * + * @return \Zend\Session\SessionManager + */ + public static function getSessionManager(ServiceManager $sm) + { + $cookieManager = $sm->get('VuFind\CookieManager'); + $sessionConfig = new \Zend\Session\Config\SessionConfig(); + $options = [ + 'cookie_path' => $cookieManager->getPath(), + 'cookie_secure' => $cookieManager->isSecure() + ]; + $domain = $cookieManager->getDomain(); + if (!empty($domain)) { + $options['cookie_domain'] = $domain; + } + + $sessionConfig->setOptions($options); + + return new \Zend\Session\SessionManager($sessionConfig); + } + /** * Construct the Session Plugin Manager. * diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/ManagerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/ManagerTest.php index 673d69f64ea..269c956f356 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/ManagerTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/ManagerTest.php @@ -461,7 +461,8 @@ class ManagerTest extends \VuFindTest\Unit\TestCase if (null === $pm) { $pm = $this->getMockPluginManager(); } - return new Manager($config, $userTable, $sessionManager, $pm); + $cookies = new \VuFind\Cookie\CookieManager([]); + return new Manager($config, $userTable, $sessionManager, $pm, $cookies); } /** diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php index f3c67576375..af1d0fab369 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php @@ -26,6 +26,7 @@ * @link http://vufind.org/wiki/vufind2:unit_tests Wiki */ namespace VuFindTest; +use VuFind\Cookie\CookieManager; /** * Cart Test Class @@ -62,23 +63,42 @@ class CartTest extends \PHPUnit_Framework_TestCase } /** - * Build a mock cart object. + * Build a mock cookie manager. * - * @param int $maxSize Maximum size of cart contents - * @param bool $active Is cart enabled? - * @param array $cookies Current cookie values + * @param array $cookies Current cookie values + * @param string $path Cookie base path (default = /) + * @param string $domain Cookie domain + * @param bool $secure Are cookies secure only? (default = false) * - * @return \VuFind\Cart + * @return CookieManager */ - protected function getCart($maxSize = 100, $active = true, $cookies = [], - $domain = null + protected function getMockCookieManager($cookies = [], $path = '/', + $domain = null, $secure = false ) { return $this->getMock( - 'VuFind\Cart', ['setCookie'], - [$this->loader, $maxSize, $active, $cookies, $domain] + 'VuFind\Cookie\CookieManager', ['set'], + [$cookies, $path, $domain, $secure] ); } + /** + * Build a mock cart object. + * + * @param int $maxSize Maximum size of cart contents + * @param bool $active Is cart enabled? + * @param array|CookieManager $cookies Current cookie values (or ready-to-use + * cookie manager) + * + * @return \VuFind\Cart + */ + protected function getCart($maxSize = 100, $active = true, $cookies = []) + { + if (!($cookies instanceof CookieManager)) { + $cookies = $this->getMockCookieManager($cookies); + } + return new \VuFind\Cart($this->loader, $cookies, $maxSize, $active); + } + /** * Test cookie domain setting. * @@ -86,7 +106,8 @@ class CartTest extends \PHPUnit_Framework_TestCase */ public function testCookieDomain() { - $cart = $this->getCart(100, true, [], '.example.com'); + $manager = $this->getMockCookieManager([], '/', '.example.com'); + $cart = $this->getCart(100, true, $manager); $this->assertEquals('.example.com', $cart->getCookieDomain()); } @@ -160,13 +181,14 @@ class CartTest extends \PHPUnit_Framework_TestCase */ public function testCookieWrite() { - $cart = $this->getCart(); - $cart->expects($this->at(0)) - ->method('setCookie') + $manager = $this->getMockCookieManager(); + $manager->expects($this->at(0)) + ->method('set') ->with($this->equalTo('vufind_cart'), $this->equalTo('Aa')); - $cart->expects($this->at(1)) - ->method('setCookie') + $manager->expects($this->at(1)) + ->method('set') ->with($this->equalTo('vufind_cart_src'), $this->equalTo('VuFind')); + $cart = $this->getCart(100, true, $manager); $cart->addItem('VuFind|a'); } diff --git a/module/VuFindTheme/src/VuFindTheme/Initializer.php b/module/VuFindTheme/src/VuFindTheme/Initializer.php index 4ddb7985c09..90683f04e59 100644 --- a/module/VuFindTheme/src/VuFindTheme/Initializer.php +++ b/module/VuFindTheme/src/VuFindTheme/Initializer.php @@ -76,6 +76,13 @@ class Initializer */ protected $mobile; + /** + * Cookie manager + * + * @var \VuFind\Cookie\CookieManager + */ + protected $cookieManager; + /** * Constructor * @@ -105,6 +112,9 @@ class Initializer // Grab the service manager for convenience: $this->serviceManager = $this->event->getApplication()->getServiceManager(); + // Get the cookie manager from the service manager: + $this->cookieManager = $this->serviceManager->get('VuFind\CookieManager'); + // Get base directory from tools object: $this->tools = $this->serviceManager->get('VuFindTheme\ThemeInfo'); @@ -220,8 +230,7 @@ class Initializer } // Save the current setting to a cookie so it persists: - $_COOKIE['ui'] = $selectedUI; - setcookie('ui', $selectedUI, null, '/'); + $this->cookieManager->set('ui', $selectedUI); // Do we have a valid mobile selection? if ($mobileTheme && $selectedUI == 'mobile') { @@ -283,7 +292,7 @@ class Initializer if (!empty($name)) { $options[] = [ 'name' => $name, 'desc' => $desc, - 'selected' => ($_COOKIE['ui'] == $name) + 'selected' => ($this->cookieManager->get('ui') == $name) ]; } } -- GitLab