PageRenderTime 14ms CodeModel.GetById 2ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/storage/session/adapter/Php.php

http://github.com/UnionOfRAD/lithium
PHP | 262 lines | 130 code | 19 blank | 113 comment | 24 complexity | f74ca060b9e0ea2877370300bf535257 MD5 | raw file
  1<?php
  2/**
  3 * li₃: the most RAD framework for PHP (http://li3.me)
  4 *
  5 * Copyright 2009, Union of RAD. All rights reserved. This source
  6 * code is distributed under the terms of the BSD 3-Clause License.
  7 * The full license text can be found in the LICENSE.txt file.
  8 */
  9
 10namespace lithium\storage\session\adapter;
 11
 12use lithium\util\Set;
 13use RuntimeException;
 14use lithium\core\ConfigException;
 15use lithium\core\Libraries;
 16
 17/**
 18 * A minimal adapter to interface with native PHP sessions.
 19 *
 20 * This adapter provides basic support for `write`, `read` and `delete`
 21 * session handling, as well as allowing these three methods to be filtered as
 22 * per the Lithium filtering system.
 23 */
 24class Php extends \lithium\core\ObjectDeprecated {
 25
 26	/**
 27	 * Default ini settings for this session adapter. Will disabl cookie lifetime,
 28	 * set cookies to HTTP only and the cache_limiter to `'nocache'`.
 29	 *
 30	 * @link http://php.net/session.configuration.php
 31	 * @link http://php.net/session.configuration.php#ini.session.cookie-lifetime
 32	 * @link http://php.net/session.configuration.php#ini.session.cookie-httponly
 33	 * @link http://php.net/session.configuration.php#ini.session.cache-limiter
 34	 * @var array Configuration options matching the pattern `'session.*'` are session
 35	 *      ini settings. Please consult the PHP documentation for further information.
 36	 */
 37	protected $_defaults = [
 38		'session.cookie_lifetime' => '0',
 39		'session.cookie_httponly' => true,
 40		'session.cache_limiter' => 'nocache'
 41	];
 42
 43	/**
 44	 * Constructor. Takes care of setting appropriate configurations for this object. Also sets
 45	 * session ini settings.
 46	 *
 47	 * @see lithium\storage\session\adapter\Php::$_defaults
 48	 * @param array $config Configuration options matching the pattern `'session.*'` are interpreted
 49	 *              as session ini settings. Please consult the PHP documentation for further
 50	 *              information.
 51	 *              A few ini settings are set by default here and will overwrite those from
 52	 *              your php.ini. To disable sending a cache limiter set `'session.cache_limiter'`
 53	 *              to `false`.
 54	 * @return void
 55	 */
 56	public function __construct(array $config = []) {
 57		if (empty($config['session.name'])) {
 58			$config['session.name'] = basename(Libraries::get(true, 'path'));
 59		}
 60		parent::__construct($config + $this->_defaults);
 61	}
 62
 63	/**
 64	 * Initialization of the session.
 65	 *
 66	 * @todo Split up into an _initialize() and a _start().
 67	 */
 68	protected function _init() {
 69		if ($this->isStarted()) {
 70			return true;
 71		}
 72		$config = $this->_config;
 73		unset($config['adapter'], $config['strategies'], $config['filters'], $config['init']);
 74
 75		foreach ($config as $key => $value) {
 76			if (strpos($key, 'session.') === false) {
 77				continue;
 78			}
 79			if (ini_set($key, $value) === false) {
 80				throw new ConfigException('Could not initialize the session.');
 81			}
 82		}
 83	}
 84
 85	/**
 86	 * Starts the session.
 87	 *
 88	 * @return boolean `true` if session successfully started
 89	 *         (or has already been started), `false` otherwise.
 90	 */
 91	protected function _start() {
 92		if ($this->isStarted()) {
 93			return true;
 94		}
 95		session_cache_limiter();
 96		return session_start();
 97	}
 98
 99	/**
100	 * Obtain the status of the session.
101	 *
102	 * @return boolean True if a session is currently started, False otherwise. If PHP 5.4
103	 *                 then we know, if PHP 5.3 then we cannot tell for sure if a session
104	 *                 has been closed.
105	 */
106	public function isStarted() {
107		if (function_exists('session_status')) {
108			return session_status() === PHP_SESSION_ACTIVE;
109		}
110		return isset($_SESSION) && session_id();
111	}
112
113	/**
114	 * Sets or obtains the session ID.
115	 *
116	 * @param string $key Optional. If specified, sets the session ID to the value of `$key`.
117	 * @return mixed Session ID, or `null` if the session has not been started.
118	 */
119	public function key($key = null) {
120		if ($key !== null) {
121			return session_id($key);
122		}
123		return session_id() ?: null;
124	}
125
126	/**
127	 * Checks if a value has been set in the session.
128	 *
129	 * @param string $key Key of the entry to be checked.
130	 * @param array $options Options array. Not used for this adapter method.
131	 * @return \Closure Function returning boolean `true` if the key exists, `false` otherwise.
132	 */
133	public function check($key, array $options = []) {
134		if (!$this->isStarted() && !$this->_start()) {
135			throw new RuntimeException('Could not start session.');
136		}
137		return function($params) {
138			return Set::check($_SESSION, $params['key']);
139		};
140	}
141
142	/**
143	 * Read a value from the session.
144	 *
145	 * @param null|string $key Key of the entry to be read. If no key is passed, all
146	 *        current session data is returned.
147	 * @param array $options Options array. Not used for this adapter method.
148	 * @return \Closure Function returning data in the session if successful, `false` otherwise.
149	 */
150	public function read($key = null, array $options = []) {
151		if (!$this->isStarted() && !$this->_start()) {
152			throw new RuntimeException('Could not start session.');
153		}
154		return function($params) {
155			$key = $params['key'];
156
157			if (!$key) {
158				return $_SESSION;
159			}
160			if (strpos($key, '.') === false) {
161				return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
162			}
163			$filter  = function($keys, $data) use (&$filter) {
164				$key = array_shift($keys);
165				if (isset($data[$key])) {
166					return (empty($keys)) ? $data[$key] : $filter($keys, $data[$key]);
167				}
168			};
169			return $filter(explode('.', $key), $_SESSION);
170		};
171	}
172
173	/**
174	 * Write a value to the session.
175	 *
176	 * @param string $key Key of the item to be stored.
177	 * @param mixed $value The value to be stored.
178	 * @param array $options Options array. Not used for this adapter method.
179	 * @return \Closure Function returning boolean `true` on successful write, `false` otherwise.
180	 */
181	public function write($key, $value, array $options = []) {
182		if (!$this->isStarted() && !$this->_start()) {
183			throw new RuntimeException('Could not start session.');
184		}
185		return function($params) {
186			return $this->overwrite(
187				$_SESSION, Set::insert($_SESSION, $params['key'], $params['value'])
188			);
189		};
190	}
191
192	/**
193	 * Delete value from the session
194	 *
195	 * @param string $key The key to be deleted.
196	 * @param array $options Options array. Not used for this adapter method.
197	 * @return \Closure Function returning boolean `true` if the key no longer
198	 *         exists in the session, `false` otherwise
199	 */
200	public function delete($key, array $options = []) {
201		if (!$this->isStarted() && !$this->_start()) {
202			throw new RuntimeException('Could not start session.');
203		}
204		return function($params) {
205			$key = $params['key'];
206			$this->overwrite($_SESSION, Set::remove($_SESSION, $key));
207			return !Set::check($_SESSION, $key);
208		};
209	}
210
211	/**
212	 * Clears all keys from the session.
213	 *
214	 * @param array $options Options array. Not used for this adapter method.
215	 * @return \Closure Function returning boolean `true` on successful clear, `false` otherwise.
216	 */
217	public function clear(array $options = []) {
218		if (!$this->isStarted() && !$this->_start()) {
219			throw new RuntimeException('Could not start session.');
220		}
221		return function($params) {
222			return session_destroy();
223		};
224	}
225
226	/**
227	 * Determines if PHP sessions are enabled.
228	 *
229	 * @return boolean Returns `true` if enabled (PHP session functionality
230	 *         can be disabled completely), `false` otherwise.
231	 */
232	public static function enabled() {
233		if (function_exists('session_status')) {
234			return session_status() !== PHP_SESSION_DISABLED;
235		}
236		return in_array('session', get_loaded_extensions());
237	}
238
239	/**
240	 * Overwrites session keys and values.
241	 *
242	 * @param array $old Reference to the array that needs to be
243	 *              overwritten. Will usually be `$_SESSION`.
244	 * @param array $new The data that should overwrite the keys/values in `$old`.
245	 * @return boolean Always `true`.
246	 */
247	public function overwrite(&$old, $new) {
248		if (!empty($old)) {
249			foreach ($old as $key => $value) {
250				if (!isset($new[$key])) {
251					unset($old[$key]);
252				}
253			}
254		}
255		foreach ($new as $key => $value) {
256			$old[$key] = $value;
257		}
258		return true;
259	}
260}
261
262?>