Skip to content

Instantly share code, notes, and snippets.

@damiankloip
Created April 17, 2015 11:57
Show Gist options
  • Save damiankloip/e15ae93b368b90270989 to your computer and use it in GitHub Desktop.
Save damiankloip/e15ae93b368b90270989 to your computer and use it in GitHub Desktop.
diff --git a/core/lib/Drupal/Core/Cache/MultiBackend.php b/core/lib/Drupal/Core/Cache/MultiBackend.php
new file mode 100644
index 0000000..6414543
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/MultiBackend.php
@@ -0,0 +1,213 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\MultiBackend.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * @todo
+ */
+class MultiBackend implements CacheBackendInterface {
+
+ /**
+ * The cache backend being decorated.
+ *
+ * @var \Drupal\Core\Cache\CacheBackendInterface
+ */
+ protected $cacheBackend;
+
+ /**
+ * The cache bin name.
+ *
+ * @var string
+ */
+ protected $bin;
+
+ /**
+ * An array of multiple cache IDs this backend is using.
+ *
+ * @var array
+ */
+ protected $multiCids = [];
+
+ /**
+ * The loaded cache items.
+ *
+ * @var array
+ */
+ protected $cacheItems = [];
+
+ /**
+ * Constructs a MultiBackend object.
+ *
+ * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+ * The cache backend.
+ * @param string $bin
+ * The cache bin for which the object is created.
+ */
+ public function __construct(CacheBackendInterface $cache_backend, $bin) {
+ $this->cacheBackend = $cache_backend;
+ $this->bin = 'cache_multi_' . $bin;
+
+ // @todo Lazy load this? If we want the backend, we might want to do this
+ // anyway. Not sure you would get a service then not use it?
+ $this->preloadMultiple();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($cid, $allow_invalid = FALSE) {
+ $cids = [$cid];
+ $cache = $this->getMultiple($cids);
+ return reset($cache);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMultiple(&$cids, $allow_invalid = FALSE) {
+ return array_intersect_key($this->cacheItems, array_flip($cids));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
+ $return = $this->cacheBackend->set($cid, $data, $expire, $tags);
+ $this->addMultiKeys([$cid]);
+ return $return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMultiple(array $items = array()) {
+ $return = $this->cacheBackend->setMultiple($items);
+
+ // Map keys and store them.
+ $this->addMultiKeys(array_map(function($item) {
+ return $item['cid'];
+ }, $items));
+
+ return $return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($cid) {
+ $this->cacheBackend->delete($cid);
+ $this->removeMultiKeys([$cid]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMultiple(array $cids) {
+ $this->cacheBackend->deleteMultiple($cids);
+ $this->removeMultiKeys($cids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteAll() {
+ $this->cacheBackend->getMultiple(array_merge($this->multiCids, [$this->bin]));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidate($cid) {
+ $this->cacheBackend->invalidate($cid);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateMultiple(array $cids) {
+ $this->cacheBackend->invalidateMultiple($cids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateAll() {
+ $this->cacheBackend->invalidateMultiple(array_merge($this->multiCids, [$this->bin]));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function garbageCollection() {
+ $this->cacheBackend->garbageCollection();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function removeBin() {
+ return FALSE;
+ }
+
+ /**
+ * Pre load Multiple items.
+ */
+ protected function preloadMultiple() {
+ // The bin name will be the multi cid key.
+ // @todo Maybe bin is a bad property name for that.
+ $multi_cid_cache = $this->cacheBackend->get($this->bin);
+
+ if (isset($multi_cid_cache->data)) {
+ $this->multiCids = $multi_cid_cache->data;
+ }
+
+ $this->cacheItems = $this->cacheBackend->getMultiple($this->multiCids);
+
+ // If the loaded items and the multi cids are different reset them.
+ if (array_diff_key($this->cacheItems, $this->multiCids)) {
+ $this->resetMultiKeys();
+ $this->addMultiKeys(array_keys($this->cacheItems));
+ }
+ }
+
+ /**
+ * Adds a mutli cache key.
+ *
+ * @param array $keys
+ */
+ protected function addMultiKeys(array $keys) {
+ foreach ($keys as $key) {
+ $this->multiCids[$key] = $key;
+ }
+
+ // @todo Move this to set on desctruct.
+ $this->cacheBackend->set($this->bin, $this->multiCids);
+ }
+
+ /**
+ * Removes a mutli cache key.
+ *
+ * @param array $keys
+ */
+ protected function removeMultiKeys(array $keys) {
+ foreach ($keys as $key) {
+ unset($this->multiCids[$key]);
+ }
+
+ $this->cacheBackend->set($this->bin, $this->multiCids);
+ }
+
+ /**
+ * Resets multi cache keys.
+ */
+ protected function resetMultiKeys() {
+ $this->cacheBackend->delete($this->bin);
+ $this->multiCids = [];
+ }
+
+}
diff --git a/core/modules/views/views.services.yml b/core/modules/views/views.services.yml
index 1a01543..6b915e6 100644
--- a/core/modules/views/views.services.yml
+++ b/core/modules/views/views.services.yml
@@ -1,7 +1,10 @@
services:
+ cache.views_plugin:
+ class: Drupal\Core\Cache\MultiBackend
+ arguments: ['@cache.discovery', views_plugins]
plugin.manager.views.access:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [access, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [access, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.area:
class: Drupal\views\Plugin\ViewsHandlerManager
arguments: [area, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
@@ -10,22 +13,22 @@ services:
arguments: [argument, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
plugin.manager.views.argument_default:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [argument_default, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [argument_default, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.argument_validator:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [argument_validator, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [argument_validator, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.cache:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [cache, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [cache, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.display_extender:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [display_extender, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [display_extender, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.display:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [display, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [display, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.exposed_form:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [exposed_form, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [exposed_form, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.field:
class: Drupal\views\Plugin\ViewsHandlerManager
arguments: [field, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
@@ -37,7 +40,7 @@ services:
arguments: [join, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
plugin.manager.views.pager:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [pager, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [pager, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.query:
class: Drupal\views\Plugin\ViewsPluginManager
arguments: [query, '@container.namespaces', '@cache.discovery', '@module_handler']
@@ -46,16 +49,16 @@ services:
arguments: [relationship, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
plugin.manager.views.row:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [row, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [row, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.sort:
class: Drupal\views\Plugin\ViewsHandlerManager
arguments: [sort, '@container.namespaces', '@views.views_data', '@cache.discovery', '@module_handler']
plugin.manager.views.style:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [style, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [style, '@container.namespaces', '@cache.views_plugin', '@module_handler']
plugin.manager.views.wizard:
class: Drupal\views\Plugin\ViewsPluginManager
- arguments: [wizard, '@container.namespaces', '@cache.discovery', '@module_handler']
+ arguments: [wizard, '@container.namespaces', '@cache.views_plugin', '@module_handler']
views.views_data:
class: Drupal\views\ViewsData
arguments: ['@cache.discovery', '@config.factory', '@module_handler', '@language_manager']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment