/** * {@inheritdoc} */ protected function filterInvalidatedKeys(array &$keys) { $tags = $invalids = array(); foreach ($keys as $i => $key) { CacheItem::validateKey($key); foreach ($this->redis->hGetAll($this->namespace . $key . ':tags') as $tag => $version) { $tags[$this->namespace . 'tag:' . $tag][$version][$i] = $key; } } if ($tags) { $j = 0; $versions = $this->redis->mGet(array_keys($tags)); foreach ($tags as $tag => $version) { $version = $versions[$j++]; unset($tags[$tag][(int) $version]); foreach ($tags[$tag] as $version) { foreach ($version as $i => $key) { $invalids[] = $key; unset($keys[$i]); } } } } return $invalids; }
public function __construct($namespace = '', $defaultLifetime = 0, $version = null) { if (!static::isSupported()) { throw new CacheException('APCu is not enabled'); } if ('cli' === PHP_SAPI) { ini_set('apc.use_request_time', 0); } parent::__construct($namespace, $defaultLifetime); if (null !== $version) { CacheItem::validateKey($version); if (!apcu_exists($version . ':' . $namespace)) { $this->clear($namespace); apcu_add($version . ':' . $namespace, null); } } }
private function generateItems(array $keys, $now) { $f = $this->createCacheItem; foreach ($keys as $i => $key) { try { if (!($isHit = isset($this->expiries[$key]) && ($this->expiries[$key] >= $now || !$this->deleteItem($key)))) { $this->values[$key] = $value = null; } elseif (!$this->storeSerialized) { $value = $this->values[$key]; } elseif ('b:0;' === ($value = $this->values[$key])) { $value = false; } elseif (false === ($value = unserialize($value))) { $this->values[$key] = $value = null; $isHit = false; } } catch (\Exception $e) { CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e)); $this->values[$key] = $value = null; $isHit = false; } unset($keys[$i]); (yield $key => $f($key, $value, $isHit)); } foreach ($keys as $key) { (yield $key => $f($key, null, false)); } }
/** * Store an array of cached values. * * @param array $values The cached values */ public function warmUp(array $values) { if (file_exists($this->file)) { if (!is_file($this->file)) { throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: %s.', $this->file)); } if (!is_writable($this->file)) { throw new InvalidArgumentException(sprintf('Cache file is not writable: %s.', $this->file)); } } else { $directory = dirname($this->file); if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: %s.', $directory)); } if (!is_writable($directory)) { throw new InvalidArgumentException(sprintf('Cache directory is not writable: %s.', $directory)); } } $dump = <<<'EOF' <?php // This file has been auto-generated by the Symfony Cache Component. return array( EOF; foreach ($values as $key => $value) { CacheItem::validateKey(is_int($key) ? (string) $key : $key); if (null === $value || is_object($value)) { try { $value = serialize($value); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, get_class($value)), 0, $e); } } elseif (is_array($value)) { try { $serialized = serialize($value); $unserialized = unserialize($serialized); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable array value.', $key), 0, $e); } // Store arrays serialized if they contain any objects or references if ($unserialized !== $value || false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized)) { $value = $serialized; } } elseif (is_string($value)) { // Serialize strings if they could be confused with serialized objects or arrays if ('N;' === $value || isset($value[2]) && ':' === $value[1]) { $value = serialize($value); } } elseif (!is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, gettype($value))); } $dump .= var_export($key, true) . ' => ' . var_export($value, true) . ",\n"; } $dump .= "\n);\n"; $dump = str_replace("' . \"\\0\" . '", "", $dump); $tmpFile = uniqid($this->file); file_put_contents($tmpFile, $dump); @chmod($tmpFile, 0666); unset($serialized, $unserialized, $value, $dump); @rename($tmpFile, $this->file); $this->values = (include $this->file) ?: array(); }
/** * {@inheritdoc} */ public function commit() { $ok = true; $byLifetime = $this->mergeByLifetime; $byLifetime = $byLifetime($this->deferred, $this->namespace); $retry = $this->deferred = array(); foreach ($byLifetime as $lifetime => $values) { try { $e = $this->doSave($values, $lifetime); } catch (\Exception $e) { } if (true === $e || array() === $e) { continue; } if (is_array($e) || 1 === count($values)) { foreach (is_array($e) ? $e : array_keys($values) as $id) { $ok = false; $v = $values[$id]; $type = is_object($v) ? get_class($v) : gettype($v); CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => substr($id, strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null)); } } else { foreach ($values as $id => $v) { $retry[$lifetime][] = $id; } } } // When bulk-save failed, retry each item individually foreach ($retry as $lifetime => $ids) { foreach ($ids as $id) { try { $v = $byLifetime[$lifetime][$id]; $e = $this->doSave(array($id => $v), $lifetime); } catch (\Exception $e) { } if (true === $e || array() === $e) { continue; } $ok = false; $type = is_object($v) ? get_class($v) : gettype($v); CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => substr($id, strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null)); } } $this->deferred = array(); return $ok; }
private function getId($key) { CacheItem::validateKey($key); return $this->namespace . $key; }
private function generateItems($items, &$keys) { $f = $this->createCacheItem; try { foreach ($items as $id => $value) { $key = $keys[$id]; unset($keys[$id]); (yield $key => $f($key, $value, true)); } } catch (\Exception $e) { CacheItem::log($this->logger, 'Failed to fetch requested items', array('keys' => array_values($keys), 'exception' => $e)); } foreach ($keys as $key) { (yield $key => $f($key, null, false)); } }
/** * {@inheritdoc} */ public function save(CacheItemInterface $item) { if (!$item instanceof CacheItem) { return false; } $item = (array) $item; $key = $item[CacheItem::CAST_PREFIX . 'key']; $value = $item[CacheItem::CAST_PREFIX . 'value']; $expiry = $item[CacheItem::CAST_PREFIX . 'expiry']; if (null !== $expiry && $expiry <= time()) { $this->deleteItem($key); return true; } if ($this->storeSerialized) { try { $value = serialize($value); } catch (\Exception $e) { $type = is_object($value) ? get_class($value) : gettype($value); CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e)); return false; } } $this->values[$key] = $value; $this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX; return true; }
/** * @dataProvider provideInvalidKey * @expectedException Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Cache key */ public function testInvalidKey($key) { CacheItem::validateKey($key); }
/** * @dataProvider provideInvalidKey * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Cache tag */ public function testInvalidTag($tag) { $item = new CacheItem(); $item->tag($tag); }
/** * {@inheritdoc} */ public function commit() { $f = $this->mergeByLifetime; $ko = array(); foreach ($f($this->deferred, $this->namespace) as $lifetime => $values) { try { if (true === ($ok = $this->doSave($values, $lifetime))) { continue; } } catch (\Exception $e) { $ok = false; } if (false === $ok) { $ok = array_keys($values); } foreach ($ok as $id) { $ko[$lifetime][] = array($id => $values[$id]); } } $this->deferred = array(); $ok = true; // When bulk-save failed, retry each item individually foreach ($ko as $lifetime => $values) { foreach ($values as $v) { try { $e = $this->doSave($v, $lifetime); } catch (\Exception $e) { } if (true !== $e && array() !== $e) { $ok = false; foreach ($v as $key => $value) { $type = is_object($value) ? get_class($value) : gettype($value); CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null)); } } } } return $ok; }
/** * {@inheritdoc} */ public function save(CacheItemInterface $item) { if (!$item instanceof CacheItem) { return false; } $item = (array) $item; $key = $item[CacheItem::CAST_PREFIX . 'key']; $value = $item[CacheItem::CAST_PREFIX . 'value']; $lifetime = $item[CacheItem::CAST_PREFIX . 'lifetime']; if (0 > $lifetime) { return true; } if (is_object($value)) { try { $value = clone $value; } catch (\Exception $e) { $type = is_object($value) ? get_class($value) : gettype($value); CacheItem::log($this->logger, 'Failed to clone key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e)); return false; } } $this->values[$key] = $value; $this->expiries[$key] = $lifetime ? $lifetime + time() : PHP_INT_MAX; return true; }