Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | n/a |
0 / 0 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
|||
ManagerFactory | n/a |
0 / 0 |
n/a |
0 / 0 |
14 | n/a |
0 / 0 |
|||
getOptions | n/a |
0 / 0 |
n/a |
0 / 0 |
4 | |||||
getHandler | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
registerShutdownFunction | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
__invoke | n/a |
0 / 0 |
n/a |
0 / 0 |
6 |
1 | <?php |
2 | |
3 | /** |
4 | * Factory for instantiating Session Manager |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2016. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package Session_Handlers |
25 | * @author Demian Katz <demian.katz@villanova.edu> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org/wiki/development Wiki |
28 | */ |
29 | |
30 | namespace VuFind\Session; |
31 | |
32 | use Laminas\ServiceManager\Exception\ServiceNotCreatedException; |
33 | use Laminas\ServiceManager\Exception\ServiceNotFoundException; |
34 | use Laminas\ServiceManager\Factory\FactoryInterface; |
35 | use Laminas\Session\SessionManager; |
36 | use Psr\Container\ContainerExceptionInterface as ContainerException; |
37 | use Psr\Container\ContainerInterface; |
38 | |
39 | /** |
40 | * Factory for instantiating Session Manager |
41 | * |
42 | * @category VuFind |
43 | * @package Session_Handlers |
44 | * @author Demian Katz <demian.katz@villanova.edu> |
45 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
46 | * @link https://vufind.org/wiki/development Wiki |
47 | * |
48 | * @codeCoverageIgnore |
49 | */ |
50 | class ManagerFactory implements FactoryInterface |
51 | { |
52 | /** |
53 | * Build the options array. |
54 | * |
55 | * @param ContainerInterface $container Service manager |
56 | * |
57 | * @return array |
58 | */ |
59 | protected function getOptions(ContainerInterface $container) |
60 | { |
61 | $cookieManager = $container->get(\VuFind\Cookie\CookieManager::class); |
62 | // Set options only if we are not running from CLI |
63 | $options = 'cli' !== PHP_SAPI ? [ |
64 | 'cookie_httponly' => $cookieManager->isHttpOnly(), |
65 | 'cookie_path' => $cookieManager->getPath(), |
66 | 'cookie_secure' => $cookieManager->isSecure(), |
67 | 'cookie_samesite' => $cookieManager->getSameSite(), |
68 | ] : []; |
69 | |
70 | $domain = $cookieManager->getDomain(); |
71 | if (!empty($domain)) { |
72 | $options['cookie_domain'] = $domain; |
73 | } |
74 | |
75 | $name = $cookieManager->getSessionName(); |
76 | if (!empty($name)) { |
77 | $options['name'] = $name; |
78 | } |
79 | |
80 | return $options; |
81 | } |
82 | |
83 | /** |
84 | * Set up the session handler by retrieving all the pieces from the service |
85 | * manager and injecting appropriate dependencies. |
86 | * |
87 | * @param ContainerInterface $container Service manager |
88 | * |
89 | * @return array |
90 | */ |
91 | protected function getHandler(ContainerInterface $container) |
92 | { |
93 | // Load and validate session configuration: |
94 | $config = $container->get(\VuFind\Config\PluginManager::class) |
95 | ->get('config'); |
96 | if (!isset($config->Session->type)) { |
97 | throw new \Exception('Cannot initialize session; configuration missing'); |
98 | } |
99 | |
100 | return $container->get(\VuFind\Session\PluginManager::class) |
101 | ->get($config->Session->type); |
102 | } |
103 | |
104 | /** |
105 | * According to the PHP manual, session_write_close should always be |
106 | * registered as a shutdown function when using an object as a session |
107 | * handler: http://us.php.net/manual/en/function.session-set-save-handler.php |
108 | * |
109 | * This method sets that up. |
110 | * |
111 | * @param SessionManager $sessionManager Session manager instance |
112 | * |
113 | * @return void |
114 | */ |
115 | protected function registerShutdownFunction(SessionManager $sessionManager) |
116 | { |
117 | register_shutdown_function( |
118 | function () use ($sessionManager) { |
119 | // If storage is immutable, the session is already closed: |
120 | if (!$sessionManager->getStorage()->isImmutable()) { |
121 | $sessionManager->writeClose(); |
122 | } |
123 | } |
124 | ); |
125 | } |
126 | |
127 | /** |
128 | * Create an object |
129 | * |
130 | * @param ContainerInterface $container Service manager |
131 | * @param string $requestedName Service being created |
132 | * @param null|array $options Extra options (optional) |
133 | * |
134 | * @return object |
135 | * |
136 | * @throws ServiceNotFoundException if unable to resolve the service. |
137 | * @throws ServiceNotCreatedException if an exception is raised when |
138 | * creating a service. |
139 | * @throws ContainerException&\Throwable if any other error occurs |
140 | */ |
141 | public function __invoke( |
142 | ContainerInterface $container, |
143 | $requestedName, |
144 | array $options = null |
145 | ) { |
146 | if (!empty($options)) { |
147 | throw new \Exception('Unexpected options passed to factory.'); |
148 | } |
149 | |
150 | // Build configuration: |
151 | $sessionConfig = new \Laminas\Session\Config\SessionConfig(); |
152 | $sessionConfig->setOptions($this->getOptions($container)); |
153 | |
154 | // Build session manager and attach handler: |
155 | $sessionManager = new $requestedName($sessionConfig); |
156 | $sessionManager->setSaveHandler($this->getHandler($container)); |
157 | |
158 | // Start up the session: |
159 | $sessionManager->start(); |
160 | |
161 | // Verify that any existing session has the correct path to avoid using |
162 | // a cookie from a service higher up in the path hierarchy. |
163 | $storage = new \Laminas\Session\Container('SessionState', $sessionManager); |
164 | if (null !== $storage->cookiePath) { |
165 | if ($storage->cookiePath != $sessionConfig->getCookiePath()) { |
166 | // Disable writes temporarily to keep the existing session intact |
167 | $sessionManager->getSaveHandler()->disableWrites(); |
168 | // Regenerate session ID and reset the session data |
169 | $sessionManager->regenerateId(false); |
170 | session_unset(); |
171 | $sessionManager->getSaveHandler()->enableWrites(); |
172 | $storage->cookiePath = $sessionConfig->getCookiePath(); |
173 | } |
174 | } else { |
175 | $storage->cookiePath = $sessionConfig->getCookiePath(); |
176 | } |
177 | |
178 | // Set session start time: |
179 | if (empty($storage->sessionStartTime)) { |
180 | $storage->sessionStartTime = time(); |
181 | } |
182 | |
183 | // Check if we need to immediately stop it based on the settings object |
184 | // (which may have been informed by a controller that sessions should not |
185 | // be written as part of the current process): |
186 | $settings = $container->get(\VuFind\Session\Settings::class); |
187 | if ($settings->setSessionManager($sessionManager)->isWriteDisabled()) { |
188 | $sessionManager->getSaveHandler()->disableWrites(); |
189 | } else { |
190 | // If the session is not disabled, we should set up the normal |
191 | // shutdown function: |
192 | $this->registerShutdownFunction($sessionManager); |
193 | } |
194 | |
195 | return $sessionManager; |
196 | } |
197 | } |