Commit 9447b17b authored by mrweiner's avatar mrweiner

Add register class

parent 16a7d23b
......@@ -2,6 +2,7 @@
namespace Drupal\cache_register;
use Drupal\cache_register\Object\Drawer;
use Drupal\Core\Cache\CacheBackendInterface;
/**
......@@ -29,17 +30,23 @@ class Manager implements ManagerInterface {
/**
* {@inheritDoc}
*/
public function openDrawer(string $implementor_id, $drawer_name = NULL) {
$cache_register_name = $implementor_id;
public function openDrawer(string $implementor_id, $drawer_name, $open_register = FALSE) {
$drawer_id = $implementor_id;
if ($drawer_name) {
$bucket_suffix = is_array($drawer_name)
? implode('.', $drawer_name)
: $drawer_name;
$cache_register_name .= ".$bucket_suffix";
}
$bucket_suffix = is_array($drawer_name)
? implode('.', $drawer_name)
: $drawer_name;
$drawer_id .= ".$bucket_suffix";
return new Drawer($this->cache, $cache_register_name);
return new Drawer($this->cache, $drawer_id, $open_register);
}
/**
* {@inheritDoc}
*/
public function openRegister(string $implementor_id, $drawer_name) {
$drawer = $this->openDrawer($implementor_id, $drawer_name, TRUE);
return $drawer->getRegister();
}
}
......@@ -19,8 +19,34 @@ interface ManagerInterface {
* determining child slot's cache entry IDs.
* - If passed an array, slots will be imploded.
*
* @return \Drupal\cache_register\DrawerInterface
* @param bool $open_register
* (optional) Whether or not to open a register for the drawer.
*
* It's possible that keeping a register open for a large
* set of slots could result in performance penalties.
* We don't know! Use this with caution if you know this
* Drawer is likely to open a large number of slots.
* As such, this defaults to FALSE.
*
* @return \Drupal\cache_register\Object\DrawerInterface
*/
public function openDrawer(string $implementor_id, $drawer_name, bool $open_register = FALSE);
/**
* Creates a Register object and its Drawer.
*
* @param string $implementor_id
* This should generally be the implementing module's name.
* It will be used as the beginning of all child slots'
* cache entry IDs.
* @param string|array|null $drawer_name
* An identifier for the drawer this register tracks.
* It will be appended to the $implementor_id when
* determining child slot's cache entry IDs.
* - If passed an array, slots will be imploded.
*
* @return \Drupal\cache_register\Object\RegisterInterface
*/
public function openDrawer(string $implementor_id, $drawer_name = NULL);
public function openRegister(string $implementor_id, $drawer_name);
}
<?php
namespace Drupal\cache_register;
namespace Drupal\cache_register\Object;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
......@@ -28,6 +28,13 @@ class Drawer implements DrawerInterface {
*/
protected $cacheTags = [];
/**
* This drawer's register.
*
* @var \Drupal\cache_register\Object\RegisterInterface
*/
protected $register;
/**
* The constructor.
*
......@@ -38,19 +45,36 @@ class Drawer implements DrawerInterface {
* Prefixes the cache entry IDs of child Slots.
* This should generally be prefixed by the implementor's name,
* so something like my_module.bookshelf
*
* @param bool $open_register
* Whether or not to open a register for the drawer.
*
* It's possible that keeping a register open for a large
* set of slots could result in performance penalties.
* Use this with caution if you know this Drawer is likely
* to contain a large number of slots.
*/
public function __construct(CacheBackendInterface $cache, string $drawer_id) {
public function __construct(CacheBackendInterface $cache, string $drawer_id, bool $open_register) {
$this->cache = $cache;
// Set to null to help flag if it wasn't implemented in child class
$this->id = $drawer_id;
$this->populateCacheTags();
if ($open_register) {
$this->openRegister();
}
}
/**
* {@inheritDoc}
*/
public function createSlot($slot_ids) {
return new Slot($this->cache, $this, $slot_ids);
public function getRegister() {
return $this->register;
}
/**
* {@inheritDoc}
*/
public function openSlot($slot_ids) {
new Slot($this->cache, $this, $slot_ids);
}
/**
......@@ -87,4 +111,11 @@ class Drawer implements DrawerInterface {
$this->cacheTags[] = 'drawer:' . $this->id;
}
/**
* Opens the associated register.
*/
private function openRegister() {
$this->register = new Register($this->cache, $this);
}
}
<?php
namespace Drupal\cache_register;
namespace Drupal\cache_register\Object;
interface DrawerInterface {
/**
* Gets the Drawer's Register.
*
* @return \Drupal\cache_register\Object\RegisterInterface
*/
public function getRegister();
/**
* Creates a new Slot in the Drawer.
*
......@@ -18,9 +23,9 @@ interface DrawerInterface {
* This might be something like a UID if you are
* caching information about a specific user.
*
* @return \Drupal\cache_register\SlotInterface
* @return \Drupal\cache_register\Object\SlotInterface
*/
public function createSlot($slot_ids);
public function openSlot($slot_ids);
/**
* @return string
......
<?php
namespace Drupal\cache_register\Object;
use Drupal\Core\Cache\CacheBackendInterface;
use http\Exception\InvalidArgumentException;
class Register extends SlotBase implements RegisterInterface {
/**
* The constructor.
*
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* Cache backend.
*
* @param \Drupal\cache_register\Object\DrawerInterface $drawer_to_track
* The drawer that this register tracks.
*/
public function __construct(CacheBackendInterface $cache, DrawerInterface $drawer_to_track) {
parent::__construct($cache, $drawer_to_track, 'register');
if (!$this->isCached()) {
$this->setCache([]);
}
}
/**
* {@inheritDoc}
*
* @todo: getCacheData should be made abstract
*/
public function getSlotList() {
return $this->getCacheData();
}
/**
* {@inheritDoc}
*/
public function addSlot(SlotInterface $slot_to_add) {
$this->addRemoveSlot('add', $slot_to_add);
}
/**
* {@inheritDoc}
*/
public function removeSlot(SlotInterface $slot_to_remove) {
$this->addRemoveSlot('remove', $slot_to_remove);
}
/**
* {@inheritDoc}
*/
protected function setCache($data, $expire = CacheBackendInterface::CACHE_PERMANENT, $tags = []) {
$this->doSetCache($data, $expire, $tags);
}
/**
* Add or remove a slot from the register
*
* @param string $add_or_remove
* Either 'add' or 'remove'.
* @param \Drupal\cache_register\Object\SlotInterface $slot_to_add_remove
* The slot we are adding or removing.
*/
protected function addRemoveSlot(string $add_or_remove, SlotInterface $slot_to_add_remove) {
$valid_options = ['add', 'remove'];
if (!in_array($add_or_remove, $valid_options)) {
throw new InvalidArgumentException('$add_or_remove must be set to either "add" or "remove"');
}
$register_cache = $this->getCache();
$register_list = $register_cache->data;
if ($add_or_remove === 'add') {
$register_list[$slot_to_add_remove->id()] = $slot_to_add_remove->id();
}
else {
unset($register_list[$slot_to_add_remove->id()]);
}
$this->setCache($register_list, $register_cache->expire, $register_cache->tags);
}
}
<?php
namespace Drupal\cache_register\Object;
interface RegisterInterface extends SlotBaseInterface {
/**
* Get the drawer that the register is tracking.
*
* @return \Drupal\cache_register\Object\Drawer
* The Drawer.
*/
public function getDrawer();
/**
* Gets the list of Slot IDs in the register.
*
* @return array
* The list of Slot IDs.
*/
public function getSlotList();
/**
* Add a slot to the register.
*
* @param \Drupal\cache_register\Object\SlotInterface $slot_to_add
*/
public function addSlot(SlotInterface $slot_to_add);
/**
* Remove a slot from the register.
*
* @param \Drupal\cache_register\Object\SlotInterface $slot_to_remove
*/
public function removeSlot(SlotInterface $slot_to_remove);
}
<?php
namespace Drupal\cache_register\Object;
use Drupal\Core\Cache\CacheBackendInterface;
class Slot extends SlotBase implements SlotInterface {
/**
* {@inheritDoc}
*/
public function __construct(CacheBackendInterface $cache, DrawerInterface $parent_drawer, string $slot_ids) {
parent::__construct($cache, $parent_drawer, $slot_ids);
}
/**
* {@inheritDoc}
*/
public function setCache($data, $expire = CacheBackendInterface::CACHE_PERMANENT, $tags = []) {
$this->addToRegister();
$this->doSetCache($data, $expire, $tags);
}
/**
* {@inheritDoc}
*/
public function deleteCache() {
$this->cache->delete($this->id);
$this->removeFromRegister();
}
/**
* {@inheritDoc}
*/
public function invalidateCache() {
$this->cache->invalidate($this->id);
$this->removeFromRegister();
}
/**
* Adds the slot to the register.
*/
private function addToRegister() {
if ($register = $this->getDrawer()->getRegister()) {
$register->addSlot($this);
}
}
/**
* Removes the slot from the register.
*/
private function removeFromRegister() {
if ($register = $this->getDrawer()->getRegister()) {
$register->removeSlot($this);
}
}
}
<?php
namespace Drupal\cache_register;
namespace Drupal\cache_register\Object;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
class Slot implements SlotInterface {
abstract class SlotBase implements SlotBaseInterface {
/**
* The cache backend service.
......@@ -17,7 +17,7 @@ class Slot implements SlotInterface {
/**
* The parent CacheRegister.
*
* @var \Drupal\cache_register\DrawerInterface
* @var \Drupal\cache_register\Object\DrawerInterface
*/
protected $drawer;
......@@ -45,7 +45,6 @@ class Slot implements SlotInterface {
* @param array|string $slot_ids
* The ID(s) to use for the slot's cache identifier.
*/
public function __construct(CacheBackendInterface $cache, DrawerInterface $parent_drawer, string $slot_ids) {
$this->cache = $cache;
$this->drawer = $parent_drawer;
......@@ -59,6 +58,9 @@ class Slot implements SlotInterface {
return $this->id;
}
/**
* {@inheritDoc}
*/
public function getDrawer() {
return $this->drawer;
}
......@@ -74,14 +76,6 @@ class Slot implements SlotInterface {
return FALSE;
}
/**
* {@inheritDoc}
*/
public function setCache($data, $expire = CacheBackendInterface::CACHE_PERMANENT, $tags = []) {
$tags = Cache::mergeTags($tags, $this->getDrawer()->getCacheTags());
$this->cache->set($this->id, $data, $expire, $tags);
}
/**
* {@inheritDoc}
*/
......@@ -121,17 +115,58 @@ class Slot implements SlotInterface {
}
/**
* {@inheritDoc}
* Sets the slot's cache entry.
*
* @param mixed $data
* The data to be saved to the given cache slot.
*
* @param int $expire
* One of the following values:
* - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item should
* not be removed unless it is deleted explicitly.
* - A Unix timestamp: Indicates that the item will be considered invalid
* after this time, i.e. it will not be returned by get() unless
* $allow_invalid has been set to TRUE. When the item has expired, it may
* be permanently deleted by the garbage collector at any time.
*
* @param array $tags
* An array of tags to be stored with the cache item. These should normally
* identify objects used to build the cache item, which should trigger
* cache invalidation when updated. For example if a cached item represents
* a node, both the node ID and the author's user ID might be passed in as
* tags. For example ['node:123', 'node:456', 'user:789'].
*
* @see CacheBackendInterface
*/
public function deleteCache() {
$this->cache->delete($this->id);
}
abstract protected function setCache($data, int $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = []);
/**
* {@inheritDoc}
* Common inner method for abstracted setCache.
*
* @param mixed $data
* The data to be saved to the given cache slot.
*
* @param int $expire
* One of the following values:
* - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item should
* not be removed unless it is deleted explicitly.
* - A Unix timestamp: Indicates that the item will be considered invalid
* after this time, i.e. it will not be returned by get() unless
* $allow_invalid has been set to TRUE. When the item has expired, it may
* be permanently deleted by the garbage collector at any time.
*
* @param array $tags
* An array of tags to be stored with the cache item. These should normally
* identify objects used to build the cache item, which should trigger
* cache invalidation when updated. For example if a cached item represents
* a node, both the node ID and the author's user ID might be passed in as
* tags. For example ['node:123', 'node:456', 'user:789'].
*
* @see CacheBackendInterface
*/
public function invalidateCache() {
$this->cache->invalidate($this->id);
protected function doSetCache($data, int $expire, array $tags) {
$tags = Cache::mergeTags($tags, $this->getDrawer()->getCacheTags());
$this->cache->set($this->id, $data, $expire, $tags);
}
/**
......
<?php
namespace Drupal\cache_register;
namespace Drupal\cache_register\Object;
use Drupal\Core\Cache\CacheBackendInterface;
interface SlotInterface {
interface SlotBaseInterface {
/**
* Checks if the slot has an entry in the cache.
......@@ -14,32 +12,6 @@ interface SlotInterface {
*/
public function isCached();
/**
* Sets the slot's cache entry.
*
* @param mixed $data
* The data to be saved to the given cache slot.
*
* @param int $expire
* One of the following values:
* - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item should
* not be removed unless it is deleted explicitly.
* - A Unix timestamp: Indicates that the item will be considered invalid
* after this time, i.e. it will not be returned by get() unless
* $allow_invalid has been set to TRUE. When the item has expired, it may
* be permanently deleted by the garbage collector at any time.
*
* @param array $tags
* An array of tags to be stored with the cache item. These should normally
* identify objects used to build the cache item, which should trigger
* cache invalidation when updated. For example if a cached item represents
* a node, both the node ID and the author's user ID might be passed in as
* tags. For example ['node:123', 'node:456', 'user:789'].
*
* @see CacheBackendInterface
*/
public function setCache($data, int $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = []);
/**
* Adds the given tags to the slot's cache entry.
*
......@@ -72,16 +44,6 @@ interface SlotInterface {
*/
public function getCacheData();
/**
* Delete the slot's cache entry.
*/
public function deleteCache();
/**
* Delete the slot's cache entry.
*/
public function invalidateCache();
/**
* Get the ID of the slot's cache entry.
*
......@@ -93,7 +55,7 @@ interface SlotInterface {
/**
* Gets the slots parent drawer.
*
* @return \Drupal\cache_register\DrawerInterface
* @return \Drupal\cache_register\Object\DrawerInterface
* The drawer.
*/
public function getDrawer();
......
<?php
namespace Drupal\cache_register\Object;
interface SlotInterface extends SlotBaseInterface {
/**
* Delete the slot's cache entry.
*/
public function deleteCache();
/**
* Delete the slot's cache entry.
*/
public function invalidateCache();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment