Verified Commit 7a031e39 authored by godotislate's avatar godotislate
Browse files

refactor: #2538970 Improve the speed of \Drupal\Core\Theme\ThemeAccessCheck

By: dawehner
By: joelpittet
By: claudiu.cristea
By: wim leers
By: catch
By: longwave
By: godotislate
By: berdir
parent 317a6474
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1408,7 +1408,7 @@ services:
      - { name: access_check, applies_to: _entity_delete_multiple_access }
  access_check.theme:
    class: Drupal\Core\Theme\ThemeAccessCheck
    arguments: ['@theme_handler']
    arguments: ['%container.themes%']
    tags:
      - { name: access_check, applies_to: _access_theme }
  access_check.custom:
+8 −14
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
namespace Drupal\Core\Theme;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Routing\Access\AccessInterface;

/**
@@ -11,21 +10,17 @@
 */
class ThemeAccessCheck implements AccessInterface {

  /**
   * The theme handler.
   *
   * @var \Drupal\Core\Extension\ThemeHandlerInterface
   */
  protected $themeHandler;

  /**
   * Constructs a \Drupal\Core\Theme\Registry object.
   *
   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
   *   The theme handler.
   * @param array $themes
   *   Theme information from the container parameter.
   */
  public function __construct(ThemeHandlerInterface $theme_handler) {
    $this->themeHandler = $theme_handler;
  public function __construct(protected $themes) {
    if (!is_array($themes)) {
      @trigger_error('Passing ThemeHandlerInterface to ' . __METHOD__ . ' is deprecated in drupal::11.4.0 and is removed from drupal:12.0.0. Pass theme info from the "container.themes" container parameter instead. See https://www.drupal.org/project/drupal/issues/2538970');
      $this->themes = \Drupal::getContainer()->getParameter('container.themes');
    }
  }

  /**
@@ -52,8 +47,7 @@ public function access($theme) {
   *   TRUE if the theme is installed, FALSE otherwise.
   */
  public function checkAccess($theme) {
    $themes = $this->themeHandler->listInfo();
    return !empty($themes[$theme]->status);
    return isset($this->themes[$theme]);
  }

}
+9 −9
Original line number Diff line number Diff line
@@ -90,11 +90,11 @@ public function testGetIndividual(): void {

    $expected = [
      'QueryCount' => 26,
      'CacheGetCount' => 43,
      'CacheGetCount' => 41,
      'CacheGetCountByBin' => [
        'config' => 8,
        'config' => 7,
        'data' => 8,
        'bootstrap' => 6,
        'bootstrap' => 5,
        'discovery' => 13,
        'entity' => 2,
        'default' => 4,
@@ -148,12 +148,12 @@ public function testGetIndividual(): void {

    $expected = [
      'QueryCount' => 4,
      'CacheGetCount' => 20,
      'CacheGetCount' => 18,
      'CacheGetCountByBin' => [
        'config' => 6,
        'config' => 5,
        'data' => 1,
        'discovery' => 5,
        'bootstrap' => 4,
        'bootstrap' => 3,
        'entity' => 1,
        'default' => 1,
        'dynamic_page_cache' => 2,
@@ -211,12 +211,12 @@ public function testGetIndividual(): void {

    $expected = [
      'QueryCount' => 15,
      'CacheGetCount' => 44,
      'CacheGetCount' => 42,
      'CacheGetCountByBin' => [
        'config' => 8,
        'config' => 7,
        'data' => 8,
        'discovery' => 13,
        'bootstrap' => 5,
        'bootstrap' => 4,
        'entity' => 2,
        'default' => 4,
        'dynamic_page_cache' => 2,
+12 −0
Original line number Diff line number Diff line
@@ -73,6 +73,18 @@ public function installAdmin($theme) {
  private function installTheme($theme, $default_or_admin): array {
    assert(in_array($default_or_admin, ['default', 'admin']), 'The $default_or_admin parameter must be `default` or `admin`');
    $config = $this->configFactory->getEditable('system.theme');

    // The ThemeAccess event listener is constructed alongside all access checks
    // prior to this method being called, and is injected into classes which
    // indirectly call this method. This means that the list of themes in the
    // container is not available to the access check when determining the
    // active theme immediately after installing a theme and setting it as the
    // admin theme. This issue only happens when installing a theme and
    // attempting to render via that theme during the same request, so
    // work around it by triggering theme negotiation prior to installing
    // the new theme.
    $route_match = \Drupal::routeMatch();
    \Drupal::service('theme.manager')->getActiveTheme($route_match);
    $this->themeInstaller->install([$theme]);
    $config->set($default_or_admin, $theme)->save();
    return [
+2 −2
Original line number Diff line number Diff line
@@ -421,7 +421,7 @@ protected function testLogin(): void {
      'StylesheetBytes' => 1429,
      'StylesheetCount' => 1,
      'QueryCount' => 17,
      'CacheGetCount' => 74,
      'CacheGetCount' => 72,
      'CacheSetCount' => 1,
      'CacheDeleteCount' => 1,
      'CacheTagInvalidationCount' => 0,
@@ -513,7 +513,7 @@ protected function testLoginBlock(): void {
    $this->assertSame($expected_queries, $recorded_queries);
    $expected = [
      'QueryCount' => 17,
      'CacheGetCount' => 101,
      'CacheGetCount' => 99,
      'CacheSetCount' => 1,
      'CacheDeleteCount' => 1,
      'CacheTagInvalidationCount' => 0,