diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php index 5adfb30718..3cbd920be9 100644 --- a/core/lib/Drupal/Core/Cache/CacheFactory.php +++ b/core/lib/Drupal/Core/Cache/CacheFactory.php @@ -65,7 +65,7 @@ public function __construct(Settings $settings, array $default_bin_backends = [] public function get($bin) { $cache_settings = $this->settings->get('cache'); // First, look for a cache bin specific setting. - if (isset($cache_settings['bins'][$bin])) { + if (isset($cache_settings['bins'][$bin]) && $this->container->has($cache_settings['bins'][$bin])) { $service_name = $cache_settings['bins'][$bin]; } // Second, use the default backend specified by the cache bin. @@ -73,7 +73,7 @@ public function get($bin) { $service_name = $this->defaultBinBackends[$bin]; } // Third, use configured default backend. - elseif (isset($cache_settings['default'])) { + elseif (isset($cache_settings['default']) && $this->container->has($cache_settings['default'])) { $service_name = $cache_settings['default']; } else { diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php index b04ee5c55c..e6d7775332 100644 --- a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php +++ b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php @@ -66,6 +66,17 @@ public function __construct(Settings $settings = NULL, $consistent_service_name } } + /** + * Getter for the consistent service name. + * + * @return string + * The service name of the consistent backend factory. + */ + public function getConsistentServiceName() { + return ($this->consistentServiceName && $this->container->has($this->consistentServiceName)) ? + $this->consistentServiceName : 'cache.backend.database'; + } + /** * Instantiates a chained, fast cache backend class for a given cache bin. * @@ -80,13 +91,13 @@ public function get($bin) { // otherwise, just return the consistent backend directly. if (isset($this->fastServiceName)) { return new ChainedFastBackend( - $this->container->get($this->consistentServiceName)->get($bin), + $this->container->get($this->getConsistentServiceName)->get($bin), $this->container->get($this->fastServiceName)->get($bin), $bin ); } else { - return $this->container->get($this->consistentServiceName)->get($bin); + return $this->container->get($this->getConsistentServiceName)->get($bin); } } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 97b8dd04d1..d882c37a64 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -301,7 +301,7 @@ function system_requirements($phase) { $requirements['php_extensions']['value'] = t('Enabled'); } - if ($phase == 'install' || $phase == 'runtime') { + if ($phase === 'install' || $phase === 'runtime') { // Check to see if OPcache is installed. if (!OpCodeCache::isEnabled()) { $requirements['php_opcache'] = [ @@ -316,6 +316,33 @@ function system_requirements($phase) { $requirements['php_opcache']['title'] = t('PHP OPcode caching'); } + if ($phase === 'install' || $phase === 'runtime') { + // Check that the required cache backends exist. + $cache_settings = Settings::get('cache'); + $missing_cache_backends = []; + if (isset($cache_settings['bins'])) { + foreach ($cache_settings['bins'] as $bin => $backend) { + if (!Drupal::getContainer()->has($cache_settings['bins'][$bin])) { + $missing_cache_backends[] = $cache_settings['bins'][$bin]; + } + } + } + if (isset($cache_settings['default']) && !Drupal::getContainer()->has($cache_settings['default'])) { + $missing_cache_backends[] = $cache_settings['default']; + } + if ($missing_cache_backends) { + $requirements['cache_backend'] = [ + 'title' => t('Cache Backend'), + 'value' => t('Missing'), + 'severity' => REQUIREMENT_WARNING, + 'description' => new PluralTranslatableMarkup(count($missing_cache_backends), + 'The configured Cache Backend %backend is not available.', + 'The configured Cache Backends %backend are not available.', + ['%backend' => implode(', ', $missing_cache_backends)]), + ]; + } + } + // Check to see if APCu is installed and configured correctly. if ($phase == 'runtime' && PHP_SAPI != 'cli') { $requirements['php_apcu']['title'] = t('PHP APCu caching'); diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php index 40dcd82657..e70000e974 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php @@ -145,4 +145,66 @@ public function testCacheFactoryWithSpecifiedPerBinBackend() { $this->assertSame($render_bin, $actual_bin); } + /** + * Tests cache factory that specified bin service does not exist. + * + * @covers ::__construct + * @covers ::get + */ + public function testCacheFactoryBinBackendServiceExist() { + $settings = new Settings([ + 'cache' => [ + 'bins' => [ + 'render' => 'cache.backend.custom', + ], + ], + ]); + $cache_factory = new CacheFactory($settings); + + $container = new ContainerBuilder(); + $cache_factory->setContainer($container); + + $builtin_default_backend_factory = $this->createMock('\Drupal\Core\Cache\CacheFactoryInterface'); + $container->set('cache.backend.database', $builtin_default_backend_factory); + + $render_bin = $this->createMock('\Drupal\Core\Cache\CacheBackendInterface'); + $builtin_default_backend_factory->expects($this->once()) + ->method('get') + ->with('render') + ->will($this->returnValue($render_bin)); + + $actual_bin = $cache_factory->get('render'); + $this->assertSame($render_bin, $actual_bin); + } + + /** + * Tests cache factory that specified default bin service does not exist. + * + * @covers ::__construct + * @covers ::get + */ + public function testCacheFactoryBinBackendDefaultServiceExist() { + $settings = new Settings([ + 'cache' => [ + 'default' => 'cache.backend.custom', + ], + ]); + $cache_factory = new CacheFactory($settings); + + $container = new ContainerBuilder(); + $cache_factory->setContainer($container); + + $builtin_default_backend_factory = $this->createMock('\Drupal\Core\Cache\CacheFactoryInterface'); + $container->set('cache.backend.database', $builtin_default_backend_factory); + + $render_bin = $this->createMock('\Drupal\Core\Cache\CacheBackendInterface'); + $builtin_default_backend_factory->expects($this->once()) + ->method('get') + ->with('render') + ->will($this->returnValue($render_bin)); + + $actual_bin = $cache_factory->get('render'); + $this->assertSame($render_bin, $actual_bin); + } + }