PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Cache/Storage/Adapter/Session.php

http://github.com/zendframework/zf2
PHP | 546 lines | 312 code | 73 blank | 161 comment | 42 complexity | 7cc2ba1bce323b30ade308135ddc25dc MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Cache\Storage\Adapter;
  10. use stdClass;
  11. use Zend\Cache\Exception;
  12. use Zend\Cache\Storage\Capabilities;
  13. use Zend\Cache\Storage\ClearByPrefixInterface;
  14. use Zend\Cache\Storage\FlushableInterface;
  15. use Zend\Cache\Storage\IterableInterface;
  16. use Zend\Session\Container as SessionContainer;
  17. class Session extends AbstractAdapter implements
  18. ClearByPrefixInterface,
  19. FlushableInterface,
  20. IterableInterface
  21. {
  22. /**
  23. * Set options.
  24. *
  25. * @param array|\Traversable|SessionOptions $options
  26. * @return Memory
  27. * @see getOptions()
  28. */
  29. public function setOptions($options)
  30. {
  31. if (!$options instanceof SessionOptions) {
  32. $options = new SessionOptions($options);
  33. }
  34. return parent::setOptions($options);
  35. }
  36. /**
  37. * Get options.
  38. *
  39. * @return SessionOptions
  40. * @see setOptions()
  41. */
  42. public function getOptions()
  43. {
  44. if (!$this->options) {
  45. $this->setOptions(new SessionOptions());
  46. }
  47. return $this->options;
  48. }
  49. /**
  50. * Get the session container
  51. *
  52. * @return SessionContainer
  53. */
  54. protected function getSessionContainer()
  55. {
  56. $sessionContainer = $this->getOptions()->getSessionContainer();
  57. if (!$sessionContainer) {
  58. throw new Exception\RuntimeException("No session container configured");
  59. }
  60. return $sessionContainer;
  61. }
  62. /* IterableInterface */
  63. /**
  64. * Get the storage iterator
  65. *
  66. * @return KeyListIterator
  67. */
  68. public function getIterator()
  69. {
  70. $cntr = $this->getSessionContainer();
  71. $ns = $this->getOptions()->getNamespace();
  72. if ($cntr->offsetExists($ns)) {
  73. $keys = array_keys($cntr->offsetGet($ns));
  74. } else {
  75. $keys = array();
  76. }
  77. return new KeyListIterator($this, $keys);
  78. }
  79. /* FlushableInterface */
  80. /**
  81. * Flush the whole session container
  82. *
  83. * @return bool
  84. */
  85. public function flush()
  86. {
  87. $this->getSessionContainer()->exchangeArray(array());
  88. return true;
  89. }
  90. /* ClearByPrefixInterface */
  91. /**
  92. * Remove items matching given prefix
  93. *
  94. * @param string $prefix
  95. * @return bool
  96. */
  97. public function clearByPrefix($prefix)
  98. {
  99. $prefix = (string) $prefix;
  100. if ($prefix === '') {
  101. throw new Exception\InvalidArgumentException('No prefix given');
  102. }
  103. $cntr = $this->getSessionContainer();
  104. $ns = $this->getOptions()->getNamespace();
  105. if (!$cntr->offsetExists($ns)) {
  106. return true;
  107. }
  108. $data = $cntr->offsetGet($ns);
  109. $prefixL = strlen($prefix);
  110. foreach ($data as $key => & $item) {
  111. if (substr($key, 0, $prefixL) === $prefix) {
  112. unset($data[$key]);
  113. }
  114. }
  115. $cntr->offsetSet($ns, $data);
  116. return true;
  117. }
  118. /* reading */
  119. /**
  120. * Internal method to get an item.
  121. *
  122. * @param string $normalizedKey
  123. * @param bool $success
  124. * @param mixed $casToken
  125. * @return mixed Data on success, null on failure
  126. * @throws Exception\ExceptionInterface
  127. */
  128. protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
  129. {
  130. $cntr = $this->getSessionContainer();
  131. $ns = $this->getOptions()->getNamespace();
  132. if (!$cntr->offsetExists($ns)) {
  133. $success = false;
  134. return;
  135. }
  136. $data = $cntr->offsetGet($ns);
  137. $success = array_key_exists($normalizedKey, $data);
  138. if (!$success) {
  139. return;
  140. }
  141. $casToken = $value = $data[$normalizedKey];
  142. return $value;
  143. }
  144. /**
  145. * Internal method to get multiple items.
  146. *
  147. * @param array $normalizedKeys
  148. * @return array Associative array of keys and values
  149. * @throws Exception\ExceptionInterface
  150. */
  151. protected function internalGetItems(array & $normalizedKeys)
  152. {
  153. $cntr = $this->getSessionContainer();
  154. $ns = $this->getOptions()->getNamespace();
  155. if (!$cntr->offsetExists($ns)) {
  156. return array();
  157. }
  158. $data = $cntr->offsetGet($ns);
  159. $result = array();
  160. foreach ($normalizedKeys as $normalizedKey) {
  161. if (array_key_exists($normalizedKey, $data)) {
  162. $result[$normalizedKey] = $data[$normalizedKey];
  163. }
  164. }
  165. return $result;
  166. }
  167. /**
  168. * Internal method to test if an item exists.
  169. *
  170. * @param string $normalizedKey
  171. * @return bool
  172. */
  173. protected function internalHasItem(& $normalizedKey)
  174. {
  175. $cntr = $this->getSessionContainer();
  176. $ns = $this->getOptions()->getNamespace();
  177. if (!$cntr->offsetExists($ns)) {
  178. return false;
  179. }
  180. $data = $cntr->offsetGet($ns);
  181. return array_key_exists($normalizedKey, $data);
  182. }
  183. /**
  184. * Internal method to test multiple items.
  185. *
  186. * @param array $normalizedKeys
  187. * @return array Array of found keys
  188. */
  189. protected function internalHasItems(array & $normalizedKeys)
  190. {
  191. $cntr = $this->getSessionContainer();
  192. $ns = $this->getOptions()->getNamespace();
  193. if (!$cntr->offsetExists($ns)) {
  194. return array();
  195. }
  196. $data = $cntr->offsetGet($ns);
  197. $result = array();
  198. foreach ($normalizedKeys as $normalizedKey) {
  199. if (array_key_exists($normalizedKey, $data)) {
  200. $result[] = $normalizedKey;
  201. }
  202. }
  203. return $result;
  204. }
  205. /**
  206. * Get metadata of an item.
  207. *
  208. * @param string $normalizedKey
  209. * @return array|bool Metadata on success, false on failure
  210. * @throws Exception\ExceptionInterface
  211. *
  212. * @triggers getMetadata.pre(PreEvent)
  213. * @triggers getMetadata.post(PostEvent)
  214. * @triggers getMetadata.exception(ExceptionEvent)
  215. */
  216. protected function internalGetMetadata(& $normalizedKey)
  217. {
  218. return $this->internalHasItem($normalizedKey) ? array() : false;
  219. }
  220. /* writing */
  221. /**
  222. * Internal method to store an item.
  223. *
  224. * @param string $normalizedKey
  225. * @param mixed $value
  226. * @return bool
  227. * @throws Exception\ExceptionInterface
  228. */
  229. protected function internalSetItem(& $normalizedKey, & $value)
  230. {
  231. $cntr = $this->getSessionContainer();
  232. $ns = $this->getOptions()->getNamespace();
  233. $data = $cntr->offsetExists($ns) ? $cntr->offsetGet($ns) : array();
  234. $data[$normalizedKey] = $value;
  235. $cntr->offsetSet($ns, $data);
  236. return true;
  237. }
  238. /**
  239. * Internal method to store multiple items.
  240. *
  241. * @param array $normalizedKeyValuePairs
  242. * @return array Array of not stored keys
  243. * @throws Exception\ExceptionInterface
  244. */
  245. protected function internalSetItems(array & $normalizedKeyValuePairs)
  246. {
  247. $cntr = $this->getSessionContainer();
  248. $ns = $this->getOptions()->getNamespace();
  249. if ($cntr->offsetExists($ns)) {
  250. $data = array_merge($cntr->offsetGet($ns), $normalizedKeyValuePairs);
  251. } else {
  252. $data = $normalizedKeyValuePairs;
  253. }
  254. $cntr->offsetSet($ns, $data);
  255. return array();
  256. }
  257. /**
  258. * Add an item.
  259. *
  260. * @param string $normalizedKey
  261. * @param mixed $value
  262. * @return bool
  263. * @throws Exception\ExceptionInterface
  264. */
  265. protected function internalAddItem(& $normalizedKey, & $value)
  266. {
  267. $cntr = $this->getSessionContainer();
  268. $ns = $this->getOptions()->getNamespace();
  269. if ($cntr->offsetExists($ns)) {
  270. $data = $cntr->offsetGet($ns);
  271. if (array_key_exists($normalizedKey, $data)) {
  272. return false;
  273. }
  274. $data[$normalizedKey] = $value;
  275. } else {
  276. $data = array($normalizedKey => $value);
  277. }
  278. $cntr->offsetSet($ns, $data);
  279. return true;
  280. }
  281. /**
  282. * Internal method to add multiple items.
  283. *
  284. * @param array $normalizedKeyValuePairs
  285. * @return array Array of not stored keys
  286. * @throws Exception\ExceptionInterface
  287. */
  288. protected function internalAddItems(array & $normalizedKeyValuePairs)
  289. {
  290. $cntr = $this->getSessionContainer();
  291. $ns = $this->getOptions()->getNamespace();
  292. $result = array();
  293. if ($cntr->offsetExists($ns)) {
  294. $data = $cntr->offsetGet($ns);
  295. foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
  296. if (array_key_exists($normalizedKey, $data)) {
  297. $result[] = $normalizedKey;
  298. } else {
  299. $data[$normalizedKey] = $value;
  300. }
  301. }
  302. } else {
  303. $data = $normalizedKeyValuePairs;
  304. }
  305. $cntr->offsetSet($ns, $data);
  306. return $result;
  307. }
  308. /**
  309. * Internal method to replace an existing item.
  310. *
  311. * @param string $normalizedKey
  312. * @param mixed $value
  313. * @return bool
  314. * @throws Exception\ExceptionInterface
  315. */
  316. protected function internalReplaceItem(& $normalizedKey, & $value)
  317. {
  318. $cntr = $this->getSessionContainer();
  319. $ns = $this->getOptions()->getNamespace();
  320. if (!$cntr->offsetExists($ns)) {
  321. return false;
  322. }
  323. $data = $cntr->offsetGet($ns);
  324. if (!array_key_exists($normalizedKey, $data)) {
  325. return false;
  326. }
  327. $data[$normalizedKey] = $value;
  328. $cntr->offsetSet($ns, $data);
  329. return true;
  330. }
  331. /**
  332. * Internal method to replace multiple existing items.
  333. *
  334. * @param array $normalizedKeyValuePairs
  335. * @return array Array of not stored keys
  336. * @throws Exception\ExceptionInterface
  337. */
  338. protected function internalReplaceItems(array & $normalizedKeyValuePairs)
  339. {
  340. $cntr = $this->getSessionContainer();
  341. $ns = $this->getOptions()->getNamespace();
  342. if (!$cntr->offsetExists($ns)) {
  343. return array_keys($normalizedKeyValuePairs);
  344. }
  345. $data = $cntr->offsetGet($ns);
  346. $result = array();
  347. foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
  348. if (!array_key_exists($normalizedKey, $data)) {
  349. $result[] = $normalizedKey;
  350. } else {
  351. $data[$normalizedKey] = $value;
  352. }
  353. }
  354. $cntr->offsetSet($ns, $data);
  355. return $result;
  356. }
  357. /**
  358. * Internal method to remove an item.
  359. *
  360. * @param string $normalizedKey
  361. * @return bool
  362. * @throws Exception\ExceptionInterface
  363. */
  364. protected function internalRemoveItem(& $normalizedKey)
  365. {
  366. $cntr = $this->getSessionContainer();
  367. $ns = $this->getOptions()->getNamespace();
  368. if (!$cntr->offsetExists($ns)) {
  369. return false;
  370. }
  371. $data = $cntr->offsetGet($ns);
  372. if (!array_key_exists($normalizedKey, $data)) {
  373. return false;
  374. }
  375. unset($data[$normalizedKey]);
  376. if (!$data) {
  377. $cntr->offsetUnset($ns);
  378. } else {
  379. $cntr->offsetSet($ns, $data);
  380. }
  381. return true;
  382. }
  383. /**
  384. * Internal method to increment an item.
  385. *
  386. * @param string $normalizedKey
  387. * @param int $value
  388. * @return int|bool The new value on success, false on failure
  389. * @throws Exception\ExceptionInterface
  390. */
  391. protected function internalIncrementItem(& $normalizedKey, & $value)
  392. {
  393. $cntr = $this->getSessionContainer();
  394. $ns = $this->getOptions()->getNamespace();
  395. if ($cntr->offsetExists($ns)) {
  396. $data = $cntr->offsetGet($ns);
  397. } else {
  398. $data = array();
  399. }
  400. if (array_key_exists($normalizedKey, $data)) {
  401. $data[$normalizedKey]+= $value;
  402. $newValue = $data[$normalizedKey];
  403. } else {
  404. // initial value
  405. $newValue = $value;
  406. $data[$normalizedKey] = $newValue;
  407. }
  408. $cntr->offsetSet($ns, $data);
  409. return $newValue;
  410. }
  411. /**
  412. * Internal method to decrement an item.
  413. *
  414. * @param string $normalizedKey
  415. * @param int $value
  416. * @return int|bool The new value on success, false on failure
  417. * @throws Exception\ExceptionInterface
  418. */
  419. protected function internalDecrementItem(& $normalizedKey, & $value)
  420. {
  421. $cntr = $this->getSessionContainer();
  422. $ns = $this->getOptions()->getNamespace();
  423. if ($cntr->offsetExists($ns)) {
  424. $data = $cntr->offsetGet($ns);
  425. } else {
  426. $data = array();
  427. }
  428. if (array_key_exists($normalizedKey, $data)) {
  429. $data[$normalizedKey]-= $value;
  430. $newValue = $data[$normalizedKey];
  431. } else {
  432. // initial value
  433. $newValue = -$value;
  434. $data[$normalizedKey] = $newValue;
  435. }
  436. $cntr->offsetSet($ns, $data);
  437. return $newValue;
  438. }
  439. /* status */
  440. /**
  441. * Internal method to get capabilities of this adapter
  442. *
  443. * @return Capabilities
  444. */
  445. protected function internalGetCapabilities()
  446. {
  447. if ($this->capabilities === null) {
  448. $this->capabilityMarker = new stdClass();
  449. $this->capabilities = new Capabilities(
  450. $this,
  451. $this->capabilityMarker,
  452. array(
  453. 'supportedDatatypes' => array(
  454. 'NULL' => true,
  455. 'boolean' => true,
  456. 'integer' => true,
  457. 'double' => true,
  458. 'string' => true,
  459. 'array' => 'array',
  460. 'object' => 'object',
  461. 'resource' => false,
  462. ),
  463. 'supportedMetadata' => array(),
  464. 'minTtl' => 0,
  465. 'maxKeyLength' => 0,
  466. 'namespaceIsPrefix' => false,
  467. 'namespaceSeparator' => '',
  468. )
  469. );
  470. }
  471. return $this->capabilities;
  472. }
  473. }