PhpArrayCache.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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\Cache\Simple;
  11. use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
  12. use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
  13. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  14. use Symfony\Component\Cache\PruneableInterface;
  15. use Symfony\Component\Cache\ResettableInterface;
  16. use Symfony\Component\Cache\Traits\PhpArrayTrait;
  17. use Symfony\Contracts\Cache\CacheInterface;
  18. @trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PhpArrayCache::class, PhpArrayAdapter::class, CacheInterface::class), E_USER_DEPRECATED);
  19. /**
  20. * @deprecated since Symfony 4.3, use PhpArrayAdapter and type-hint for CacheInterface instead.
  21. */
  22. class PhpArrayCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface
  23. {
  24. use PhpArrayTrait;
  25. /**
  26. * @param string $file The PHP file were values are cached
  27. * @param Psr16CacheInterface $fallbackPool A pool to fallback on when an item is not hit
  28. */
  29. public function __construct(string $file, Psr16CacheInterface $fallbackPool)
  30. {
  31. $this->file = $file;
  32. $this->pool = $fallbackPool;
  33. }
  34. /**
  35. * This adapter takes advantage of how PHP stores arrays in its latest versions.
  36. *
  37. * @param string $file The PHP file were values are cached
  38. *
  39. * @return Psr16CacheInterface
  40. */
  41. public static function create($file, Psr16CacheInterface $fallbackPool)
  42. {
  43. // Shared memory is available in PHP 7.0+ with OPCache enabled
  44. if (filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) {
  45. return new static($file, $fallbackPool);
  46. }
  47. return $fallbackPool;
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function get($key, $default = null)
  53. {
  54. if (!\is_string($key)) {
  55. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  56. }
  57. if (null === $this->values) {
  58. $this->initialize();
  59. }
  60. if (!isset($this->keys[$key])) {
  61. return $this->pool->get($key, $default);
  62. }
  63. $value = $this->values[$this->keys[$key]];
  64. if ('N;' === $value) {
  65. return null;
  66. }
  67. if ($value instanceof \Closure) {
  68. try {
  69. return $value();
  70. } catch (\Throwable $e) {
  71. return $default;
  72. }
  73. }
  74. return $value;
  75. }
  76. /**
  77. * {@inheritdoc}
  78. */
  79. public function getMultiple($keys, $default = null)
  80. {
  81. if ($keys instanceof \Traversable) {
  82. $keys = iterator_to_array($keys, false);
  83. } elseif (!\is_array($keys)) {
  84. throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys)));
  85. }
  86. foreach ($keys as $key) {
  87. if (!\is_string($key)) {
  88. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  89. }
  90. }
  91. if (null === $this->values) {
  92. $this->initialize();
  93. }
  94. return $this->generateItems($keys, $default);
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function has($key)
  100. {
  101. if (!\is_string($key)) {
  102. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  103. }
  104. if (null === $this->values) {
  105. $this->initialize();
  106. }
  107. return isset($this->keys[$key]) || $this->pool->has($key);
  108. }
  109. /**
  110. * {@inheritdoc}
  111. */
  112. public function delete($key)
  113. {
  114. if (!\is_string($key)) {
  115. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  116. }
  117. if (null === $this->values) {
  118. $this->initialize();
  119. }
  120. return !isset($this->keys[$key]) && $this->pool->delete($key);
  121. }
  122. /**
  123. * {@inheritdoc}
  124. */
  125. public function deleteMultiple($keys)
  126. {
  127. if (!\is_array($keys) && !$keys instanceof \Traversable) {
  128. throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys)));
  129. }
  130. $deleted = true;
  131. $fallbackKeys = [];
  132. foreach ($keys as $key) {
  133. if (!\is_string($key)) {
  134. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  135. }
  136. if (isset($this->keys[$key])) {
  137. $deleted = false;
  138. } else {
  139. $fallbackKeys[] = $key;
  140. }
  141. }
  142. if (null === $this->values) {
  143. $this->initialize();
  144. }
  145. if ($fallbackKeys) {
  146. $deleted = $this->pool->deleteMultiple($fallbackKeys) && $deleted;
  147. }
  148. return $deleted;
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function set($key, $value, $ttl = null)
  154. {
  155. if (!\is_string($key)) {
  156. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  157. }
  158. if (null === $this->values) {
  159. $this->initialize();
  160. }
  161. return !isset($this->keys[$key]) && $this->pool->set($key, $value, $ttl);
  162. }
  163. /**
  164. * {@inheritdoc}
  165. */
  166. public function setMultiple($values, $ttl = null)
  167. {
  168. if (!\is_array($values) && !$values instanceof \Traversable) {
  169. throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', \is_object($values) ? \get_class($values) : \gettype($values)));
  170. }
  171. $saved = true;
  172. $fallbackValues = [];
  173. foreach ($values as $key => $value) {
  174. if (!\is_string($key) && !\is_int($key)) {
  175. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  176. }
  177. if (isset($this->keys[$key])) {
  178. $saved = false;
  179. } else {
  180. $fallbackValues[$key] = $value;
  181. }
  182. }
  183. if ($fallbackValues) {
  184. $saved = $this->pool->setMultiple($fallbackValues, $ttl) && $saved;
  185. }
  186. return $saved;
  187. }
  188. private function generateItems(array $keys, $default)
  189. {
  190. $fallbackKeys = [];
  191. foreach ($keys as $key) {
  192. if (isset($this->keys[$key])) {
  193. $value = $this->values[$this->keys[$key]];
  194. if ('N;' === $value) {
  195. yield $key => null;
  196. } elseif ($value instanceof \Closure) {
  197. try {
  198. yield $key => $value();
  199. } catch (\Throwable $e) {
  200. yield $key => $default;
  201. }
  202. } else {
  203. yield $key => $value;
  204. }
  205. } else {
  206. $fallbackKeys[] = $key;
  207. }
  208. }
  209. if ($fallbackKeys) {
  210. yield from $this->pool->getMultiple($fallbackKeys, $default);
  211. }
  212. }
  213. }