/Nette/Http/SessionSection.php

https://github.com/langpavel/nette · PHP · 273 lines · 127 code · 59 blank · 87 comment · 15 complexity · c32f4e34074fe8c261fadd2de74cfac2 MD5 · raw file

  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (http://nette.org)
  4. *
  5. * Copyright (c) 2004, 2011 David Grudl (http://davidgrudl.com)
  6. *
  7. * For the full copyright and license information, please view
  8. * the file license.txt that was distributed with this source code.
  9. */
  10. namespace Nette\Http;
  11. use Nette;
  12. /**
  13. * Session section.
  14. *
  15. * @author David Grudl
  16. */
  17. final class SessionSection extends Nette\Object implements \IteratorAggregate, \ArrayAccess
  18. {
  19. /** @var Session */
  20. private $session;
  21. /** @var string */
  22. private $name;
  23. /** @var array session data storage */
  24. private $data;
  25. /** @var array session metadata storage */
  26. private $meta = FALSE;
  27. /** @var bool */
  28. public $warnOnUndefined = FALSE;
  29. /**
  30. * Do not call directly. Use Session::getSection().
  31. */
  32. public function __construct(Session $session, $name)
  33. {
  34. if (!is_string($name)) {
  35. throw new Nette\InvalidArgumentException("Session namespace must be a string, " . gettype($name) ." given.");
  36. }
  37. $this->session = $session;
  38. $this->name = $name;
  39. }
  40. /**
  41. * Do not call directly. Use Session::getNamespace().
  42. */
  43. private function start()
  44. {
  45. if ($this->meta === FALSE) {
  46. $this->session->start();
  47. $this->data = & $_SESSION['__NF']['DATA'][$this->name];
  48. $this->meta = & $_SESSION['__NF']['META'][$this->name];
  49. }
  50. }
  51. /**
  52. * Returns an iterator over all section variables.
  53. * @return \ArrayIterator
  54. */
  55. public function getIterator()
  56. {
  57. $this->start();
  58. if (isset($this->data)) {
  59. return new \ArrayIterator($this->data);
  60. } else {
  61. return new \ArrayIterator;
  62. }
  63. }
  64. /**
  65. * Sets a variable in this session section.
  66. * @param string name
  67. * @param mixed value
  68. * @return void
  69. */
  70. public function __set($name, $value)
  71. {
  72. $this->start();
  73. $this->data[$name] = $value;
  74. if (is_object($value)) {
  75. $this->meta[$name]['V'] = Nette\Reflection\ClassType::from($value)->getAnnotation('serializationVersion');
  76. }
  77. }
  78. /**
  79. * Gets a variable from this session section.
  80. * @param string name
  81. * @return mixed
  82. */
  83. public function &__get($name)
  84. {
  85. $this->start();
  86. if ($this->warnOnUndefined && !array_key_exists($name, $this->data)) {
  87. trigger_error("The variable '$name' does not exist in session section", E_USER_NOTICE);
  88. }
  89. return $this->data[$name];
  90. }
  91. /**
  92. * Determines whether a variable in this session section is set.
  93. * @param string name
  94. * @return bool
  95. */
  96. public function __isset($name)
  97. {
  98. if ($this->session->exists()) {
  99. $this->start();
  100. }
  101. return isset($this->data[$name]);
  102. }
  103. /**
  104. * Unsets a variable in this session section.
  105. * @param string name
  106. * @return void
  107. */
  108. public function __unset($name)
  109. {
  110. $this->start();
  111. unset($this->data[$name], $this->meta[$name]);
  112. }
  113. /**
  114. * Sets a variable in this session section.
  115. * @param string name
  116. * @param mixed value
  117. * @return void
  118. */
  119. public function offsetSet($name, $value)
  120. {
  121. $this->__set($name, $value);
  122. }
  123. /**
  124. * Gets a variable from this session section.
  125. * @param string name
  126. * @return mixed
  127. */
  128. public function offsetGet($name)
  129. {
  130. return $this->__get($name);
  131. }
  132. /**
  133. * Determines whether a variable in this session section is set.
  134. * @param string name
  135. * @return bool
  136. */
  137. public function offsetExists($name)
  138. {
  139. return $this->__isset($name);
  140. }
  141. /**
  142. * Unsets a variable in this session section.
  143. * @param string name
  144. * @return void
  145. */
  146. public function offsetUnset($name)
  147. {
  148. $this->__unset($name);
  149. }
  150. /**
  151. * Sets the expiration of the section or specific variables.
  152. * @param string|int|DateTime time, value 0 means "until the browser is closed"
  153. * @param mixed optional list of variables / single variable to expire
  154. * @return SessionSection provides a fluent interface
  155. */
  156. public function setExpiration($time, $variables = NULL)
  157. {
  158. $this->start();
  159. if (empty($time)) {
  160. $time = NULL;
  161. $whenBrowserIsClosed = TRUE;
  162. } else {
  163. $time = Nette\DateTime::from($time)->format('U');
  164. $max = ini_get('session.gc_maxlifetime');
  165. if ($time - time() > $max + 3) { // bulgarian constant
  166. trigger_error("The expiration time is greater than the session expiration $max seconds", E_USER_NOTICE);
  167. }
  168. $whenBrowserIsClosed = FALSE;
  169. }
  170. if ($variables === NULL) { // to entire section
  171. $this->meta['']['T'] = $time;
  172. $this->meta['']['B'] = $whenBrowserIsClosed;
  173. } elseif (is_array($variables)) { // to variables
  174. foreach ($variables as $variable) {
  175. $this->meta[$variable]['T'] = $time;
  176. $this->meta[$variable]['B'] = $whenBrowserIsClosed;
  177. }
  178. } else { // to variable
  179. $this->meta[$variables]['T'] = $time;
  180. $this->meta[$variables]['B'] = $whenBrowserIsClosed;
  181. }
  182. return $this;
  183. }
  184. /**
  185. * Removes the expiration from the section or specific variables.
  186. * @param mixed optional list of variables / single variable to expire
  187. * @return void
  188. */
  189. public function removeExpiration($variables = NULL)
  190. {
  191. $this->start();
  192. if ($variables === NULL) {
  193. // from entire section
  194. unset($this->meta['']['T'], $this->meta['']['B']);
  195. } elseif (is_array($variables)) {
  196. // from variables
  197. foreach ($variables as $variable) {
  198. unset($this->meta[$variable]['T'], $this->meta[$variable]['B']);
  199. }
  200. } else {
  201. unset($this->meta[$variables]['T'], $this->meta[$variable]['B']);
  202. }
  203. }
  204. /**
  205. * Cancels the current session section.
  206. * @return void
  207. */
  208. public function remove()
  209. {
  210. $this->start();
  211. $this->data = NULL;
  212. $this->meta = NULL;
  213. }
  214. }