PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/blog/vendor/laravel/framework/src/Illuminate/Session/Store.php

https://gitlab.com/zan_zan/laravel_sample
PHP | 682 lines | 292 code | 92 blank | 298 comment | 11 complexity | 3c42a19b52577be1118a213e27c73bb0 MD5 | raw file
  1. <?php
  2. namespace Illuminate\Session;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Support\Str;
  5. use SessionHandlerInterface;
  6. use InvalidArgumentException;
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  9. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  10. class Store implements SessionInterface
  11. {
  12. /**
  13. * The session ID.
  14. *
  15. * @var string
  16. */
  17. protected $id;
  18. /**
  19. * The session name.
  20. *
  21. * @var string
  22. */
  23. protected $name;
  24. /**
  25. * The session attributes.
  26. *
  27. * @var array
  28. */
  29. protected $attributes = [];
  30. /**
  31. * The session bags.
  32. *
  33. * @var array
  34. */
  35. protected $bags = [];
  36. /**
  37. * The meta-data bag instance.
  38. *
  39. * @var \Symfony\Component\HttpFoundation\Session\Storage\MetadataBag
  40. */
  41. protected $metaBag;
  42. /**
  43. * Local copies of the session bag data.
  44. *
  45. * @var array
  46. */
  47. protected $bagData = [];
  48. /**
  49. * The session handler implementation.
  50. *
  51. * @var \SessionHandlerInterface
  52. */
  53. protected $handler;
  54. /**
  55. * Session store started status.
  56. *
  57. * @var bool
  58. */
  59. protected $started = false;
  60. /**
  61. * Create a new session instance.
  62. *
  63. * @param string $name
  64. * @param \SessionHandlerInterface $handler
  65. * @param string|null $id
  66. * @return void
  67. */
  68. public function __construct($name, SessionHandlerInterface $handler, $id = null)
  69. {
  70. $this->setId($id);
  71. $this->name = $name;
  72. $this->handler = $handler;
  73. $this->metaBag = new MetadataBag;
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. public function start()
  79. {
  80. $this->loadSession();
  81. if (!$this->has('_token')) {
  82. $this->regenerateToken();
  83. }
  84. return $this->started = true;
  85. }
  86. /**
  87. * Load the session data from the handler.
  88. *
  89. * @return void
  90. */
  91. protected function loadSession()
  92. {
  93. $this->attributes = array_merge($this->attributes, $this->readFromHandler());
  94. foreach (array_merge($this->bags, [$this->metaBag]) as $bag) {
  95. $this->initializeLocalBag($bag);
  96. $bag->initialize($this->bagData[$bag->getStorageKey()]);
  97. }
  98. }
  99. /**
  100. * Read the session data from the handler.
  101. *
  102. * @return array
  103. */
  104. protected function readFromHandler()
  105. {
  106. $data = $this->handler->read($this->getId());
  107. if ($data) {
  108. $data = @unserialize($this->prepareForUnserialize($data));
  109. if ($data !== false && $data !== null && is_array($data)) {
  110. return $data;
  111. }
  112. }
  113. return [];
  114. }
  115. /**
  116. * Prepare the raw string data from the session for unserialization.
  117. *
  118. * @param string $data
  119. * @return string
  120. */
  121. protected function prepareForUnserialize($data)
  122. {
  123. return $data;
  124. }
  125. /**
  126. * Initialize a bag in storage if it doesn't exist.
  127. *
  128. * @param \Symfony\Component\HttpFoundation\Session\SessionBagInterface $bag
  129. * @return void
  130. */
  131. protected function initializeLocalBag($bag)
  132. {
  133. $this->bagData[$bag->getStorageKey()] = $this->pull($bag->getStorageKey(), []);
  134. }
  135. /**
  136. * {@inheritdoc}
  137. */
  138. public function getId()
  139. {
  140. return $this->id;
  141. }
  142. /**
  143. * {@inheritdoc}
  144. */
  145. public function setId($id)
  146. {
  147. if (!$this->isValidId($id)) {
  148. $id = $this->generateSessionId();
  149. }
  150. $this->id = $id;
  151. }
  152. /**
  153. * Determine if this is a valid session ID.
  154. *
  155. * @param string $id
  156. * @return bool
  157. */
  158. public function isValidId($id)
  159. {
  160. return is_string($id) && preg_match('/^[a-f0-9]{40}$/', $id);
  161. }
  162. /**
  163. * Get a new, random session ID.
  164. *
  165. * @return string
  166. */
  167. protected function generateSessionId()
  168. {
  169. return sha1(uniqid('', true).Str::random(25).microtime(true));
  170. }
  171. /**
  172. * {@inheritdoc}
  173. */
  174. public function getName()
  175. {
  176. return $this->name;
  177. }
  178. /**
  179. * {@inheritdoc}
  180. */
  181. public function setName($name)
  182. {
  183. $this->name = $name;
  184. }
  185. /**
  186. * {@inheritdoc}
  187. */
  188. public function invalidate($lifetime = null)
  189. {
  190. $this->clear();
  191. return $this->migrate(true, $lifetime);
  192. }
  193. /**
  194. * {@inheritdoc}
  195. */
  196. public function migrate($destroy = false, $lifetime = null)
  197. {
  198. if ($destroy) {
  199. $this->handler->destroy($this->getId());
  200. }
  201. $this->setExists(false);
  202. $this->id = $this->generateSessionId();
  203. return true;
  204. }
  205. /**
  206. * Generate a new session identifier.
  207. *
  208. * @param bool $destroy
  209. * @return bool
  210. */
  211. public function regenerate($destroy = false)
  212. {
  213. return $this->migrate($destroy);
  214. }
  215. /**
  216. * {@inheritdoc}
  217. */
  218. public function save()
  219. {
  220. $this->addBagDataToSession();
  221. $this->ageFlashData();
  222. $this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));
  223. $this->started = false;
  224. }
  225. /**
  226. * Prepare the serialized session data for storage.
  227. *
  228. * @param string $data
  229. * @return string
  230. */
  231. protected function prepareForStorage($data)
  232. {
  233. return $data;
  234. }
  235. /**
  236. * Merge all of the bag data into the session.
  237. *
  238. * @return void
  239. */
  240. protected function addBagDataToSession()
  241. {
  242. foreach (array_merge($this->bags, [$this->metaBag]) as $bag) {
  243. $this->put($bag->getStorageKey(), $this->bagData[$bag->getStorageKey()]);
  244. }
  245. }
  246. /**
  247. * Age the flash data for the session.
  248. *
  249. * @return void
  250. */
  251. public function ageFlashData()
  252. {
  253. foreach ($this->get('flash.old', []) as $old) {
  254. $this->forget($old);
  255. }
  256. $this->put('flash.old', $this->get('flash.new', []));
  257. $this->put('flash.new', []);
  258. }
  259. /**
  260. * {@inheritdoc}
  261. */
  262. public function has($name)
  263. {
  264. return !is_null($this->get($name));
  265. }
  266. /**
  267. * {@inheritdoc}
  268. */
  269. public function get($name, $default = null)
  270. {
  271. return Arr::get($this->attributes, $name, $default);
  272. }
  273. /**
  274. * Get the value of a given key and then forget it.
  275. *
  276. * @param string $key
  277. * @param string $default
  278. * @return mixed
  279. */
  280. public function pull($key, $default = null)
  281. {
  282. return Arr::pull($this->attributes, $key, $default);
  283. }
  284. /**
  285. * Determine if the session contains old input.
  286. *
  287. * @param string $key
  288. * @return bool
  289. */
  290. public function hasOldInput($key = null)
  291. {
  292. $old = $this->getOldInput($key);
  293. return is_null($key) ? count($old) > 0 : !is_null($old);
  294. }
  295. /**
  296. * Get the requested item from the flashed input array.
  297. *
  298. * @param string $key
  299. * @param mixed $default
  300. * @return mixed
  301. */
  302. public function getOldInput($key = null, $default = null)
  303. {
  304. $input = $this->get('_old_input', []);
  305. // Input that is flashed to the session can be easily retrieved by the
  306. // developer, making repopulating old forms and the like much more
  307. // convenient, since the request's previous input is available.
  308. return Arr::get($input, $key, $default);
  309. }
  310. /**
  311. * {@inheritdoc}
  312. */
  313. public function set($name, $value)
  314. {
  315. Arr::set($this->attributes, $name, $value);
  316. }
  317. /**
  318. * Put a key / value pair or array of key / value pairs in the session.
  319. *
  320. * @param string|array $key
  321. * @param mixed|null $value
  322. * @return void
  323. */
  324. public function put($key, $value = null)
  325. {
  326. if (!is_array($key)) {
  327. $key = [$key => $value];
  328. }
  329. foreach ($key as $arrayKey => $arrayValue) {
  330. $this->set($arrayKey, $arrayValue);
  331. }
  332. }
  333. /**
  334. * Push a value onto a session array.
  335. *
  336. * @param string $key
  337. * @param mixed $value
  338. * @return void
  339. */
  340. public function push($key, $value)
  341. {
  342. $array = $this->get($key, []);
  343. $array[] = $value;
  344. $this->put($key, $array);
  345. }
  346. /**
  347. * Flash a key / value pair to the session.
  348. *
  349. * @param string $key
  350. * @param mixed $value
  351. * @return void
  352. */
  353. public function flash($key, $value)
  354. {
  355. $this->put($key, $value);
  356. $this->push('flash.new', $key);
  357. $this->removeFromOldFlashData([$key]);
  358. }
  359. /**
  360. * Flash an input array to the session.
  361. *
  362. * @param array $value
  363. * @return void
  364. */
  365. public function flashInput(array $value)
  366. {
  367. $this->flash('_old_input', $value);
  368. }
  369. /**
  370. * Reflash all of the session flash data.
  371. *
  372. * @return void
  373. */
  374. public function reflash()
  375. {
  376. $this->mergeNewFlashes($this->get('flash.old', []));
  377. $this->put('flash.old', []);
  378. }
  379. /**
  380. * Reflash a subset of the current flash data.
  381. *
  382. * @param array|mixed $keys
  383. * @return void
  384. */
  385. public function keep($keys = null)
  386. {
  387. $keys = is_array($keys) ? $keys : func_get_args();
  388. $this->mergeNewFlashes($keys);
  389. $this->removeFromOldFlashData($keys);
  390. }
  391. /**
  392. * Merge new flash keys into the new flash array.
  393. *
  394. * @param array $keys
  395. * @return void
  396. */
  397. protected function mergeNewFlashes(array $keys)
  398. {
  399. $values = array_unique(array_merge($this->get('flash.new', []), $keys));
  400. $this->put('flash.new', $values);
  401. }
  402. /**
  403. * Remove the given keys from the old flash data.
  404. *
  405. * @param array $keys
  406. * @return void
  407. */
  408. protected function removeFromOldFlashData(array $keys)
  409. {
  410. $this->put('flash.old', array_diff($this->get('flash.old', []), $keys));
  411. }
  412. /**
  413. * {@inheritdoc}
  414. */
  415. public function all()
  416. {
  417. return $this->attributes;
  418. }
  419. /**
  420. * {@inheritdoc}
  421. */
  422. public function replace(array $attributes)
  423. {
  424. $this->put($attributes);
  425. }
  426. /**
  427. * {@inheritdoc}
  428. */
  429. public function remove($name)
  430. {
  431. return Arr::pull($this->attributes, $name);
  432. }
  433. /**
  434. * Remove an item from the session.
  435. *
  436. * @param string $key
  437. * @return void
  438. */
  439. public function forget($key)
  440. {
  441. Arr::forget($this->attributes, $key);
  442. }
  443. /**
  444. * {@inheritdoc}
  445. */
  446. public function clear()
  447. {
  448. $this->attributes = [];
  449. foreach ($this->bags as $bag) {
  450. $bag->clear();
  451. }
  452. }
  453. /**
  454. * Remove all of the items from the session.
  455. *
  456. * @return void
  457. */
  458. public function flush()
  459. {
  460. $this->clear();
  461. }
  462. /**
  463. * {@inheritdoc}
  464. */
  465. public function isStarted()
  466. {
  467. return $this->started;
  468. }
  469. /**
  470. * {@inheritdoc}
  471. */
  472. public function registerBag(SessionBagInterface $bag)
  473. {
  474. $this->bags[$bag->getStorageKey()] = $bag;
  475. }
  476. /**
  477. * {@inheritdoc}
  478. */
  479. public function getBag($name)
  480. {
  481. return Arr::get($this->bags, $name, function () {
  482. throw new InvalidArgumentException('Bag not registered.');
  483. });
  484. }
  485. /**
  486. * {@inheritdoc}
  487. */
  488. public function getMetadataBag()
  489. {
  490. return $this->metaBag;
  491. }
  492. /**
  493. * Get the raw bag data array for a given bag.
  494. *
  495. * @param string $name
  496. * @return array
  497. */
  498. public function getBagData($name)
  499. {
  500. return Arr::get($this->bagData, $name, []);
  501. }
  502. /**
  503. * Get the CSRF token value.
  504. *
  505. * @return string
  506. */
  507. public function token()
  508. {
  509. return $this->get('_token');
  510. }
  511. /**
  512. * Get the CSRF token value.
  513. *
  514. * @return string
  515. */
  516. public function getToken()
  517. {
  518. return $this->token();
  519. }
  520. /**
  521. * Regenerate the CSRF token value.
  522. *
  523. * @return void
  524. */
  525. public function regenerateToken()
  526. {
  527. $this->put('_token', Str::random(40));
  528. }
  529. /**
  530. * Get the previous URL from the session.
  531. *
  532. * @return string|null
  533. */
  534. public function previousUrl()
  535. {
  536. return $this->get('_previous.url');
  537. }
  538. /**
  539. * Set the "previous" URL in the session.
  540. *
  541. * @param string $url
  542. * @return void
  543. */
  544. public function setPreviousUrl($url)
  545. {
  546. return $this->put('_previous.url', $url);
  547. }
  548. /**
  549. * Set the existence of the session on the handler if applicable.
  550. *
  551. * @param bool $value
  552. * @return void
  553. */
  554. public function setExists($value)
  555. {
  556. if ($this->handler instanceof ExistenceAwareInterface) {
  557. $this->handler->setExists($value);
  558. }
  559. }
  560. /**
  561. * Get the underlying session handler implementation.
  562. *
  563. * @return \SessionHandlerInterface
  564. */
  565. public function getHandler()
  566. {
  567. return $this->handler;
  568. }
  569. /**
  570. * Determine if the session handler needs a request.
  571. *
  572. * @return bool
  573. */
  574. public function handlerNeedsRequest()
  575. {
  576. return $this->handler instanceof CookieSessionHandler;
  577. }
  578. /**
  579. * Set the request on the handler instance.
  580. *
  581. * @param \Symfony\Component\HttpFoundation\Request $request
  582. * @return void
  583. */
  584. public function setRequestOnHandler(Request $request)
  585. {
  586. if ($this->handlerNeedsRequest()) {
  587. $this->handler->setRequest($request);
  588. }
  589. }
  590. }