Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Session / SessionManager.php
blob863f3f1347d7072649fd54ad9157df1ea613152f
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Session;
12 use Zend\EventManager\EventManagerInterface;
14 /**
15 * Session ManagerInterface implementation utilizing ext/session
17 class SessionManager extends AbstractManager
19 /**
20 * Default options when a call to {@link destroy()} is made
21 * - send_expire_cookie: whether or not to send a cookie expiring the current session cookie
22 * - clear_storage: whether or not to empty the storage object of any stored values
23 * @var array
25 protected $defaultDestroyOptions = array(
26 'send_expire_cookie' => true,
27 'clear_storage' => false,
30 /**
31 * @var string value returned by session_name()
33 protected $name;
35 /**
36 * @var EventManagerInterface Validation chain to determine if session is valid
38 protected $validatorChain;
40 /**
41 * Constructor
43 * @param Config\ConfigInterface|null $config
44 * @param Storage\StorageInterface|null $storage
45 * @param SaveHandler\SaveHandlerInterface|null $saveHandler
46 * @throws Exception\RuntimeException
48 public function __construct(Config\ConfigInterface $config = null, Storage\StorageInterface $storage = null, SaveHandler\SaveHandlerInterface $saveHandler = null)
50 parent::__construct($config, $storage, $saveHandler);
51 register_shutdown_function(array($this, 'writeClose'));
54 /**
55 * Does a session exist and is it currently active?
57 * @return bool
59 public function sessionExists()
61 $sid = defined('SID') ? constant('SID') : false;
62 if ($sid !== false && $this->getId()) {
63 return true;
65 if (headers_sent()) {
66 return true;
68 return false;
71 /**
72 * Start session
74 * if No session currently exists, attempt to start it. Calls
75 * {@link isValid()} once session_start() is called, and raises an
76 * exception if validation fails.
78 * @param bool $preserveStorage If set to true, current session storage will not be overwritten by the
79 * contents of $_SESSION.
80 * @return void
81 * @throws Exception\RuntimeException
83 public function start($preserveStorage = false)
85 if ($this->sessionExists()) {
86 return;
89 $saveHandler = $this->getSaveHandler();
90 if ($saveHandler instanceof SaveHandler\SaveHandlerInterface) {
91 // register the session handler with ext/session
92 $this->registerSaveHandler($saveHandler);
95 session_start();
97 $storage = $this->getStorage();
99 // Since session is starting, we need to potentially repopulate our
100 // session storage
101 if ($storage instanceof Storage\SessionStorage && $_SESSION !== $storage) {
102 if (!$preserveStorage) {
103 $storage->fromArray($_SESSION);
105 $_SESSION = $storage;
106 } elseif ($storage instanceof Storage\StorageInitializationInterface) {
107 $storage->init($_SESSION);
110 if (!$this->isValid()) {
111 throw new Exception\RuntimeException('Session validation failed');
116 * Destroy/end a session
118 * @param array $options See {@link $defaultDestroyOptions}
119 * @return void
121 public function destroy(array $options = null)
123 if (!$this->sessionExists()) {
124 return;
127 if (null === $options) {
128 $options = $this->defaultDestroyOptions;
129 } else {
130 $options = array_merge($this->defaultDestroyOptions, $options);
133 session_destroy();
134 if ($options['send_expire_cookie']) {
135 $this->expireSessionCookie();
138 if ($options['clear_storage']) {
139 $this->getStorage()->clear();
144 * Write session to save handler and close
146 * Once done, the Storage object will be marked as isImmutable.
148 * @return void
150 public function writeClose()
152 // The assumption is that we're using PHP's ext/session.
153 // session_write_close() will actually overwrite $_SESSION with an
154 // empty array on completion -- which leads to a mismatch between what
155 // is in the storage object and $_SESSION. To get around this, we
156 // temporarily reset $_SESSION to an array, and then re-link it to
157 // the storage object.
159 // Additionally, while you _can_ write to $_SESSION following a
160 // session_write_close() operation, no changes made to it will be
161 // flushed to the session handler. As such, we now mark the storage
162 // object isImmutable.
163 $storage = $this->getStorage();
164 if (!$storage->isImmutable()) {
165 $_SESSION = $storage->toArray(true);
166 session_write_close();
167 $storage->fromArray($_SESSION);
168 $storage->markImmutable();
173 * Attempt to set the session name
175 * If the session has already been started, or if the name provided fails
176 * validation, an exception will be raised.
178 * @param string $name
179 * @return SessionManager
180 * @throws Exception\InvalidArgumentException
182 public function setName($name)
184 if ($this->sessionExists()) {
185 throw new Exception\InvalidArgumentException(
186 'Cannot set session name after a session has already started'
190 if (!preg_match('/^[a-zA-Z0-9]+$/', $name)) {
191 throw new Exception\InvalidArgumentException(
192 'Name provided contains invalid characters; must be alphanumeric only'
196 $this->name = $name;
197 session_name($name);
198 return $this;
202 * Get session name
204 * Proxies to {@link session_name()}.
206 * @return string
208 public function getName()
210 if (null === $this->name) {
211 // If we're grabbing via session_name(), we don't need our
212 // validation routine; additionally, calling setName() after
213 // session_start() can lead to issues, and often we just need the name
214 // in order to do things such as setting cookies.
215 $this->name = session_name();
217 return $this->name;
221 * Set session ID
223 * Can safely be called in the middle of a session.
225 * @param string $id
226 * @return SessionManager
228 public function setId($id)
230 if ($this->sessionExists()) {
231 throw new Exception\RuntimeException('Session has already been started, to change the session ID call regenerateId()');
233 session_id($id);
234 return $this;
238 * Get session ID
240 * Proxies to {@link session_id()}
242 * @return string
244 public function getId()
246 return session_id();
250 * Regenerate id
252 * Regenerate the session ID, using session save handler's
253 * native ID generation Can safely be called in the middle of a session.
255 * @param bool $deleteOldSession
256 * @return SessionManager
258 public function regenerateId($deleteOldSession = true)
260 session_regenerate_id((bool) $deleteOldSession);
261 return $this;
265 * Set the TTL (in seconds) for the session cookie expiry
267 * Can safely be called in the middle of a session.
269 * @param null|int $ttl
270 * @return SessionManager
272 public function rememberMe($ttl = null)
274 if (null === $ttl) {
275 $ttl = $this->getConfig()->getRememberMeSeconds();
277 $this->setSessionCookieLifetime($ttl);
278 return $this;
282 * Set a 0s TTL for the session cookie
284 * Can safely be called in the middle of a session.
286 * @return SessionManager
288 public function forgetMe()
290 $this->setSessionCookieLifetime(0);
291 return $this;
295 * Set the validator chain to use when validating a session
297 * In most cases, you should use an instance of {@link ValidatorChain}.
299 * @param EventManagerInterface $chain
300 * @return SessionManager
302 public function setValidatorChain(EventManagerInterface $chain)
304 $this->validatorChain = $chain;
305 return $this;
309 * Get the validator chain to use when validating a session
311 * By default, uses an instance of {@link ValidatorChain}.
313 * @return EventManagerInterface
315 public function getValidatorChain()
317 if (null === $this->validatorChain) {
318 $this->setValidatorChain(new ValidatorChain($this->getStorage()));
320 return $this->validatorChain;
324 * Is this session valid?
326 * Notifies the Validator Chain until either all validators have returned
327 * true or one has failed.
329 * @return bool
331 public function isValid()
333 $validator = $this->getValidatorChain();
334 $responses = $validator->triggerUntil('session.validate', $this, array($this), function ($test) {
335 return !$test;
337 if ($responses->stopped()) {
338 // If execution was halted, validation failed
339 return false;
341 // Otherwise, we're good to go
342 return true;
346 * Expire the session cookie
348 * Sends a session cookie with no value, and with an expiry in the past.
350 * @return void
352 public function expireSessionCookie()
354 $config = $this->getConfig();
355 if (!$config->getUseCookies()) {
356 return;
358 setcookie(
359 $this->getName(), // session name
360 '', // value
361 $_SERVER['REQUEST_TIME'] - 42000, // TTL for cookie
362 $config->getCookiePath(),
363 $config->getCookieDomain(),
364 $config->getCookieSecure(),
365 $config->getCookieHttpOnly()
370 * Set the session cookie lifetime
372 * If a session already exists, destroys it (without sending an expiration
373 * cookie), regenerates the session ID, and restarts the session.
375 * @param int $ttl
376 * @return void
378 protected function setSessionCookieLifetime($ttl)
380 $config = $this->getConfig();
381 if (!$config->getUseCookies()) {
382 return;
385 // Set new cookie TTL
386 $config->setCookieLifetime($ttl);
388 if ($this->sessionExists()) {
389 // There is a running session so we'll regenerate id to send a new cookie
390 $this->regenerateId();
395 * Register Save Handler with ext/session
397 * Since ext/session is coupled to this particular session manager
398 * register the save handler with ext/session.
400 * @param SaveHandler\SaveHandlerInterface $saveHandler
401 * @return bool
403 protected function registerSaveHandler(SaveHandler\SaveHandlerInterface $saveHandler)
405 return session_set_save_handler(
406 array($saveHandler, 'open'),
407 array($saveHandler, 'close'),
408 array($saveHandler, 'read'),
409 array($saveHandler, 'write'),
410 array($saveHandler, 'destroy'),
411 array($saveHandler, 'gc')