프로그래밍 방식으로 활성 테마를 어떻게 변경할 수 있습니까?


20

활성 Drupal 8 테마를 프로그래밍 방식으로 변경하려면 어떻게해야합니까?

Drupal 6에서는 다음 코드를 사용했습니다.

global $custom_theme;
$custom_theme = 'garland';

Drupal 7에서는을 사용했습니다 hook_custom_theme().

Drupal 8에서이를 수행하는 올바른 방법은 무엇입니까?

답변:


22

Drupal 8에서는 기본적으로 특정 태그를 사용하는 서비스 인 테마 협상자를 사용합니다. 그들이 어떻게 작동하는지 정확하게 이해하기 위해 Drupal이 구현 한 테마 협상자를보십시오. 변경 레코드에 제공된 예제는 업데이트되지 않습니다.

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');
  }

}

코드는 이해하기 매우 쉽습니다 . 현재 경로가 모듈이 테마를 변경하려는 경로 일 때이 applies()메서드가 반환 TRUE됩니다. 이 determineActiveTheme()메소드는 적용 할 테마의 테마 머신 이름을 리턴합니다.

참조 ThemeNegotiator :: determineActiveTheme은 ()에 전달 될 수있는 RouteMatch 필요가 없습니다 테마 협상에 의해 사용 된 방법으로부터받은 인수에 가능한 변화를; 해당 패치가 적용되면 테마 협상자 코드도 변경해야합니다.


위 예제에서 apply ()를 apply ($ route_match)로 작성해서는 안됩니까? 연결된 질문 페이지에 동일한 질문을 게시했습니다. 감사!
Stefanos Petrakis

@StefanosPetrakis Hmmm ... 현재 구현은 변경 기록의 내용과 달리 매개 변수로 사용합니다.
kiamlaluno

Drupal 코어가 실제로 테마 협상 중 하나에서 사용하는 코드를 사용하여 답변을 업데이트했습니다.
kiamlaluno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.