3 namespace Drupal\system\Controller;
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Config\PreExistingConfigException;
7 use Drupal\Core\Config\UnmetDependenciesException;
8 use Drupal\Core\Controller\ControllerBase;
9 use Drupal\Core\Extension\ThemeHandlerInterface;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
11 use Symfony\Component\HttpFoundation\Request;
12 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
15 * Controller for theme handling.
17 class ThemeController extends ControllerBase {
20 * The theme handler service.
22 * @var \Drupal\Core\Extension\ThemeHandlerInterface
24 protected $themeHandler;
27 * Constructs a new ThemeController.
29 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
31 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
34 public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryInterface $config_factory) {
35 $this->themeHandler = $theme_handler;
36 $this->configFactory = $config_factory;
42 public static function create(ContainerInterface $container) {
44 $container->get('theme_handler'),
45 $container->get('config.factory')
52 * @param \Symfony\Component\HttpFoundation\Request $request
53 * A request object containing a theme name and a valid token.
55 * @return \Symfony\Component\HttpFoundation\RedirectResponse
56 * Redirects back to the appearance admin page.
58 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
59 * Throws access denied when no theme or token is set in the request or when
60 * the token is invalid.
62 public function uninstall(Request $request) {
63 $theme = $request->query->get('theme');
64 $config = $this->config('system.theme');
67 // Get current list of themes.
68 $themes = $this->themeHandler->listInfo();
70 // Check if the specified theme is one recognized by the system.
71 if (!empty($themes[$theme])) {
72 // Do not uninstall the default or admin theme.
73 if ($theme === $config->get('default') || $theme === $config->get('admin')) {
74 $this->messenger()->addError($this->t('%theme is the default theme and cannot be uninstalled.', ['%theme' => $themes[$theme]->info['name']]));
77 $this->themeHandler->uninstall([$theme]);
78 $this->messenger()->addStatus($this->t('The %theme theme has been uninstalled.', ['%theme' => $themes[$theme]->info['name']]));
82 $this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
85 return $this->redirect('system.themes_page');
88 throw new AccessDeniedHttpException();
94 * @param \Symfony\Component\HttpFoundation\Request $request
95 * A request object containing a theme name and a valid token.
97 * @return \Symfony\Component\HttpFoundation\RedirectResponse
98 * Redirects back to the appearance admin page.
100 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
101 * Throws access denied when no theme or token is set in the request or when
102 * the token is invalid.
104 public function install(Request $request) {
105 $theme = $request->query->get('theme');
109 if ($this->themeHandler->install([$theme])) {
110 $themes = $this->themeHandler->listInfo();
111 $this->messenger()->addStatus($this->t('The %theme theme has been installed.', ['%theme' => $themes[$theme]->info['name']]));
114 $this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
117 catch (PreExistingConfigException $e) {
118 $config_objects = $e->flattenConfigObjects($e->getConfigObjects());
119 $this->messenger()->addError(
121 count($config_objects),
122 'Unable to install @extension, %config_names already exists in active configuration.',
123 'Unable to install @extension, %config_names already exist in active configuration.',
125 '%config_names' => implode(', ', $config_objects),
126 '@extension' => $theme,
130 catch (UnmetDependenciesException $e) {
131 $this->messenger()->addError($e->getTranslatedMessage($this->getStringTranslation(), $theme));
134 return $this->redirect('system.themes_page');
137 throw new AccessDeniedHttpException();
141 * Set the default theme.
143 * @param \Symfony\Component\HttpFoundation\Request $request
144 * A request object containing a theme name.
146 * @return \Symfony\Component\HttpFoundation\RedirectResponse
147 * Redirects back to the appearance admin page.
149 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
150 * Throws access denied when no theme is set in the request.
152 public function setDefaultTheme(Request $request) {
153 $config = $this->configFactory->getEditable('system.theme');
154 $theme = $request->query->get('theme');
157 // Get current list of themes.
158 $themes = $this->themeHandler->listInfo();
160 // Check if the specified theme is one recognized by the system.
161 // Or try to install the theme.
162 if (isset($themes[$theme]) || $this->themeHandler->install([$theme])) {
163 $themes = $this->themeHandler->listInfo();
165 // Set the default theme.
166 $config->set('default', $theme)->save();
168 // The status message depends on whether an admin theme is currently in
169 // use: a value of 0 means the admin theme is set to be the default
171 $admin_theme = $config->get('admin');
172 if ($admin_theme != 0 && $admin_theme != $theme) {
174 ->addStatus($this->t('Please note that the administration theme is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', [
175 '%admin_theme' => $themes[$admin_theme]->info['name'],
176 '%selected_theme' => $themes[$theme]->info['name'],
180 $this->messenger()->addStatus($this->t('%theme is now the default theme.', ['%theme' => $themes[$theme]->info['name']]));
184 $this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
187 return $this->redirect('system.themes_page');
190 throw new AccessDeniedHttpException();