diff --git a/core/core.services.yml b/core/core.services.yml index e40ef9e3538cc7fd25749573cb0d7c5645f7147e..a98b28b5d464e5376de5c6e37edfb977d73a8179 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -124,6 +124,7 @@ services: class: Drupal\Core\PageCache\ChainResponsePolicy tags: - { name: service_collector, tag: page_cache_response_policy, call: addPolicy} + lazy: true page_cache_kill_switch: class: Drupal\Core\PageCache\ResponsePolicy\KillSwitch tags: @@ -455,7 +456,7 @@ services: - { name: http_middleware, priority: 300 } http_middleware.page_cache: class: Drupal\Core\StackMiddleware\PageCache - arguments: ['@kernel'] + arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy', '@content_negotiation'] tags: - { name: http_middleware, priority: 200 } http_middleware.kernel_pre_handle: diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index ff20f28fba076425b37ed23a57bad7fc7b779aac..6fae299bf1d0ea4d4cabb63a6d4fe4cfbe818b7e 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -68,25 +68,18 @@ const DRUPAL_BOOTSTRAP_KERNEL = 1; /** - * Third bootstrap phase: try to serve a cached page. + * Third bootstrap phase: load code for subsystems and modules. * * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. */ -const DRUPAL_BOOTSTRAP_PAGE_CACHE = 2; - -/** - * Fourth bootstrap phase: load code for subsystems and modules. - * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - */ -const DRUPAL_BOOTSTRAP_CODE = 3; +const DRUPAL_BOOTSTRAP_CODE = 2; /** * Final bootstrap phase: initialize language, path, theme, and modules. * * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. */ -const DRUPAL_BOOTSTRAP_FULL = 4; +const DRUPAL_BOOTSTRAP_FULL = 3; /** * Role ID for anonymous users; should match what's in the "role" table. @@ -310,39 +303,6 @@ function drupal_get_path($type, $name) { return dirname(drupal_get_filename($type, $name)); } -/** - * Gets the page cache cid for this request. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request for this page. - * - * @return string - * The cid for this request. - */ -function drupal_page_cache_get_cid(Request $request) { - $cid_parts = array( - $request->getUri(), - \Drupal::service('content_negotiation')->getContentType($request), - ); - return implode(':', $cid_parts); -} - -/** - * Retrieves the current page from the cache. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request for this page. - * - * @return \Symfony\Component\HttpFoundation\Response - * The response, if the page was found in the cache, NULL otherwise. - */ -function drupal_page_get_cache(Request $request) { - $cache = \Drupal::cache('render')->get(drupal_page_cache_get_cid($request)); - if ($cache) { - return $cache->data; - } -} - /** * Sets an HTTP response header for the current page. * @@ -426,72 +386,6 @@ function _drupal_set_preferred_header_name($name = NULL) { $header_names[strtolower($name)] = $name; } -/** - * Sets HTTP headers in preparation for a cached page response. - * - * The headers allow as much as possible in proxies and browsers without any - * particular knowledge about the pages. Modules can override these headers - * using _drupal_add_http_header(). - * - * If the request is conditional (using If-Modified-Since and If-None-Match), - * and the conditions match those currently in the cache, a 304 Not Modified - * response is sent. - */ -function drupal_serve_page_from_cache(Response $response, Request $request) { - // Only allow caching in the browser and prevent that the response is stored - // by an external proxy server when the following conditions apply: - // 1. There is a session cookie on the request. - // 2. The Vary: Cookie header is on the response. - // 3. The Cache-Control header does not contain the no-cache directive. - if ($request->cookies->has(session_name()) && - in_array('Cookie', $response->getVary()) && - !$response->headers->hasCacheControlDirective('no-cache')) { - - $response->setPrivate(); - } - - // Negotiate whether to use compression. - if ($response->headers->get('Content-Encoding') == 'gzip' && extension_loaded('zlib')) { - if (strpos($request->headers->get('Accept-Encoding'), 'gzip') !== FALSE) { - // The response content is already gzip'ed, so make sure - // zlib.output_compression does not compress it once more. - ini_set('zlib.output_compression', '0'); - } - else { - // The client does not support compression. Decompress the content and - // remove the Content-Encoding header. - $content = $response->getContent(); - $content = gzinflate(substr(substr($content, 10), 0, -8)); - $response->setContent($content); - $response->headers->remove('Content-Encoding'); - } - } - - // Perform HTTP revalidation. - // @todo Use Response::isNotModified() as per https://drupal.org/node/2259489 - $last_modified = $response->getLastModified(); - if ($last_modified) { - // See if the client has provided the required HTTP headers. - $if_modified_since = $request->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime($request->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE; - $if_none_match = $request->server->has('HTTP_IF_NONE_MATCH') ? stripslashes($request->server->get('HTTP_IF_NONE_MATCH')) : FALSE; - - if ($if_modified_since && $if_none_match - && $if_none_match == $response->getEtag() // etag must match - && $if_modified_since == $last_modified->getTimestamp()) { // if-modified-since must match - $response->setStatusCode(304); - $response->setContent(NULL); - - // In the case of a 304 response, certain headers must be sent, and the - // remaining may not (see RFC 2616, section 10.3.5). - foreach (array_keys($response->headers->all()) as $name) { - if (!in_array($name, array('content-location', 'expires', 'cache-control', 'vary'))) { - $response->headers->remove($name); - } - } - } - } -} - /** * Translates a string to the current language or to a given language. * @@ -830,10 +724,6 @@ function drupal_bootstrap($phase = NULL) { $kernel->boot(); break; - case DRUPAL_BOOTSTRAP_PAGE_CACHE: - $kernel->handlePageCache($request); - break; - case DRUPAL_BOOTSTRAP_CODE: case DRUPAL_BOOTSTRAP_FULL: $kernel->prepareLegacyRequest($request); diff --git a/core/includes/common.inc b/core/includes/common.inc index 27c9c540d0b5414c09681cc092d9e27fdc1822c1..bfcbce6361fa0be506b74e4bfa13a340ea525fce 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1267,48 +1267,6 @@ function drupal_clear_js_cache() { \Drupal::service('asset.js.collection_optimizer')->deleteAll(); } -/** - * Stores the current page in the cache. - * - * If page_compression is enabled, a gzipped version of the page is stored in - * the cache to avoid compressing the output on each request. The cache entry - * is unzipped in the relatively rare event that the page is requested by a - * client without gzip support. - * - * Page compression requires the PHP zlib extension - * (http://php.net/manual/ref.zlib.php). - * - * @param \Symfony\Component\HttpFoundation\Response $response - * The fully populated response. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request for this page. - */ -function drupal_page_set_cache(Response $response, Request $request) { - // Check if the current page may be compressed. - if (extension_loaded('zlib') && !$response->headers->get('Content-Encoding') && - \Drupal::config('system.performance')->get('response.gzip')) { - - $content = $response->getContent(); - if ($content) { - $response->setContent(gzencode($content, 9, FORCE_GZIP)); - $response->headers->set('Content-Encoding', 'gzip'); - } - - // When page compression is enabled, ensure that proxy caches will record - // and deliver different versions of a page depending on whether the - // client supports gzip or not. - $response->setVary('Accept-Encoding', FALSE); - } - - // Use the actual timestamp from an Expires header, if available. - $date = $response->getExpires(); - $expire = ($date > (new DateTime())) ? $date->getTimestamp() : Cache::PERMANENT; - - $cid = drupal_page_cache_get_cid($request); - $tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags')); - \Drupal::cache('render')->set($cid, $response, $expire, $tags); -} - /** * Pre-render callback: Renders a link into #markup. * diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index d722d6b2db0b34f56ef382f086fc492b8d91a3be..8ddeb1759e66703d14f87074881711018e667dba 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -76,6 +76,13 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { */ protected $booted = FALSE; + /** + * Whether essential services have been set up properly by preHandle(). + * + * @var bool + */ + protected $prepared = FALSE; + /** * Holds the list of enabled modules. * @@ -474,42 +481,8 @@ public function preHandle(Request $request) { // Override of Symfony's mime type guesser singleton. MimeTypeGuesser::registerWithSymfonyGuesser($this->container); - } - - /** - * {@inheritdoc} - * - * @todo Invoke proper request/response/terminate events. - */ - public function handlePageCache(Request $request) { - $this->boot(); - - // Check for a cache mode force from settings.php. - if (Settings::get('page_cache_without_database')) { - $cache_enabled = TRUE; - } - else { - $config = $this->getContainer()->get('config.factory')->get('system.performance'); - $cache_enabled = $config->get('cache.page.use_internal'); - } - - $request_policy = \Drupal::service('page_cache_request_policy'); - if ($cache_enabled && $request_policy->check($request) === RequestPolicyInterface::ALLOW) { - // Get the page from the cache. - $response = drupal_page_get_cache($request); - // If there is a cached page, display it. - if ($response) { - $response->headers->set('X-Drupal-Cache', 'HIT'); - drupal_serve_page_from_cache($response, $request); - - // We are done. - $response->prepare($request); - $response->send(); - exit; - } - } - return $this; + $this->prepared = TRUE; } /** @@ -577,7 +550,9 @@ public function getServiceProviders($origin) { * {@inheritdoc} */ public function terminate(Request $request, Response $response) { - if (FALSE === $this->booted) { + // Only run terminate() when essential services have been set up properly + // by preHandle() before. + if (FALSE === $this->prepared) { return; } diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php index 0ba61dee2dfcfa9694ac8952d056befd3f569e6e..ab17b77ff09d491d09252cdf2b3698e2fe98e219 100644 --- a/core/lib/Drupal/Core/DrupalKernelInterface.php +++ b/core/lib/Drupal/Core/DrupalKernelInterface.php @@ -93,16 +93,6 @@ public function getAppRoot(); */ public function updateModules(array $module_list, array $module_filenames = array()); - /** - * Attempts to serve a page from the cache. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - * - * @return $this - */ - public function handlePageCache(Request $request); - /** * Prepare the kernel for handling a request without handling the request. * diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 9634161bcb1176c8547099038f433ea6252cda4b..3c8bdf2f3461081825ccb5dd97e4e63bedfae566 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -136,17 +136,6 @@ public function onRespond(FilterResponseEvent $event) { // header declaring the response as not cacheable. $this->setResponseNotCacheable($response, $request); } - - // Currently it is not possible to cache some types of responses. Therefore - // exclude binary file responses (generated files, e.g. images with image - // styles) and streamed responses (files directly read from the disk). - // see: https://github.com/symfony/symfony/issues/9128#issuecomment-25088678 - if ($is_cacheable && $this->config->get('cache.page.use_internal') && !($response instanceof BinaryFileResponse) && !($response instanceof StreamedResponse)) { - // Store the response in the internal page cache. - drupal_page_set_cache($response, $request); - $response->headers->set('X-Drupal-Cache', 'MISS'); - drupal_serve_page_from_cache($response, $request); - } } /** diff --git a/core/lib/Drupal/Core/StackMiddleware/PageCache.php b/core/lib/Drupal/Core/StackMiddleware/PageCache.php index ba59e936f48e0e86966bd23ce33eabb028ef93f0..b381018f49d751d89d54020933a2a84488e588cd 100644 --- a/core/lib/Drupal/Core/StackMiddleware/PageCache.php +++ b/core/lib/Drupal/Core/StackMiddleware/PageCache.php @@ -7,8 +7,16 @@ namespace Drupal\Core\StackMiddleware; -use Drupal\Core\DrupalKernelInterface; +use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\ContentNegotiation; +use Drupal\Core\PageCache\RequestPolicyInterface; +use Drupal\Core\PageCache\ResponsePolicyInterface; +use Drupal\Core\Site\Settings; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\HttpKernelInterface; /** @@ -24,32 +32,321 @@ class PageCache implements HttpKernelInterface { protected $httpKernel; /** - * The main Drupal kernel. + * The cache bin. * - * @var \Drupal\Core\DrupalKernelInterface + * @var \Drupal\Core\Cache\CacheBackendInterface. */ - protected $drupalKernel; + protected $cache; + + /** + * A policy rule determining the cacheability of a request. + * + * @var \Drupal\Core\PageCache\RequestPolicyInterface + */ + protected $requestPolicy; + + /** + * A policy rule determining the cacheability of the response. + * + * @var \Drupal\Core\PageCache\ResponsePolicyInterface + */ + protected $responsePolicy; + + /** + * The content negotiation library. + * + * @var \Drupal\Core\ContentNegotiation + */ + protected $contentNegotiation; /** * Constructs a ReverseProxyMiddleware object. * * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel * The decorated kernel. - * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel - * The main Drupal kernel. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache + * The cache bin. + * @param \Drupal\Core\PageCache\RequestPolicyInterface $request_policy + * A policy rule determining the cacheability of a request. + * @param \Drupal\Core\PageCache\ResponsePolicyInterface $response_policy + * A policy rule determining the cacheability of the response. + * @param \Drupal\Core\ContentNegotiation $content_negotiation + * The content negotiation library. */ - public function __construct(HttpKernelInterface $http_kernel, DrupalKernelInterface $drupal_kernel) { + public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy, ContentNegotiation $content_negotiation) { $this->httpKernel = $http_kernel; - $this->drupalKernel = $drupal_kernel; + $this->cache = $cache; + $this->requestPolicy = $request_policy; + $this->responsePolicy = $response_policy; + $this->contentNegotiation = $content_negotiation; } /** * {@inheritdoc} */ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { - $this->drupalKernel->handlePageCache($request); + if ($type !== static::MASTER_REQUEST) { + // Only allow page caching on master request. + $cache_enabled = FALSE; + } + elseif (Settings::get('page_cache_without_database')) { + // Check for a cache mode force from settings.php. + $cache_enabled = TRUE; + } + else { + $config = $this->config('system.performance'); + $cache_enabled = $config->get('cache.page.use_internal'); + } + if ($cache_enabled && $this->requestPolicy->check($request) === RequestPolicyInterface::ALLOW) { + $response = $this->lookup($request, $type, $catch); + } + else { + $response = $this->pass($request, $type, $catch); + } + + return $response; + } + + /** + * Sidesteps the page cache and directly forwards a request to the backend. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * @param int $type + * The type of the request (one of HttpKernelInterface::MASTER_REQUEST or + * HttpKernelInterface::SUB_REQUEST) + * @param bool $catch + * Whether to catch exceptions or not + * + * @returns \Symfony\Component\HttpFoundation\Response $response + * A response object. + */ + protected function pass(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { return $this->httpKernel->handle($request, $type, $catch); } + /** + * Retrieves a response from the cache or fetches it from the backend. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * @param int $type + * The type of the request (one of HttpKernelInterface::MASTER_REQUEST or + * HttpKernelInterface::SUB_REQUEST) + * @param bool $catch + * Whether to catch exceptions or not + * + * @returns \Symfony\Component\HttpFoundation\Response $response + * A response object. + */ + protected function lookup(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { + if ($response = $this->get($request)) { + $response->headers->set('X-Drupal-Cache', 'HIT'); + } + else { + $response = $this->fetch($request, $type, $catch); + } + + // Only allow caching in the browser and prevent that the response is stored + // by an external proxy server when the following conditions apply: + // 1. There is a session cookie on the request. + // 2. The Vary: Cookie header is on the response. + // 3. The Cache-Control header does not contain the no-cache directive. + if ($request->cookies->has(session_name()) && + in_array('Cookie', $response->getVary()) && + !$response->headers->hasCacheControlDirective('no-cache')) { + + $response->setPrivate(); + } + + // Negotiate whether to use compression. + if (extension_loaded('zlib') && $response->headers->get('Content-Encoding') === 'gzip') { + if (strpos($request->headers->get('Accept-Encoding'), 'gzip') !== FALSE) { + // The response content is already gzip'ed, so make sure + // zlib.output_compression does not compress it once more. + ini_set('zlib.output_compression', '0'); + } + else { + // The client does not support compression. Decompress the content and + // remove the Content-Encoding header. + $content = $response->getContent(); + $content = gzinflate(substr(substr($content, 10), 0, -8)); + $response->setContent($content); + $response->headers->remove('Content-Encoding'); + } + } + + // Perform HTTP revalidation. + // @todo Use Response::isNotModified() as per https://drupal.org/node/2259489 + $last_modified = $response->getLastModified(); + if ($last_modified) { + // See if the client has provided the required HTTP headers. + $if_modified_since = $request->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime($request->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE; + $if_none_match = $request->server->has('HTTP_IF_NONE_MATCH') ? stripslashes($request->server->get('HTTP_IF_NONE_MATCH')) : FALSE; + + if ($if_modified_since && $if_none_match + && $if_none_match == $response->getEtag() // etag must match + && $if_modified_since == $last_modified->getTimestamp()) { // if-modified-since must match + $response->setStatusCode(304); + $response->setContent(NULL); + + // In the case of a 304 response, certain headers must be sent, and the + // remaining may not (see RFC 2616, section 10.3.5). + foreach (array_keys($response->headers->all()) as $name) { + if (!in_array($name, array('content-location', 'expires', 'cache-control', 'vary'))) { + $response->headers->remove($name); + } + } + } + } + + return $response; + } + + /** + * Fetches a response from the backend and stores it in the cache. + * + * If page_compression is enabled, a gzipped version of the page is stored in + * the cache to avoid compressing the output on each request. The cache entry + * is unzipped in the relatively rare event that the page is requested by a + * client without gzip support. + * + * Page compression requires the PHP zlib extension + * (http://php.net/manual/ref.zlib.php). + * + * @see drupal_page_header() + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * @param int $type + * The type of the request (one of HttpKernelInterface::MASTER_REQUEST or + * HttpKernelInterface::SUB_REQUEST) + * @param bool $catch + * Whether to catch exceptions or not + * + * @returns \Symfony\Component\HttpFoundation\Response $response + * A response object. + */ + protected function fetch(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { + $response = $this->httpKernel->handle($request, $type, $catch); + + // Currently it is not possible to cache some types of responses. Therefore + // exclude binary file responses (generated files, e.g. images with image + // styles) and streamed responses (files directly read from the disk). + // see: https://github.com/symfony/symfony/issues/9128#issuecomment-25088678 + if ($response instanceof BinaryFileResponse || $response instanceof StreamedResponse) { + return $response; + } + + if ($this->responsePolicy->check($response, $request) === ResponsePolicyInterface::DENY) { + return $response; + } + + // Check if the current page may be compressed. + if (extension_loaded('zlib') && !$response->headers->get('Content-Encoding') && $this->config('system.performance')->get('response.gzip')) { + $content = $response->getContent(); + if ($content) { + $response->setContent(gzencode($content, 9, FORCE_GZIP)); + $response->headers->set('Content-Encoding', 'gzip'); + } + + // When page compression is enabled, ensure that proxy caches will record + // and deliver different versions of a page depending on whether the + // client supports gzip or not. + $response->setVary('Accept-Encoding', FALSE); + } + + // Use the actual timestamp from an Expires header, if available. + $date = $response->getExpires(); + $expire = ($date > (new \DateTime())) ? $date->getTimestamp() : Cache::PERMANENT; + + $tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags')); + $this->set($request, $response, $expire, $tags); + + // Mark response as a cache miss. + $response->headers->set('X-Drupal-Cache', 'MISS'); + + return $response; + } + + /** + * Returns a response object from the page cache. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * @param bool $allow_invalid + * (optional) If TRUE, a cache item may be returned even if it is expired or + * has been invalidated. Such items may sometimes be preferred, if the + * alternative is recalculating the value stored in the cache, especially + * if another concurrent request is already recalculating the same value. + * The "valid" property of the returned object indicates whether the item is + * valid or not. Defaults to FALSE. + * + * @return \Symfony\Component\HttpFoundation\Response|false + * The cached response or FALSE on failure. + */ + protected function get(Request $request, $allow_invalid = FALSE) { + $cid = $this->getCacheId($request); + if ($cache = $this->cache->get($cid, $allow_invalid)) { + return $cache->data; + } + } + + /** + * Stores a response object in the page cache. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * @param \Symfony\Component\HttpFoundation\Response $response + * The response to store in the cache. + * @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 array('node' => array(123), 'user' => array(92)). + */ + protected function set(Request $request, Response $response, $expire, array $tags) { + $cid = $this->getCacheId($request); + $this->cache->set($cid, $response, $expire, $tags); + } + + /** + * Gets the page cache ID for this request. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * A request object. + * + * @return string + * The cache ID for this request. + */ + protected function getCacheId(Request $request) { + $cid_parts = array( + $request->getUri(), + $this->contentNegotiation->getContentType($request), + ); + return implode(':', $cid_parts); + } + + /** + * Wraps Drupal::config(). + * + * Config factory is not injected into this class in order to prevent + * premature initialization of config storage (database). + * + * @see \Drupal::config() + */ + protected function config($name) { + return \Drupal::config($name); + } + } diff --git a/core/modules/system/src/Tests/DrupalKernel/ServiceDestructionTest.php b/core/modules/system/src/Tests/DrupalKernel/ServiceDestructionTest.php index 4fdc9b7b4d05c7791c8dedf57014e3bc77c360fe..68e28a2e8501bbc8436af8ab1b872b32bc52d30d 100644 --- a/core/modules/system/src/Tests/DrupalKernel/ServiceDestructionTest.php +++ b/core/modules/system/src/Tests/DrupalKernel/ServiceDestructionTest.php @@ -25,13 +25,18 @@ public function testDestructionUsed() { // Enable the test module to add it to the container. $this->enableModules(array('service_provider_test')); + $request = $this->container->get('request_stack')->getCurrentRequest(); + $kernel = $this->container->get('kernel'); + $kernel->preHandle($request); + // The service has not been destructed yet. $this->assertNull(\Drupal::state()->get('service_provider_test.destructed')); // Call the class and then terminate the kernel $this->container->get('service_provider_test_class'); + $response = new Response(); - $this->container->get('kernel')->terminate($this->container->get('request_stack')->getCurrentRequest(), $response); + $kernel->terminate($request, $response); $this->assertTrue(\Drupal::state()->get('service_provider_test.destructed')); } @@ -42,13 +47,17 @@ public function testDestructionUnused() { // Enable the test module to add it to the container. $this->enableModules(array('service_provider_test')); + $request = $this->container->get('request_stack')->getCurrentRequest(); + $kernel = $this->container->get('kernel'); + $kernel->preHandle($request); + // The service has not been destructed yet. $this->assertNull(\Drupal::state()->get('service_provider_test.destructed')); // Terminate the kernel. The test class has not been called, so it should not // be destructed. $response = new Response(); - $this->container->get('kernel')->terminate($this->container->get('request_stack')->getCurrentRequest(), $response); + $kernel->terminate($request, $response); $this->assertNull(\Drupal::state()->get('service_provider_test.destructed')); } } diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php index 33869799e316b1e398610774723187c985be3702..8c7d556be39f8d19091ca21d08643502bf680302 100644 --- a/core/modules/system/tests/http.php +++ b/core/modules/system/tests/http.php @@ -26,7 +26,6 @@ $request = Request::createFromGlobals(); $kernel = TestKernel::createFromRequest($request, $autoloader, 'testing', TRUE); $response = $kernel - ->handlePageCache($request) ->handle($request) // Handle the response object. ->prepare($request)->send(); diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index 00a6b13d6155ee7bb55e0f4fe841913ded4329bd..702184df62702cfea5a354976b798916327d8d6e 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -28,7 +28,6 @@ $request = Request::createFromGlobals(); $kernel = TestKernel::createFromRequest($request, $autoloader, 'testing', TRUE); $response = $kernel - ->handlePageCache($request) ->handle($request) // Handle the response object. ->prepare($request)->send();