Session.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\storage;
  9. use lithium\core\Libraries;
  10. /**
  11. * The `Session` static class provides a consistent interface to configure and utilize the
  12. * different persistent storage adapters included with Lithium, as well as your own adapters.
  13. *
  14. * The Session layer of Lithium inherits from the common `Adaptable` class, which provides
  15. * the generic configuration setting & retrieval logic, as well as the logic required to
  16. * locate & instantiate the proper adapter class.
  17. *
  18. * In most cases, you will configure various named session configurations in your bootstrap
  19. * process, which will then be available to you in all other parts of your application.
  20. *
  21. * Each adapter provides a consistent interface for the basic session operations like `read`,
  22. * `write`, `delete` and `check`, which can be used interchangeably between all adapters.
  23. *
  24. * For more information on `Session` methods and specific adapters, please see their relevant
  25. * documentation.
  26. *
  27. * @see lithium\core\Adaptable
  28. * @see lithium\storage\session\adapter
  29. */
  30. class Session extends \lithium\core\Adaptable {
  31. /**
  32. * Stores configurations arrays for session adapters, keyed by configuration name.
  33. *
  34. * @var array
  35. */
  36. protected static $_configurations = array();
  37. /**
  38. * A dot-separated path for use by `Libraries::locate()`. Used to look up the correct type of
  39. * adapters for this class.
  40. *
  41. * @var string
  42. */
  43. protected static $_adapters = 'adapter.storage.session';
  44. /**
  45. * `Libraries::locate()` compatible path to strategies for this class.
  46. *
  47. * @var string
  48. */
  49. protected static $_strategies = 'strategy.storage.session';
  50. /**
  51. * Returns the key used to identify the session.
  52. *
  53. * @param mixed $name Optional named session configuration.
  54. * @return string Returns the value of the session identifier key, or `null` if no named
  55. * configuration exists, or no session has been started.
  56. */
  57. public static function key($name = null) {
  58. return is_object($adapter = static::adapter($name)) ? $adapter->key() : null;
  59. }
  60. /**
  61. * Indicates whether the the current request includes information on a previously started
  62. * session.
  63. *
  64. * @param string $name Optional named session configuration.
  65. * @return boolean Returns `true` if a the request includes a key from a previously created
  66. * session.
  67. */
  68. public static function isStarted($name = null) {
  69. return is_object($adapter = static::adapter($name)) ? $adapter->isStarted() : false;
  70. }
  71. /**
  72. * Reads a value from a persistent session store.
  73. *
  74. * @param string $key Key to be read.
  75. * @param array $options Optional parameters that this method accepts:
  76. * - `'name'` _string_: To force the read from a specific adapter, specify the name
  77. * of the configuration (i.e. `'default'`) here.
  78. * - `'strategies'` _boolean_: Indicates whether or not a configuration's applied
  79. * strategy classes should be enabled for this operation. Defaults to `true`.
  80. * @return mixed Read result on successful session read, `null` otherwise.
  81. * @filter This method may be filtered.
  82. */
  83. public static function read($key = null, array $options = array()) {
  84. $defaults = array('name' => null, 'strategies' => true);
  85. $options += $defaults;
  86. $method = ($name = $options['name']) ? static::adapter($name)->read($key, $options) : null;
  87. $settings = static::_config($name);
  88. if (!$method) {
  89. foreach (array_keys(static::$_configurations) as $name) {
  90. if ($method = static::adapter($name)->read($key, $options)) {
  91. break;
  92. }
  93. }
  94. if (!$method || !$name) {
  95. return null;
  96. }
  97. }
  98. $filters = $settings['filters'] ?: array();
  99. $result = static::_filter(__FUNCTION__, compact('key', 'options'), $method, $filters);
  100. if ($options['strategies']) {
  101. $options += array('key' => $key, 'mode' => 'LIFO', 'class' => __CLASS__);
  102. return static::applyStrategies(__FUNCTION__, $name, $result, $options);
  103. }
  104. return $result;
  105. }
  106. /**
  107. * Writes a persistent value to one or more session stores.
  108. *
  109. * @param string $key Key to be written.
  110. * @param mixed $value Data to be stored.
  111. * @param array $options Optional parameters that this method accepts:
  112. * - `'name'` _string_: To force the write to a specific adapter, specify the name
  113. * of the configuration (i.e. `'default'`) here.
  114. * - `'strategies'` _boolean_: Indicates whether or not a configuration's applied
  115. * strategy classes should be enabled for this operation. Defaults to `true`.
  116. * @return boolean Returns `true` on successful write, `false` otherwise.
  117. * @filter This method may be filtered.
  118. */
  119. public static function write($key, $value = null, array $options = array()) {
  120. $defaults = array('name' => null, 'strategies' => true);
  121. $options += $defaults;
  122. if (is_resource($value) || !static::$_configurations) {
  123. return false;
  124. }
  125. $methods = array();
  126. if ($name = $options['name']) {
  127. $methods = array($name => static::adapter($name)->write($key, $value, $options));
  128. } else {
  129. foreach (array_keys(static::$_configurations) as $name) {
  130. if ($method = static::adapter($name)->write($key, $value, $options)) {
  131. $methods[$name] = $method;
  132. }
  133. }
  134. }
  135. $result = false;
  136. $original = $value;
  137. foreach ($methods as $name => $method) {
  138. $settings = static::_config($name);
  139. $filters = $settings['filters'];
  140. if ($options['strategies']) {
  141. $options += array('key' => $key, 'class' => __CLASS__);
  142. $value = static::applyStrategies(__FUNCTION__, $name, $original, $options);
  143. }
  144. $params = compact('key', 'value', 'options');
  145. $result = static::_filter(__FUNCTION__, $params, $method, $filters) || $result;
  146. }
  147. return $result;
  148. }
  149. /**
  150. * Deletes a named key from a single adapter (if a `'name'` option is specified) or all
  151. * session adapters.
  152. *
  153. * @param string $key The name of the session key to delete.
  154. * @param array $options Optional parameters that this method accepts:
  155. * - `'name'` _string_: To force the delete to a specific adapter, specify the name
  156. * of the configuration (i.e. `'default'`) here.
  157. * - `'strategies'` _boolean_: Indicates whether or not a configuration's applied
  158. * strategy classes should be enabled for this operation. Defaults to `true`.
  159. * @return boolean Returns `true` on successful delete, or `false` on failure.
  160. * @filter This method may be filtered.
  161. */
  162. public static function delete($key, array $options = array()) {
  163. $defaults = array('name' => null, 'strategies' => true);
  164. $options += $defaults;
  165. $methods = array();
  166. if ($name = $options['name']) {
  167. $methods = array($name => static::adapter($name)->delete($key, $options));
  168. } else {
  169. foreach (static::$_configurations as $name => $config) {
  170. if ($method = static::adapter($name)->delete($key, $options)) {
  171. $methods[$name] = $method;
  172. }
  173. }
  174. }
  175. $result = false;
  176. $options += array('key' => $key, 'class' => __CLASS__);
  177. $original = $key;
  178. foreach ($methods as $name => $method) {
  179. $settings = static::_config($name);
  180. if ($options['strategies']) {
  181. $options += array('key' => $key, 'class' => __CLASS__);
  182. $key = static::applyStrategies(__FUNCTION__, $name, $original, $options);
  183. }
  184. $params = compact('key', 'options');
  185. $filters = $settings['filters'];
  186. $result = static::_filter(__FUNCTION__, $params, $method, $filters) || $result;
  187. }
  188. return $result;
  189. }
  190. /**
  191. * Clears all keys from a single adapter (if a `'name'` options is specified) or all
  192. * session adapters.
  193. *
  194. * @param array $options Optional parameters that this method accepts:
  195. * - `'name'` _string_: To force the write to a specific adapter, specify the name
  196. * of the configuration (i.e. `'default'`) here.
  197. * - `'strategies'` _boolean_: Indicates whether or not a configuration's applied
  198. * strategy classes should be enabled for this operation. Defaults to `true`.
  199. * @filter
  200. */
  201. public static function clear(array $options = array()) {
  202. $defaults = array('name' => null, 'strategies' => true);
  203. $options += $defaults;
  204. $methods = array();
  205. if ($name = $options['name']) {
  206. $methods = array($name => static::adapter($name)->clear($options));
  207. } else {
  208. foreach (static::$_configurations as $name => $config) {
  209. if ($method = static::adapter($name)->clear($options)) {
  210. $methods[$name] = $method;
  211. }
  212. }
  213. }
  214. $params = compact('options');
  215. $result = false;
  216. foreach ($methods as $name => $method) {
  217. $settings = static::_config($name);
  218. $filters = $settings['filters'];
  219. $result = static::_filter(__FUNCTION__, $params, $method, $filters) || $result;
  220. }
  221. if ($options['strategies']) {
  222. $options += array('mode' => 'LIFO', 'class' => __CLASS__);
  223. return static::applyStrategies(__FUNCTION__, $name, $result, $options);
  224. }
  225. return $result;
  226. }
  227. /**
  228. * Checks if a session key is set in any adapter, or if a particular adapter configuration is
  229. * specified (via `'name'` in `$options`), only that configuration is checked.
  230. *
  231. * @param string $key The session key to check.
  232. * @param array $options Optional parameters that this method accepts.
  233. * @return boolean
  234. * @filter This method may be filtered.
  235. */
  236. public static function check($key, array $options = array()) {
  237. $defaults = array('name' => null, 'strategies' => true);
  238. $options += $defaults;
  239. $methods = array();
  240. if ($name = $options['name']) {
  241. $methods = array($name => static::adapter($name)->check($key, $options));
  242. } else {
  243. foreach (static::$_configurations as $name => $config) {
  244. if ($method = static::adapter($name)->check($key, $options)) {
  245. $methods[$name] = $method;
  246. }
  247. }
  248. }
  249. $params = compact('key', 'options');
  250. $result = false;
  251. foreach ($methods as $name => $method) {
  252. $settings = static::_config($name);
  253. $filters = $settings['filters'];
  254. $result = static::_filter(__FUNCTION__, $params, $method, $filters) || $result;
  255. }
  256. if ($options['strategies']) {
  257. $options += array('key' => $key, 'mode' => 'LIFO', 'class' => __CLASS__);
  258. return static::applyStrategies(__FUNCTION__, $name, $result, $options);
  259. }
  260. return $result;
  261. }
  262. /**
  263. * Returns the adapter object instance of the named configuration.
  264. *
  265. * @param string $name Named configuration. If not set, the last configured
  266. * adapter object instance will be returned.
  267. * @return object Adapter instance.
  268. */
  269. public static function adapter($name = null) {
  270. if (!$name) {
  271. if (!$names = array_keys(static::$_configurations)) {
  272. return;
  273. }
  274. $name = end($names);
  275. }
  276. return parent::adapter($name);
  277. }
  278. }
  279. ?>