diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index eac2f97..282da00 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -2443,7 +2443,7 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) { // @todo Replace this with a cache.factory service plus 'config' argument. $container ->register('cache.config', 'Drupal\Core\Cache\CacheBackendInterface') - ->setFactoryClass('Drupal\Core\Cache\CacheFactory') + ->setFactoryService('cache') ->setFactoryMethod('get') ->addArgument('config'); @@ -2452,6 +2452,14 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) { ->addArgument(new Reference('config.cachedstorage.storage')) ->addArgument(new Reference('cache.config')); + // Register the KeyValueStore factory. + $container + ->register('cache', 'Drupal\Core\Cache\CacheFactory') + ->addArgument(new Reference('service_container')); + $container + ->register('cache.database', 'Drupal\Core\Cache\DatabaseBackendFactory') + ->addArgument(new Reference('database')); + // Register configuration object factory. $container->register('config.subscriber.globalconf', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber'); $container->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher') diff --git a/core/includes/cache.inc b/core/includes/cache.inc index 341d77f..452403c 100644 --- a/core/includes/cache.inc +++ b/core/includes/cache.inc @@ -26,21 +26,7 @@ * @see Drupal\Core\Cache\CacheBackendInterface */ function cache($bin = 'cache') { - // Use the advanced drupal_static() pattern, since this is called very often. - static $drupal_static_fast; - if (!isset($drupal_static_fast)) { - $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__, array()); - } - $cache_objects = &$drupal_static_fast['cache']; - - // Temporary backwards compatibiltiy layer, allow old style prefixed cache - // bin names to be passed as arguments. - $bin = str_replace('cache_', '', $bin); - - if (!isset($cache_objects[$bin])) { - $cache_objects[$bin] = CacheFactory::get($bin); - } - return $cache_objects[$bin]; + return drupal_container()->get('cache')->get($bin); } /** diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php index da42a26..9f259d4 100644 --- a/core/lib/Drupal/Core/Cache/CacheFactory.php +++ b/core/lib/Drupal/Core/Cache/CacheFactory.php @@ -7,50 +7,62 @@ namespace Drupal\Core\Cache; +use Symfony\Component\DependencyInjection\ContainerInterface; + /** * Defines the cache backend factory. */ class CacheFactory { /** - * Instantiates a cache backend class for a given cache bin. - * - * By default, this returns an instance of the - * Drupal\Core\Cache\DatabaseBackend class. + * Instantiated caches, keyed by bin name. * - * Classes implementing Drupal\Core\Cache\CacheBackendInterface can register - * themselves both as a default implementation and for specific bins. + * @var array + */ + protected $bins = array(); + + /** + * The dependency injection container. * - * @param string $bin - * The cache bin for which a cache backend object should be returned. + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** + * Constructs a CacheFactory. * - * @return Drupal\Core\Cache\CacheBackendInterface - * The cache backend object associated with the specified bin. + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container */ - public static function get($bin) { - // Check whether there is a custom class defined for the requested bin or - // use the default 'cache' definition otherwise. - $cache_backends = self::getBackends(); - $class = isset($cache_backends[$bin]) ? $cache_backends[$bin] : $cache_backends['cache']; - return new $class($bin); + function __construct(ContainerInterface $container) { + $this->container = $container; } /** - * Returns a list of cache backends for this site. + * Instantiates a cache backend class for a given cache bin. + * + * Classes implementing CacheBackendInterface can register themselves both as + * a default implementation and for specific bins. + * + * @param string $bin + * The cache bin for which a cache backend object should be returned. * - * @return array - * An associative array with cache bins as keys, and backend class names as - * value. + * @return Drupal\Core\Cache\CacheBackendInterface + * The cache backend object associated with the specified bin. */ - public static function getBackends() { - // @todo Improve how cache backend classes are defined. Cannot be - // configuration, since e.g. the CachedStorage config storage controller - // requires the definition in its constructor already. + public function get($bin) { global $conf; - $cache_backends = isset($conf['cache_classes']) ? $conf['cache_classes'] : array(); - // Ensure there is a default 'cache' bin definition. - $cache_backends += array('cache' => 'Drupal\Core\Cache\DatabaseBackend'); - return $cache_backends; + if (!isset($this->bins[$bin])) { + if (isset($conf['cache_bin_' . $bin])) { + $service_name = $conf['cache_bin_' . $bin]; + } + elseif (isset($conf['cache_bin'])) { + $service_name = $conf['cache_bin']; + } + else { + $service_name = 'cache.database'; + } + $this->bins[$bin] = $this->container->get($service_name)->get($bin); + } + return $this->bins[$bin]; } - } diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index a12ed13..d98199e 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Cache; -use Drupal\Core\Database\Database; +use Drupal\Core\Database\Connection; use Exception; /** @@ -24,17 +24,27 @@ class DatabaseBackend implements CacheBackendInterface { protected $bin; /** + * A database connection object. + * + * @var Drupal\Core\Database\Connection + */ + protected $connection; + + /** * A static cache of all tags checked during the request. */ protected static $tagCache = array(); /** - * Constructs a DatabaseBackend object. + * Constructs a new cache database backend. * * @param string $bin - * The cache bin for which the object is created. + * (optional) The cache bin that should be used. + * @param Drupal\Core\Database\Connection $connection + * The database connection that should be used. */ - public function __construct($bin) { + function __construct($bin, Connection $connection) { + $this->connection = $connection; // All cache tables should be prefixed with 'cache_', except for the // default 'cache' bin. if ($bin != 'cache') { @@ -64,7 +74,7 @@ public function getMultiple(&$cids) { // is used here only due to the performance overhead we would incur // otherwise. When serving an uncached page, the overhead of using // ::select() is a much smaller proportion of the request. - $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); + $result = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids)); $cache = array(); foreach ($result as $item) { $item = $this->prepareItem($item); @@ -75,7 +85,7 @@ public function getMultiple(&$cids) { $cids = array_diff($cids, array_keys($cache)); return $cache; } - catch (Exception $e) { + catch (\Exception $e) { // If the database is never going to be available, cache requests should // return FALSE in order to allow exception handling to occur. return array(); @@ -137,7 +147,7 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN } try { - Database::getConnection()->merge($this->bin) + $this->connection->merge($this->bin) ->key(array('cid' => $cid)) ->fields($fields) ->execute(); @@ -151,7 +161,7 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ public function delete($cid) { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('cid', $cid) ->execute(); } @@ -162,7 +172,7 @@ public function delete($cid) { public function deleteMultiple(array $cids) { // Delete in chunks when a large array is passed. do { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('cid', array_splice($cids, 0, 1000), 'IN') ->execute(); } @@ -173,14 +183,14 @@ public function deleteMultiple(array $cids) { * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ public function flush() { - Database::getConnection()->truncate($this->bin)->execute(); + $this->connection->truncate($this->bin)->execute(); } /** * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ public function expire() { - Database::getConnection()->delete($this->bin) + $this->connection->delete($this->bin) ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>') ->condition('expire', REQUEST_TIME, '<') ->execute(); @@ -243,7 +253,7 @@ protected function flattenTags(array $tags) { public function invalidateTags(array $tags) { foreach ($this->flattenTags($tags) as $tag) { unset(self::$tagCache[$tag]); - Database::getConnection()->merge('cache_tags') + $this->connection->merge('cache_tags') ->key(array('tag' => $tag)) ->fields(array('invalidations' => 1)) ->expression('invalidations', 'invalidations + 1') @@ -274,7 +284,7 @@ protected function checksumTags($tags) { } if ($query_tags) { try { - if ($db_tags = Database::getConnection()->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) { + if ($db_tags = $this->connection->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) { self::$tagCache = array_merge(self::$tagCache, $db_tags); $checksum += array_sum($db_tags); } @@ -291,7 +301,7 @@ protected function checksumTags($tags) { */ public function isEmpty() { $this->garbageCollection(); - $query = Database::getConnection()->select($this->bin); + $query = $this->connection->select($this->bin); $query->addExpression('1'); $result = $query->range(0, 1) ->execute() diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php new file mode 100644 index 0000000..fda7d13 --- /dev/null +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php @@ -0,0 +1,40 @@ +connection = $connection; + } + + /** + * Constructs a new cache database backend for a given bin name. + * + * @param string $bin + * The cache bin for which a cache backend object should be returned. + * + * @return Drupal\Core\Cache\CacheBackendInterface + * The cache backend object associated with the specified bin. + */ + public function get($bin) { + return new DatabaseBackend($bin, $this->connection); + } +}