Source of file Session.php
Size: 9,474 Bytes - Last Modified: 2017-11-08T13:54:24+00:00
/home/travis/build/bluzphp/framework/src/Session/Session.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 | <?php /** * Bluz Framework Component * * @copyright Bluz PHP Team * @link https://github.com/bluzphp/framework */ declare(strict_types=1); namespace Bluz\Session; use Bluz\Common\Exception\ComponentException; use Bluz\Common\Options; /** * Session * * @package Bluz\Session * @author Anton Shevchuk * @link https://github.com/bluzphp/framework/wiki/Session */ class Session { use Options; /** * @var string value returned by session_name() */ protected $name; /** * @var string namespace */ protected $namespace = 'bluz'; /** * @var \SessionHandlerInterface Session save handler */ protected $adapter; /** * Attempt to set the session name * * If the session has already been started, or if the name provided fails * validation, an exception will be raised. * * @param string $name * * @throws SessionException * @return Session */ public function setName($name) { if ($this->sessionExists()) { throw new SessionException( 'Cannot set session name after a session has already started' ); } if (!preg_match('/^[a-zA-Z0-9]+$/', $name)) { throw new SessionException( 'Name provided contains invalid characters; must be alphanumeric only' ); } $this->name = $name; session_name($name); return $this; } /** * Get session name * * Proxies to {@link session_name()}. * * @return string */ public function getName() { if (null === $this->name) { // If we're grabbing via session_name(), we don't need our // validation routine; additionally, calling setName() after // session_start() can lead to issues, and often we just need the name // in order to do things such as setting cookies. $this->name = session_name(); } return $this->name; } /** * Set Namespace * * @param string $namespace * * @return Session */ public function setNamespace($namespace) { $this->namespace = $namespace; return $this; } /** * Get Namespace * * @return string */ public function getNamespace() { return $this->namespace; } /** * Set session ID * * Can safely be called in the middle of a session. * * @param string $id * * @return Session * @throws SessionException */ public function setId($id) { if ($this->sessionExists()) { throw new SessionException( 'Session has already been started, to change the session ID call regenerateId()' ); } session_id($id); return $this; } /** * Get session ID * * Proxies to {@link session_id()} * * @return string */ public function getId() { return session_id(); } /** * Regenerate id * * Regenerate the session ID, using session save handler's * native ID generation Can safely be called in the middle of a session. * * @param bool $deleteOldSession * * @return bool */ public function regenerateId($deleteOldSession = true) { if ($this->sessionExists()) { if (session_id() !== '') { return session_regenerate_id((bool)$deleteOldSession); } } return false; } /** * Returns true if session ID is set * * @return bool */ public function cookieExists() { return isset($_COOKIE[session_name()]); } /** * Does a session started and is it currently active? * * @return bool */ public function sessionExists() { return session_status() === PHP_SESSION_ACTIVE; } /** * Start session * * if No session currently exists, attempt to start it. Calls * {@link isValid()} once session_start() is called, and raises an * exception if validation fails. * * @return bool * @throws \Bluz\Common\Exception\ComponentException * @throws SessionException */ public function start() { if ($this->sessionExists()) { return true; } if ($this->initAdapter()) { return session_start(); } throw new ComponentException('Invalid adapter settings'); } /** * Destroy/end a session * * @return void */ public function destroy() { if (!$this->cookieExists() || !$this->sessionExists()) { return; } session_destroy(); // send expire cookies $this->expireSessionCookie(); // clear session data unset($_SESSION[$this->getNamespace()]); } /** * Set session save handler object * * @param \SessionHandlerInterface $saveHandler * * @return Session */ public function setAdapter($saveHandler) { $this->adapter = $saveHandler; return $this; } /** * Get SaveHandler Object * * @return \SessionHandlerInterface */ public function getAdapter() { return $this->adapter; } /** * Register Save Handler with ext/session * * Since ext/session is coupled to this particular session manager * register the save handler with ext/session. * * @return bool * @throws ComponentException */ protected function initAdapter() { if (null === $this->adapter || 'files' === $this->adapter) { // try to apply settings if ($settings = $this->getOption('settings', 'files')) { $this->setSavePath($settings['save_path']); } return true; } if (is_string($this->adapter)) { $adapterClass = '\\Bluz\\Session\\Adapter\\' . ucfirst($this->adapter); if (!class_exists($adapterClass) || !is_subclass_of($adapterClass, '\SessionHandlerInterface')) { throw new ComponentException("Class for session adapter `{$this->adapter}` not found"); } $settings = $this->getOption('settings', $this->adapter) ?: []; $this->adapter = new $adapterClass($settings); return session_set_save_handler($this->adapter); } return true; } /** * Set the session cookie lifetime * * If a session already exists, destroys it (without sending an expiration * cookie), regenerates the session ID, and restarts the session. * * @param integer $ttl TTL in seconds * * @return void */ public function setSessionCookieLifetime($ttl) { // Set new cookie TTL session_set_cookie_params($ttl); if ($this->sessionExists()) { // There is a running session so we'll regenerate id to send a new cookie $this->regenerateId(); } } /** * Expire the session cookie * * Sends a session cookie with no value, and with an expiry in the past. * * @return void */ public function expireSessionCookie() { if (ini_get('session.use_cookies')) { $params = session_get_cookie_params(); setcookie( $this->getName(), '', $_SERVER['REQUEST_TIME'] - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly'] ); } } /** * Set session save path * * @param string $savePath * * @return Session * @throws ComponentException */ protected function setSavePath($savePath) { if (!is_dir($savePath) || !is_writable($savePath) ) { throw new ComponentException('Session path is not writable'); } session_save_path($savePath); return $this; } /** * Set key/value pair * * @param string $key * @param mixed $value * * @return void */ public function set($key, $value) { $this->start(); // check storage if (!isset($_SESSION[$this->getNamespace()])) { $_SESSION[$this->getNamespace()] = []; } $_SESSION[$this->namespace][$key] = $value; } /** * Get value by key * * @param string $key * * @return mixed */ public function get($key) { if ($this->contains($key)) { return $_SESSION[$this->namespace][$key]; } return null; } /** * Isset * * @param string $key * * @return bool */ public function contains($key) { if ($this->cookieExists()) { $this->start(); } elseif (!$this->sessionExists()) { return false; } return isset($_SESSION[$this->namespace][$key]); } /** * Unset * * @param string $key * * @return void */ public function delete($key) { if ($this->contains($key)) { unset($_SESSION[$this->namespace][$key]); } } } |