Session.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpFoundation\Session;
  11. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
  12. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  13. use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
  14. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  15. use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
  16. use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
  17. // Help opcache.preload discover always-needed symbols
  18. class_exists(AttributeBag::class);
  19. class_exists(FlashBag::class);
  20. class_exists(SessionBagProxy::class);
  21. /**
  22. * @author Fabien Potencier <fabien@symfony.com>
  23. * @author Drak <drak@zikula.org>
  24. *
  25. * @implements \IteratorAggregate<string, mixed>
  26. */
  27. class Session implements SessionInterface, \IteratorAggregate, \Countable
  28. {
  29. protected $storage;
  30. private $flashName;
  31. private $attributeName;
  32. private $data = [];
  33. private $usageIndex = 0;
  34. private $usageReporter;
  35. public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null)
  36. {
  37. $this->storage = $storage ?? new NativeSessionStorage();
  38. $this->usageReporter = $usageReporter;
  39. $attributes = $attributes ?? new AttributeBag();
  40. $this->attributeName = $attributes->getName();
  41. $this->registerBag($attributes);
  42. $flashes = $flashes ?? new FlashBag();
  43. $this->flashName = $flashes->getName();
  44. $this->registerBag($flashes);
  45. }
  46. /**
  47. * {@inheritdoc}
  48. */
  49. public function start()
  50. {
  51. return $this->storage->start();
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. public function has(string $name)
  57. {
  58. return $this->getAttributeBag()->has($name);
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. public function get(string $name, $default = null)
  64. {
  65. return $this->getAttributeBag()->get($name, $default);
  66. }
  67. /**
  68. * {@inheritdoc}
  69. */
  70. public function set(string $name, $value)
  71. {
  72. $this->getAttributeBag()->set($name, $value);
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. public function all()
  78. {
  79. return $this->getAttributeBag()->all();
  80. }
  81. /**
  82. * {@inheritdoc}
  83. */
  84. public function replace(array $attributes)
  85. {
  86. $this->getAttributeBag()->replace($attributes);
  87. }
  88. /**
  89. * {@inheritdoc}
  90. */
  91. public function remove(string $name)
  92. {
  93. return $this->getAttributeBag()->remove($name);
  94. }
  95. /**
  96. * {@inheritdoc}
  97. */
  98. public function clear()
  99. {
  100. $this->getAttributeBag()->clear();
  101. }
  102. /**
  103. * {@inheritdoc}
  104. */
  105. public function isStarted()
  106. {
  107. return $this->storage->isStarted();
  108. }
  109. /**
  110. * Returns an iterator for attributes.
  111. *
  112. * @return \ArrayIterator<string, mixed>
  113. */
  114. #[\ReturnTypeWillChange]
  115. public function getIterator()
  116. {
  117. return new \ArrayIterator($this->getAttributeBag()->all());
  118. }
  119. /**
  120. * Returns the number of attributes.
  121. *
  122. * @return int
  123. */
  124. #[\ReturnTypeWillChange]
  125. public function count()
  126. {
  127. return \count($this->getAttributeBag()->all());
  128. }
  129. public function &getUsageIndex(): int
  130. {
  131. return $this->usageIndex;
  132. }
  133. /**
  134. * @internal
  135. */
  136. public function isEmpty(): bool
  137. {
  138. if ($this->isStarted()) {
  139. ++$this->usageIndex;
  140. if ($this->usageReporter && 0 <= $this->usageIndex) {
  141. ($this->usageReporter)();
  142. }
  143. }
  144. foreach ($this->data as &$data) {
  145. if (!empty($data)) {
  146. return false;
  147. }
  148. }
  149. return true;
  150. }
  151. /**
  152. * {@inheritdoc}
  153. */
  154. public function invalidate(?int $lifetime = null)
  155. {
  156. $this->storage->clear();
  157. return $this->migrate(true, $lifetime);
  158. }
  159. /**
  160. * {@inheritdoc}
  161. */
  162. public function migrate(bool $destroy = false, ?int $lifetime = null)
  163. {
  164. return $this->storage->regenerate($destroy, $lifetime);
  165. }
  166. /**
  167. * {@inheritdoc}
  168. */
  169. public function save()
  170. {
  171. $this->storage->save();
  172. }
  173. /**
  174. * {@inheritdoc}
  175. */
  176. public function getId()
  177. {
  178. return $this->storage->getId();
  179. }
  180. /**
  181. * {@inheritdoc}
  182. */
  183. public function setId(string $id)
  184. {
  185. if ($this->storage->getId() !== $id) {
  186. $this->storage->setId($id);
  187. }
  188. }
  189. /**
  190. * {@inheritdoc}
  191. */
  192. public function getName()
  193. {
  194. return $this->storage->getName();
  195. }
  196. /**
  197. * {@inheritdoc}
  198. */
  199. public function setName(string $name)
  200. {
  201. $this->storage->setName($name);
  202. }
  203. /**
  204. * {@inheritdoc}
  205. */
  206. public function getMetadataBag()
  207. {
  208. ++$this->usageIndex;
  209. if ($this->usageReporter && 0 <= $this->usageIndex) {
  210. ($this->usageReporter)();
  211. }
  212. return $this->storage->getMetadataBag();
  213. }
  214. /**
  215. * {@inheritdoc}
  216. */
  217. public function registerBag(SessionBagInterface $bag)
  218. {
  219. $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter));
  220. }
  221. /**
  222. * {@inheritdoc}
  223. */
  224. public function getBag(string $name)
  225. {
  226. $bag = $this->storage->getBag($name);
  227. return method_exists($bag, 'getBag') ? $bag->getBag() : $bag;
  228. }
  229. /**
  230. * Gets the flashbag interface.
  231. *
  232. * @return FlashBagInterface
  233. */
  234. public function getFlashBag()
  235. {
  236. return $this->getBag($this->flashName);
  237. }
  238. /**
  239. * Gets the attributebag interface.
  240. *
  241. * Note that this method was added to help with IDE autocompletion.
  242. */
  243. private function getAttributeBag(): AttributeBagInterface
  244. {
  245. return $this->getBag($this->attributeName);
  246. }
  247. }