Skip to content

Commit

Permalink
Merge branch 'cache-tags'
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Nov 1, 2013
2 parents 64f2482 + 1b4d4f2 commit 70108fe
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 201 deletions.
13 changes: 1 addition & 12 deletions src/Illuminate/Cache/ApcStore.php
@@ -1,6 +1,6 @@
<?php namespace Illuminate\Cache;

class ApcStore implements StoreInterface {
class ApcStore extends TaggableStore implements StoreInterface {

/**
* The APC wrapper instance.
Expand Down Expand Up @@ -115,17 +115,6 @@ public function flush()
$this->apc->flush();
}

/**
* Begin executing a new section operation.
*
* @param string $name
* @return \Illuminate\Cache\Section
*/
public function section($name)
{
return new Section($this, $name);
}

/**
* Get the cache key prefix.
*
Expand Down
13 changes: 1 addition & 12 deletions src/Illuminate/Cache/ArrayStore.php
@@ -1,6 +1,6 @@
<?php namespace Illuminate\Cache;

class ArrayStore implements StoreInterface {
class ArrayStore extends TaggableStore implements StoreInterface {

/**
* The array of stored values.
Expand Down Expand Up @@ -97,17 +97,6 @@ public function flush()
$this->storage = array();
}

/**
* Begin executing a new section operation.
*
* @param string $name
* @return \Illuminate\Cache\Section
*/
public function section($name)
{
return new Section($this, $name);
}

/**
* Get the cache key prefix.
*
Expand Down
13 changes: 1 addition & 12 deletions src/Illuminate/Cache/MemcachedStore.php
Expand Up @@ -2,7 +2,7 @@

use Memcached;

class MemcachedStore implements StoreInterface {
class MemcachedStore extends TaggableStore implements StoreInterface {

/**
* The Memcached instance.
Expand Down Expand Up @@ -117,17 +117,6 @@ public function flush()
$this->memcached->flush();
}

/**
* Begin executing a new section operation.
*
* @param string $name
* @return \Illuminate\Cache\Section
*/
public function section($name)
{
return new Section($this, $name);
}

/**
* Get the underlying Memcached connection.
*
Expand Down
84 changes: 0 additions & 84 deletions src/Illuminate/Cache/RedisSection.php

This file was deleted.

12 changes: 6 additions & 6 deletions src/Illuminate/Cache/RedisStore.php
Expand Up @@ -2,7 +2,7 @@

use Illuminate\Redis\Database as Redis;

class RedisStore implements StoreInterface {
class RedisStore extends TaggableStore implements StoreInterface {

/**
* The Redis database connection.
Expand Down Expand Up @@ -131,14 +131,14 @@ public function flush()
}

/**
* Begin executing a new section operation.
* Begin executing a new tags operation.
*
* @param string $name
* @return \Illuminate\Cache\RedisSection
* @param array|dynamic $names
* @return \Illuminate\Cache\RedisTaggedCache
*/
public function section($name)
public function tags($names)
{
return new RedisSection($this, $name);
return new RedisTaggedCache($this, is_array($names) ? $names : func_get_args());
}

/**
Expand Down
90 changes: 90 additions & 0 deletions src/Illuminate/Cache/RedisTaggedCache.php
@@ -0,0 +1,90 @@
<?php namespace Illuminate\Cache;

class RedisTaggedCache extends TaggedCache {

/**
* Store an item in the cache indefinitely.
*
* @param string $key
* @param mixed $value
* @return void
*/
public function forever($key, $value)
{
$this->pushForeverKeys($namespace = $this->tags->getNamespace(), $key);

$this->store->forever(sha1($namespace).':'.$key, $value);
}

/**
* Remove all items from the cache.
*
* @return void
*/
public function flush()
{
$this->deleteForeverKeys();

parent::flush();
}

/**
* Store a copy of the full key for each namespace segment.
*
* @param string $namespace
* @param string $key
* @return void
*/
protected function pushForeverKeys($namespace, $key)
{
$fullKey = $this->getPrefix().sha1($namespace).':'.$key;

foreach (explode('|', $namespace) as $segment)
{
$this->store->connection()->lpush($this->foreverKey($segment), $fullKey);
}
}

/**
* Delete all of the items that were stored forever.
*
* @return void
*/
protected function deleteForeverKeys()
{
foreach (explode('|', $this->tags->getNamespace()) as $segment)
{
$this->deleteForeverValues($segment = $this->foreverKey($segment));

$this->store->connection()->del($segment);
}
}

/**
* Delete all of the keys that have been stored forever.
*
* @param string $foreverKey
* @return void
*/
protected function deleteForeverValues($foreverKey)
{
$forever = array_unique($this->store->connection()->lrange($foreverKey, 0, -1));

if (count($forever) > 0)
{
call_user_func_array(array($this->store->connection(), 'del'), $forever);
}
}

/**
* Get the forever reference key for hte segment.
*
* @param string $segment
* @return string
*/
protected function foreverKey($segment)
{
return $this->getPrefix().$segment.':forever';
}

}
110 changes: 110 additions & 0 deletions src/Illuminate/Cache/TagSet.php
@@ -0,0 +1,110 @@
<?php namespace Illuminate\Cache;

use ArrayIterator;
use IteratorAggregate;

class TagSet implements IteratorAggregate {

/**
* The cache store implementation.
*
* @var \Illuminate\Cache\StoreInterface
*/
protected $store;

/**
* The tag names.
*
* @var array
*/
protected $names = array();

/**
* Create a new TagSet instance.
*
* @param \Illuminate\Cache\StoreInterface $store
* @param string $names
* @return void
*/
public function __construct(StoreInterface $store, $names)
{
$this->store = $store;
$this->names = $names;
}

/**
* Reset all tags in the set.
*
* @return void
*/
public function reset()
{
array_walk($this->names, array($this, 'resetTag'));
}

/**
* Get the unique tag identifier for a given tag.
*
* @param string $name
* @return string
*/
public function tagId($name)
{
return $this->store->get($this->tagKey($name)) ?: $this->resetTag($name);
}

/**
* Get an array of tag identifiers for all of the tags in the set.
*
* @return array
*/
protected function tagIds()
{
return array_map(array($this, 'tagId'), $this->names);
}

/**
* Get a unique namespace that changes when any of the tags are flushed.
*
* @return string
*/
public function getNamespace()
{
return implode('|', $this->tagIds());
}

/**
* Reset the tag and return the new tag identifier
*
* @param string $name
* @return string
*/
public function resetTag($name)
{
$this->store->forever($this->tagKey($name), $id = uniqid());

return $id;
}

/**
* Get the tag identifier key for a given tag.
*
* @param string $name
* @return string
*/
public function tagKey($name)
{
return 'tag:'.$name.':key';
}

/**
* Get a traversable implementation for the class.
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->names);
}

}

0 comments on commit 70108fe

Please sign in to comment.