Wie kann ich das aktive Thema programmgesteuert ändern?

20

Wie kann ich das aktive Drupal 8-Thema programmgesteuert ändern?

In Drupal 6 haben wir den folgenden Code verwendet.

global $custom_theme;
$custom_theme = 'garland';

In Drupal 7 haben wir verwendet hook_custom_theme().

Was ist in Drupal 8 der richtige Weg, um dies zu tun?

visabhishek
quelle

Antworten:

22

In Drupal 8 verwenden Sie Themenunterhändler , bei denen es sich im Wesentlichen um Dienste handelt, die ein bestimmtes Tag verwenden. Sehen Sie sich die von Drupal implementierten Themenunterhändler an, um genau zu verstehen, wie sie funktionieren. Das im Änderungsprotokoll angegebene Beispiel wird nicht aktualisiert.

user.services.yml

  theme.negotiator.admin_theme:
    class: Drupal\user\Theme\AdminNegotiator
    arguments: ['@current_user', '@config.factory', '@entity.manager', '@router.admin_context']
    tags:
      - { name: theme_negotiator, priority: -40 }

AdminNegotiator.php

namespace Drupal\user\Theme;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Theme\ThemeNegotiatorInterface;

/**
 * Sets the active theme on admin pages.
 */
class AdminNegotiator implements ThemeNegotiatorInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $user;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityManagerInterface
   */
  protected $entityManager;

  /**
   * The route admin context to determine whether a route is an admin one.
   *
   * @var \Drupal\Core\Routing\AdminContext
   */
  protected $adminContext;

  /**
   * Creates a new AdminNegotiator instance.
   *
   * @param \Drupal\Core\Session\AccountInterface $user
   *   The current user.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   *   The entity manager.
   * @param \Drupal\Core\Routing\AdminContext $admin_context
   *   The route admin context to determine whether the route is an admin one.
   */
  public function __construct(AccountInterface $user, ConfigFactoryInterface $config_factory, EntityManagerInterface $entity_manager, AdminContext $admin_context) {
    $this->user = $user;
    $this->configFactory = $config_factory;
    $this->entityManager = $entity_manager;
    $this->adminContext = $admin_context;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    return ($this->entityManager->hasHandler('user_role', 'storage') && $this->user->hasPermission('view the administration theme') && $this->adminContext->isAdminRoute($route_match->getRouteObject()));
  }

  /**
   * {@inheritdoc}
   */
  public function determineActiveTheme(RouteMatchInterface $route_match) {
    return $this->configFactory->get('system.theme')->get('admin');
  }

}

Der Code ist ziemlich einfach zu verstehen: Die applies()Methode gibt zurück, TRUEwenn die aktuelle Route die Route ist, für die Ihr Modul das Thema ändern möchte. Die determineActiveTheme()Methode gibt den Namen des Themencomputers des anzuwendenden Themas zurück.

Siehe auch ThemeNegotiator :: detectActiveTheme () sollte nicht erfordern, dass ein RouteMatch übergeben wird, um die Argumente zu ändern, die von den von den Theme-Verhandlern verwendeten Methoden erhalten wurden. Wenn dieser Patch angewendet wird, müssen Sie auch Ihren Code für den Themen-Unterhändler ändern.

kiamlaluno
quelle
Sollte nicht apply () so geschrieben werden, wie dies im obigen Beispiel der Fall ist ($ route_match)? Habe die gleiche Frage auf der verlinkten Do-Seite gepostet. Vielen Dank!
Stefanos Petrakis
@StefanosPetrakis Hmmm ... Jede aktuelle Implementierung erhält das als Parameter, im Gegensatz zu dem, was in diesem Änderungsdatensatz steht.
kiamlaluno
Ich habe die Antwort mit dem Code aktualisiert, den Drupal Core tatsächlich in einem seiner Themenunterhändler verwendet.
kiamlaluno