PageRenderTime 62ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/phpfastcache/phpfastcache/src/phpFastCache/Core/Pool/CacheItemPoolTrait.php

https://bitbucket.org/ameeronline/odk-wp-appcontrol
PHP | 416 lines | 185 code | 54 blank | 177 comment | 30 complexity | cf36aeebbb7878572095ca3a5a2dbac4 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. <?php
  2. /**
  3. *
  4. * This file is part of phpFastCache.
  5. *
  6. * @license MIT License (MIT)
  7. *
  8. * For full copyright and license information, please see the docs/CREDITS.txt file.
  9. *
  10. * @author Khoa Bui (khoaofgod) <khoaofgod@gmail.com> http://www.phpfastcache.com
  11. * @author Georges.L (Geolim4) <contact@geolim4.com>
  12. *
  13. */
  14. namespace phpFastCache\Core\Pool;
  15. use phpFastCache\CacheManager;
  16. use phpFastCache\Core\Item\ExtendedCacheItemInterface;
  17. use phpFastCache\Entities\ItemBatch;
  18. use phpFastCache\EventManager;
  19. use phpFastCache\Exceptions\phpFastCacheCoreException;
  20. use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
  21. use phpFastCache\Exceptions\phpFastCacheLogicException;
  22. use phpFastCache\Util\ClassNamespaceResolverTrait;
  23. use Psr\Cache\CacheItemInterface;
  24. /**
  25. * Trait StandardPsr6StructureTrait
  26. * @package phpFastCache\Core
  27. * @property array $config The config array
  28. */
  29. trait CacheItemPoolTrait
  30. {
  31. use ClassNamespaceResolverTrait;
  32. /**
  33. * @var string
  34. */
  35. protected static $unsupportedKeyChars = '{}()/\@:';
  36. /**
  37. * @var array
  38. */
  39. protected $deferredList = [];
  40. /**
  41. * @var ExtendedCacheItemInterface[]
  42. */
  43. protected $itemInstances = [];
  44. /**
  45. * @var EventManager
  46. */
  47. protected $eventManager;
  48. /**
  49. * @param string $key
  50. * @return \phpFastCache\Core\Item\ExtendedCacheItemInterface
  51. * @throws phpFastCacheInvalidArgumentException
  52. * @throws phpFastCacheLogicException
  53. * @throws phpFastCacheCoreException
  54. */
  55. public function getItem($key)
  56. {
  57. if (is_string($key)) {
  58. /**
  59. * Replace array_key_exists by isset
  60. * due to performance issue on huge
  61. * loop dispatching operations
  62. */
  63. if (!isset($this->itemInstances[ $key ])) {
  64. if (preg_match('~([' . preg_quote(self::$unsupportedKeyChars, '~') . ']+)~', $key, $matches)) {
  65. throw new phpFastCacheInvalidArgumentException('Unsupported key character detected: "' . $matches[ 1 ] . '". Please check: https://github.com/PHPSocialNetwork/phpfastcache/wiki/%5BV6%CB%96%5D-Unsupported-characters-in-key-identifiers');
  66. }
  67. /**
  68. * @var $item ExtendedCacheItemInterface
  69. */
  70. CacheManager::$ReadHits++;
  71. $cacheSlamsSpendSeconds = 0;
  72. $class = $this->getClassNamespace() . '\Item';
  73. $item = new $class($this, $key);
  74. $item->setEventManager($this->eventManager);
  75. getItemDriverRead:
  76. {
  77. $driverArray = $this->driverRead($item);
  78. if ($driverArray) {
  79. if (!is_array($driverArray)) {
  80. throw new phpFastCacheCoreException(sprintf('The driverRead method returned an unexpected variable type: %s',
  81. gettype($driverArray)));
  82. }
  83. $driverData = $this->driverUnwrapData($driverArray);
  84. if ($this->getConfig()[ 'preventCacheSlams' ]) {
  85. while ($driverData instanceof ItemBatch) {
  86. if ($driverData->getItemDate()->getTimestamp() + $this->getConfig()[ 'cacheSlamsTimeout' ] < time()) {
  87. /**
  88. * The timeout has been reached
  89. * Consider that the batch has
  90. * failed and serve an empty item
  91. * to avoid to get stuck with a
  92. * batch item stored in driver
  93. */
  94. goto getItemDriverExpired;
  95. }
  96. /**
  97. * @eventName CacheGetItem
  98. * @param $this ExtendedCacheItemPoolInterface
  99. * @param $driverData ItemBatch
  100. * @param $cacheSlamsSpendSeconds int
  101. */
  102. $this->eventManager->dispatch('CacheGetItemInSlamBatch', $this, $driverData, $cacheSlamsSpendSeconds);
  103. /**
  104. * Wait for a second before
  105. * attempting to get exit
  106. * the current batch process
  107. */
  108. sleep(1);
  109. $cacheSlamsSpendSeconds++;
  110. goto getItemDriverRead;
  111. }
  112. }
  113. $item->set($driverData);
  114. $item->expiresAt($this->driverUnwrapEdate($driverArray));
  115. if ($this->config[ 'itemDetailedDate' ]) {
  116. /**
  117. * If the itemDetailedDate has been
  118. * set after caching, we MUST inject
  119. * a new DateTime object on the fly
  120. */
  121. $item->setCreationDate($this->driverUnwrapCdate($driverArray) ?: new \DateTime());
  122. $item->setModificationDate($this->driverUnwrapMdate($driverArray) ?: new \DateTime());
  123. }
  124. $item->setTags($this->driverUnwrapTags($driverArray));
  125. getItemDriverExpired:
  126. if ($item->isExpired()) {
  127. /**
  128. * Using driverDelete() instead of delete()
  129. * to avoid infinite loop caused by
  130. * getItem() call in delete() method
  131. * As we MUST return an item in any
  132. * way, we do not de-register here
  133. */
  134. $this->driverDelete($item);
  135. /**
  136. * Reset the Item
  137. */
  138. $item->set(null)
  139. ->expiresAfter(abs((int)$this->getConfig()[ 'defaultTtl' ]))
  140. ->setHit(false)
  141. ->setTags([]);
  142. if ($this->config[ 'itemDetailedDate' ]) {
  143. /**
  144. * If the itemDetailedDate has been
  145. * set after caching, we MUST inject
  146. * a new DateTime object on the fly
  147. */
  148. $item->setCreationDate(new \DateTime());
  149. $item->setModificationDate(new \DateTime());
  150. }
  151. } else {
  152. $item->setHit(true);
  153. }
  154. } else {
  155. $item->expiresAfter(abs((int)$this->getConfig()[ 'defaultTtl' ]));
  156. }
  157. }
  158. }
  159. } else {
  160. throw new phpFastCacheInvalidArgumentException(sprintf('$key must be a string, got type "%s" instead.', gettype($key)));
  161. }
  162. /**
  163. * @eventName CacheGetItem
  164. * @param $this ExtendedCacheItemPoolInterface
  165. * @param $this ExtendedCacheItemInterface
  166. */
  167. $this->eventManager->dispatch('CacheGetItem', $this, $this->itemInstances[ $key ]);
  168. return $this->itemInstances[ $key ];
  169. }
  170. /**
  171. * @param \Psr\Cache\CacheItemInterface $item
  172. * @return $this
  173. * @throws phpFastCacheInvalidArgumentException
  174. */
  175. public function setItem(CacheItemInterface $item)
  176. {
  177. if ($this->getClassNamespace() . '\\Item' === get_class($item)) {
  178. $this->itemInstances[ $item->getKey() ] = $item;
  179. return $this;
  180. } else {
  181. throw new phpFastCacheInvalidArgumentException(sprintf('Invalid Item Class "%s" for this driver.', get_class($item)));
  182. }
  183. }
  184. /**
  185. * @param array $keys
  186. * @return CacheItemInterface[]
  187. * @throws phpFastCacheInvalidArgumentException
  188. */
  189. public function getItems(array $keys = [])
  190. {
  191. $collection = [];
  192. foreach ($keys as $key) {
  193. $collection[ $key ] = $this->getItem($key);
  194. }
  195. return $collection;
  196. }
  197. /**
  198. * @param string $key
  199. * @return bool
  200. * @throws phpFastCacheInvalidArgumentException
  201. */
  202. public function hasItem($key)
  203. {
  204. return $this->getItem($key)->isHit();
  205. }
  206. /**
  207. * @return bool
  208. */
  209. public function clear()
  210. {
  211. /**
  212. * @eventName CacheClearItem
  213. * @param $this ExtendedCacheItemPoolInterface
  214. * @param $deferredList ExtendedCacheItemInterface[]
  215. */
  216. $this->eventManager->dispatch('CacheClearItem', $this, $this->itemInstances);
  217. CacheManager::$WriteHits++;
  218. $this->itemInstances = [];
  219. return $this->driverClear();
  220. }
  221. /**
  222. * @param string $key
  223. * @return bool
  224. * @throws phpFastCacheInvalidArgumentException
  225. */
  226. public function deleteItem($key)
  227. {
  228. $item = $this->getItem($key);
  229. if ($item->isHit() && $this->driverDelete($item)) {
  230. $item->setHit(false);
  231. CacheManager::$WriteHits++;
  232. /**
  233. * @eventName CacheCommitItem
  234. * @param $this ExtendedCacheItemPoolInterface
  235. * @param $item ExtendedCacheItemInterface
  236. */
  237. $this->eventManager->dispatch('CacheDeleteItem', $this, $item);
  238. /**
  239. * De-register the item instance
  240. * then collect gc cycles
  241. */
  242. $this->deregisterItem($key);
  243. /**
  244. * Perform a tag cleanup to avoid memory leaks
  245. */
  246. if (strpos($key, self::DRIVER_TAGS_KEY_PREFIX) !== 0) {
  247. $this->cleanItemTags($item);
  248. }
  249. return true;
  250. }
  251. return false;
  252. }
  253. /**
  254. * @param array $keys
  255. * @return bool
  256. * @throws phpFastCacheInvalidArgumentException
  257. */
  258. public function deleteItems(array $keys)
  259. {
  260. $return = null;
  261. foreach ($keys as $key) {
  262. $result = $this->deleteItem($key);
  263. if ($result !== false) {
  264. $return = $result;
  265. }
  266. }
  267. return (bool)$return;
  268. }
  269. /**
  270. * @param \Psr\Cache\CacheItemInterface $item
  271. * @return mixed
  272. * @throws phpFastCacheInvalidArgumentException
  273. * @throws \RuntimeException
  274. */
  275. public function save(CacheItemInterface $item)
  276. {
  277. /**
  278. * @var ExtendedCacheItemInterface $item
  279. *
  280. * Replace array_key_exists by isset
  281. * due to performance issue on huge
  282. * loop dispatching operations
  283. */
  284. if (!isset($this->itemInstances[ $item->getKey() ])) {
  285. $this->itemInstances[ $item->getKey() ] = $item;
  286. } else if (spl_object_hash($item) !== spl_object_hash($this->itemInstances[ $item->getKey() ])) {
  287. throw new \RuntimeException('Spl object hash mismatches ! You probably tried to save a detached item which has been already retrieved from cache.');
  288. }
  289. /**
  290. * @eventName CacheSaveItem
  291. * @param $this ExtendedCacheItemPoolInterface
  292. * @param $this ExtendedCacheItemInterface
  293. */
  294. $this->eventManager->dispatch('CacheSaveItem', $this, $item);
  295. if ($this->getConfig()[ 'preventCacheSlams' ]) {
  296. /**
  297. * @var $itemBatch ExtendedCacheItemInterface
  298. */
  299. $class = new \ReflectionClass((new \ReflectionObject($this))->getNamespaceName() . '\Item');
  300. $itemBatch = $class->newInstanceArgs([$this, $item->getKey()]);
  301. $itemBatch->setEventManager($this->eventManager)
  302. ->set(new ItemBatch($item->getKey(), new \DateTime()))
  303. ->expiresAfter($this->getConfig()[ 'cacheSlamsTimeout' ]);
  304. /**
  305. * To avoid SPL mismatches
  306. * we have to re-attach the
  307. * original item to the pool
  308. */
  309. $this->driverWrite($itemBatch);
  310. $this->detachItem($itemBatch);
  311. $this->attachItem($item);
  312. }
  313. if ($this->driverWrite($item) && $this->driverWriteTags($item)) {
  314. $item->setHit(true);
  315. CacheManager::$WriteHits++;
  316. return true;
  317. }
  318. return false;
  319. }
  320. /**
  321. * @param \Psr\Cache\CacheItemInterface $item
  322. * @return \Psr\Cache\CacheItemInterface
  323. * @throws \RuntimeException
  324. */
  325. public function saveDeferred(CacheItemInterface $item)
  326. {
  327. if (!array_key_exists($item->getKey(), $this->itemInstances)) {
  328. $this->itemInstances[ $item->getKey() ] = $item;
  329. } else if (spl_object_hash($item) !== spl_object_hash($this->itemInstances[ $item->getKey() ])) {
  330. throw new \RuntimeException('Spl object hash mismatches ! You probably tried to save a detached item which has been already retrieved from cache.');
  331. }
  332. /**
  333. * @eventName CacheSaveDeferredItem
  334. * @param $this ExtendedCacheItemPoolInterface
  335. * @param $this ExtendedCacheItemInterface
  336. */
  337. $this->eventManager->dispatch('CacheSaveDeferredItem', $this, $item);
  338. return $this->deferredList[ $item->getKey() ] = $item;
  339. }
  340. /**
  341. * @return mixed|null
  342. * @throws phpFastCacheInvalidArgumentException
  343. */
  344. public function commit()
  345. {
  346. /**
  347. * @eventName CacheCommitItem
  348. * @param $this ExtendedCacheItemPoolInterface
  349. * @param $deferredList ExtendedCacheItemInterface[]
  350. */
  351. $this->eventManager->dispatch('CacheCommitItem', $this, $this->deferredList);
  352. $return = null;
  353. foreach ($this->deferredList as $key => $item) {
  354. $result = $this->save($item);
  355. if ($return !== false) {
  356. unset($this->deferredList[ $key ]);
  357. $return = $result;
  358. }
  359. }
  360. return (bool)$return;
  361. }
  362. }