Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Extension;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Config\ConfigFactoryInterface;
|
Chris@0
|
6 use Drupal\Core\State\StateInterface;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * Default theme handler using the config system to store installation statuses.
|
Chris@0
|
10 */
|
Chris@0
|
11 class ThemeHandler implements ThemeHandlerInterface {
|
Chris@0
|
12
|
Chris@0
|
13 /**
|
Chris@0
|
14 * Contains the features enabled for themes by default.
|
Chris@0
|
15 *
|
Chris@0
|
16 * @var array
|
Chris@0
|
17 *
|
Chris@0
|
18 * @see _system_default_theme_features()
|
Chris@0
|
19 */
|
Chris@0
|
20 protected $defaultFeatures = [
|
Chris@0
|
21 'favicon',
|
Chris@0
|
22 'logo',
|
Chris@0
|
23 'node_user_picture',
|
Chris@0
|
24 'comment_user_picture',
|
Chris@0
|
25 'comment_user_verification',
|
Chris@0
|
26 ];
|
Chris@0
|
27
|
Chris@0
|
28 /**
|
Chris@0
|
29 * A list of all currently available themes.
|
Chris@0
|
30 *
|
Chris@0
|
31 * @var array
|
Chris@0
|
32 */
|
Chris@0
|
33 protected $list;
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * The config factory to get the installed themes.
|
Chris@0
|
37 *
|
Chris@0
|
38 * @var \Drupal\Core\Config\ConfigFactoryInterface
|
Chris@0
|
39 */
|
Chris@0
|
40 protected $configFactory;
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * The module handler to fire themes_installed/themes_uninstalled hooks.
|
Chris@0
|
44 *
|
Chris@0
|
45 * @var \Drupal\Core\Extension\ModuleHandlerInterface
|
Chris@0
|
46 */
|
Chris@0
|
47 protected $moduleHandler;
|
Chris@0
|
48
|
Chris@0
|
49 /**
|
Chris@0
|
50 * The state backend.
|
Chris@0
|
51 *
|
Chris@0
|
52 * @var \Drupal\Core\State\StateInterface
|
Chris@0
|
53 */
|
Chris@0
|
54 protected $state;
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * The config installer to install configuration.
|
Chris@0
|
58 *
|
Chris@0
|
59 * @var \Drupal\Core\Config\ConfigInstallerInterface
|
Chris@0
|
60 */
|
Chris@0
|
61 protected $configInstaller;
|
Chris@0
|
62
|
Chris@0
|
63 /**
|
Chris@0
|
64 * The info parser to parse the theme.info.yml files.
|
Chris@0
|
65 *
|
Chris@0
|
66 * @var \Drupal\Core\Extension\InfoParserInterface
|
Chris@0
|
67 */
|
Chris@0
|
68 protected $infoParser;
|
Chris@0
|
69
|
Chris@0
|
70 /**
|
Chris@0
|
71 * A logger instance.
|
Chris@0
|
72 *
|
Chris@0
|
73 * @var \Psr\Log\LoggerInterface
|
Chris@0
|
74 */
|
Chris@0
|
75 protected $logger;
|
Chris@0
|
76
|
Chris@0
|
77 /**
|
Chris@0
|
78 * The route builder to rebuild the routes if a theme is installed.
|
Chris@0
|
79 *
|
Chris@0
|
80 * @var \Drupal\Core\Routing\RouteBuilderInterface
|
Chris@0
|
81 */
|
Chris@0
|
82 protected $routeBuilder;
|
Chris@0
|
83
|
Chris@0
|
84 /**
|
Chris@0
|
85 * An extension discovery instance.
|
Chris@0
|
86 *
|
Chris@0
|
87 * @var \Drupal\Core\Extension\ExtensionDiscovery
|
Chris@0
|
88 */
|
Chris@0
|
89 protected $extensionDiscovery;
|
Chris@0
|
90
|
Chris@0
|
91 /**
|
Chris@0
|
92 * The CSS asset collection optimizer service.
|
Chris@0
|
93 *
|
Chris@0
|
94 * @var \Drupal\Core\Asset\AssetCollectionOptimizerInterface
|
Chris@0
|
95 */
|
Chris@0
|
96 protected $cssCollectionOptimizer;
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * The config manager used to uninstall a theme.
|
Chris@0
|
100 *
|
Chris@0
|
101 * @var \Drupal\Core\Config\ConfigManagerInterface
|
Chris@0
|
102 */
|
Chris@0
|
103 protected $configManager;
|
Chris@0
|
104
|
Chris@0
|
105 /**
|
Chris@0
|
106 * The app root.
|
Chris@0
|
107 *
|
Chris@0
|
108 * @var string
|
Chris@0
|
109 */
|
Chris@0
|
110 protected $root;
|
Chris@0
|
111
|
Chris@0
|
112 /**
|
Chris@0
|
113 * Constructs a new ThemeHandler.
|
Chris@0
|
114 *
|
Chris@0
|
115 * @param string $root
|
Chris@0
|
116 * The app root.
|
Chris@0
|
117 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
Chris@0
|
118 * The config factory to get the installed themes.
|
Chris@0
|
119 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
Chris@0
|
120 * The module handler to fire themes_installed/themes_uninstalled hooks.
|
Chris@0
|
121 * @param \Drupal\Core\State\StateInterface $state
|
Chris@0
|
122 * The state store.
|
Chris@0
|
123 * @param \Drupal\Core\Extension\InfoParserInterface $info_parser
|
Chris@0
|
124 * The info parser to parse the theme.info.yml files.
|
Chris@0
|
125 * @param \Drupal\Core\Extension\ExtensionDiscovery $extension_discovery
|
Chris@0
|
126 * (optional) A extension discovery instance (for unit tests).
|
Chris@0
|
127 */
|
Chris@0
|
128 public function __construct($root, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, StateInterface $state, InfoParserInterface $info_parser, ExtensionDiscovery $extension_discovery = NULL) {
|
Chris@0
|
129 $this->root = $root;
|
Chris@0
|
130 $this->configFactory = $config_factory;
|
Chris@0
|
131 $this->moduleHandler = $module_handler;
|
Chris@0
|
132 $this->state = $state;
|
Chris@0
|
133 $this->infoParser = $info_parser;
|
Chris@0
|
134 $this->extensionDiscovery = $extension_discovery;
|
Chris@0
|
135 }
|
Chris@0
|
136
|
Chris@0
|
137 /**
|
Chris@0
|
138 * {@inheritdoc}
|
Chris@0
|
139 */
|
Chris@0
|
140 public function getDefault() {
|
Chris@0
|
141 return $this->configFactory->get('system.theme')->get('default');
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 /**
|
Chris@0
|
145 * {@inheritdoc}
|
Chris@0
|
146 */
|
Chris@0
|
147 public function setDefault($name) {
|
Chris@0
|
148 $list = $this->listInfo();
|
Chris@0
|
149 if (!isset($list[$name])) {
|
Chris@0
|
150 throw new \InvalidArgumentException("$name theme is not installed.");
|
Chris@0
|
151 }
|
Chris@0
|
152 $this->configFactory->getEditable('system.theme')
|
Chris@0
|
153 ->set('default', $name)
|
Chris@0
|
154 ->save();
|
Chris@0
|
155 return $this;
|
Chris@0
|
156 }
|
Chris@0
|
157
|
Chris@0
|
158 /**
|
Chris@0
|
159 * {@inheritdoc}
|
Chris@0
|
160 */
|
Chris@0
|
161 public function install(array $theme_list, $install_dependencies = TRUE) {
|
Chris@0
|
162 // We keep the old install() method as BC layer but redirect directly to the
|
Chris@0
|
163 // theme installer.
|
Chris@0
|
164 return \Drupal::service('theme_installer')->install($theme_list, $install_dependencies);
|
Chris@0
|
165 }
|
Chris@0
|
166
|
Chris@0
|
167 /**
|
Chris@0
|
168 * {@inheritdoc}
|
Chris@0
|
169 */
|
Chris@0
|
170 public function uninstall(array $theme_list) {
|
Chris@0
|
171 // We keep the old uninstall() method as BC layer but redirect directly to
|
Chris@0
|
172 // the theme installer.
|
Chris@0
|
173 \Drupal::service('theme_installer')->uninstall($theme_list);
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 /**
|
Chris@0
|
177 * {@inheritdoc}
|
Chris@0
|
178 */
|
Chris@0
|
179 public function listInfo() {
|
Chris@0
|
180 if (!isset($this->list)) {
|
Chris@0
|
181 $this->list = [];
|
Chris@0
|
182 $themes = $this->systemThemeList();
|
Chris@0
|
183 // @todo Ensure that systemThemeList() does not contain an empty list
|
Chris@0
|
184 // during the batch installer, see https://www.drupal.org/node/2322619.
|
Chris@0
|
185 if (empty($themes)) {
|
Chris@0
|
186 $this->refreshInfo();
|
Chris@0
|
187 $this->list = $this->list ?: [];
|
Chris@0
|
188 $themes = \Drupal::state()->get('system.theme.data', []);
|
Chris@0
|
189 }
|
Chris@0
|
190 foreach ($themes as $theme) {
|
Chris@0
|
191 $this->addTheme($theme);
|
Chris@0
|
192 }
|
Chris@0
|
193 }
|
Chris@0
|
194 return $this->list;
|
Chris@0
|
195 }
|
Chris@0
|
196
|
Chris@0
|
197 /**
|
Chris@0
|
198 * {@inheritdoc}
|
Chris@0
|
199 */
|
Chris@0
|
200 public function addTheme(Extension $theme) {
|
Chris@0
|
201 if (!empty($theme->info['libraries'])) {
|
Chris@0
|
202 foreach ($theme->info['libraries'] as $library => $name) {
|
Chris@0
|
203 $theme->libraries[$library] = $name;
|
Chris@0
|
204 }
|
Chris@0
|
205 }
|
Chris@0
|
206 if (isset($theme->info['engine'])) {
|
Chris@0
|
207 $theme->engine = $theme->info['engine'];
|
Chris@0
|
208 }
|
Chris@0
|
209 if (isset($theme->info['base theme'])) {
|
Chris@0
|
210 $theme->base_theme = $theme->info['base theme'];
|
Chris@0
|
211 }
|
Chris@0
|
212 $this->list[$theme->getName()] = $theme;
|
Chris@0
|
213 }
|
Chris@0
|
214
|
Chris@0
|
215 /**
|
Chris@0
|
216 * {@inheritdoc}
|
Chris@0
|
217 */
|
Chris@0
|
218 public function refreshInfo() {
|
Chris@0
|
219 $extension_config = $this->configFactory->get('core.extension');
|
Chris@0
|
220 $installed = $extension_config->get('theme');
|
Chris@0
|
221 // Only refresh the info if a theme has been installed. Modules are
|
Chris@0
|
222 // installed before themes by the installer and this method is called during
|
Chris@0
|
223 // module installation.
|
Chris@0
|
224 if (empty($installed) && empty($this->list)) {
|
Chris@0
|
225 return;
|
Chris@0
|
226 }
|
Chris@0
|
227
|
Chris@0
|
228 $this->reset();
|
Chris@0
|
229 // @todo Avoid re-scanning all themes by retaining the original (unaltered)
|
Chris@0
|
230 // theme info somewhere.
|
Chris@0
|
231 $list = $this->rebuildThemeData();
|
Chris@0
|
232 foreach ($list as $name => $theme) {
|
Chris@0
|
233 if (isset($installed[$name])) {
|
Chris@0
|
234 $this->addTheme($theme);
|
Chris@0
|
235 }
|
Chris@0
|
236 }
|
Chris@0
|
237 $this->state->set('system.theme.data', $this->list);
|
Chris@0
|
238 }
|
Chris@0
|
239
|
Chris@0
|
240 /**
|
Chris@0
|
241 * {@inheritdoc}
|
Chris@0
|
242 */
|
Chris@0
|
243 public function reset() {
|
Chris@0
|
244 $this->systemListReset();
|
Chris@0
|
245 $this->list = NULL;
|
Chris@0
|
246 }
|
Chris@0
|
247
|
Chris@0
|
248 /**
|
Chris@0
|
249 * {@inheritdoc}
|
Chris@0
|
250 */
|
Chris@0
|
251 public function rebuildThemeData() {
|
Chris@0
|
252 $listing = $this->getExtensionDiscovery();
|
Chris@0
|
253 $themes = $listing->scan('theme');
|
Chris@0
|
254 $engines = $listing->scan('theme_engine');
|
Chris@0
|
255 $extension_config = $this->configFactory->get('core.extension');
|
Chris@0
|
256 $installed = $extension_config->get('theme') ?: [];
|
Chris@0
|
257
|
Chris@0
|
258 // Set defaults for theme info.
|
Chris@0
|
259 $defaults = [
|
Chris@0
|
260 'engine' => 'twig',
|
Chris@0
|
261 'base theme' => 'stable',
|
Chris@0
|
262 'regions' => [
|
Chris@0
|
263 'sidebar_first' => 'Left sidebar',
|
Chris@0
|
264 'sidebar_second' => 'Right sidebar',
|
Chris@0
|
265 'content' => 'Content',
|
Chris@0
|
266 'header' => 'Header',
|
Chris@0
|
267 'primary_menu' => 'Primary menu',
|
Chris@0
|
268 'secondary_menu' => 'Secondary menu',
|
Chris@0
|
269 'footer' => 'Footer',
|
Chris@0
|
270 'highlighted' => 'Highlighted',
|
Chris@0
|
271 'help' => 'Help',
|
Chris@0
|
272 'page_top' => 'Page top',
|
Chris@0
|
273 'page_bottom' => 'Page bottom',
|
Chris@0
|
274 'breadcrumb' => 'Breadcrumb',
|
Chris@0
|
275 ],
|
Chris@0
|
276 'description' => '',
|
Chris@0
|
277 'features' => $this->defaultFeatures,
|
Chris@0
|
278 'screenshot' => 'screenshot.png',
|
Chris@0
|
279 'php' => DRUPAL_MINIMUM_PHP,
|
Chris@0
|
280 'libraries' => [],
|
Chris@0
|
281 ];
|
Chris@0
|
282
|
Chris@0
|
283 $sub_themes = [];
|
Chris@0
|
284 $files_theme = [];
|
Chris@0
|
285 $files_theme_engine = [];
|
Chris@0
|
286 // Read info files for each theme.
|
Chris@0
|
287 foreach ($themes as $key => $theme) {
|
Chris@0
|
288 // @todo Remove all code that relies on the $status property.
|
Chris@0
|
289 $theme->status = (int) isset($installed[$key]);
|
Chris@0
|
290
|
Chris@0
|
291 $theme->info = $this->infoParser->parse($theme->getPathname()) + $defaults;
|
Chris@0
|
292 // Remove the default Stable base theme when 'base theme: false' is set in
|
Chris@0
|
293 // a theme .info.yml file.
|
Chris@0
|
294 if ($theme->info['base theme'] === FALSE) {
|
Chris@0
|
295 unset($theme->info['base theme']);
|
Chris@0
|
296 }
|
Chris@0
|
297
|
Chris@0
|
298 // Add the info file modification time, so it becomes available for
|
Chris@0
|
299 // contributed modules to use for ordering theme lists.
|
Chris@0
|
300 $theme->info['mtime'] = $theme->getMTime();
|
Chris@0
|
301
|
Chris@0
|
302 // Invoke hook_system_info_alter() to give installed modules a chance to
|
Chris@0
|
303 // modify the data in the .info.yml files if necessary.
|
Chris@0
|
304 // @todo Remove $type argument, obsolete with $theme->getType().
|
Chris@0
|
305 $type = 'theme';
|
Chris@0
|
306 $this->moduleHandler->alter('system_info', $theme->info, $theme, $type);
|
Chris@0
|
307
|
Chris@0
|
308 if (!empty($theme->info['base theme'])) {
|
Chris@0
|
309 $sub_themes[] = $key;
|
Chris@0
|
310 // Add the base theme as a proper dependency.
|
Chris@0
|
311 $themes[$key]->info['dependencies'][] = $themes[$key]->info['base theme'];
|
Chris@0
|
312 }
|
Chris@0
|
313
|
Chris@0
|
314 // Defaults to 'twig' (see $defaults above).
|
Chris@0
|
315 $engine = $theme->info['engine'];
|
Chris@0
|
316 if (isset($engines[$engine])) {
|
Chris@0
|
317 $theme->owner = $engines[$engine]->getExtensionPathname();
|
Chris@0
|
318 $theme->prefix = $engines[$engine]->getName();
|
Chris@0
|
319 $files_theme_engine[$engine] = $engines[$engine]->getPathname();
|
Chris@0
|
320 }
|
Chris@0
|
321
|
Chris@0
|
322 // Prefix screenshot with theme path.
|
Chris@0
|
323 if (!empty($theme->info['screenshot'])) {
|
Chris@0
|
324 $theme->info['screenshot'] = $theme->getPath() . '/' . $theme->info['screenshot'];
|
Chris@0
|
325 }
|
Chris@0
|
326
|
Chris@0
|
327 $files_theme[$key] = $theme->getPathname();
|
Chris@0
|
328 }
|
Chris@0
|
329 // Build dependencies.
|
Chris@0
|
330 // @todo Move into a generic ExtensionHandler base class.
|
Chris@0
|
331 // @see https://www.drupal.org/node/2208429
|
Chris@0
|
332 $themes = $this->moduleHandler->buildModuleDependencies($themes);
|
Chris@0
|
333
|
Chris@0
|
334 // Store filenames to allow system_list() and drupal_get_filename() to
|
Chris@0
|
335 // retrieve them for themes and theme engines without having to scan the
|
Chris@0
|
336 // filesystem.
|
Chris@0
|
337 $this->state->set('system.theme.files', $files_theme);
|
Chris@0
|
338 $this->state->set('system.theme_engine.files', $files_theme_engine);
|
Chris@0
|
339
|
Chris@0
|
340 // After establishing the full list of available themes, fill in data for
|
Chris@0
|
341 // sub-themes.
|
Chris@0
|
342 foreach ($sub_themes as $key) {
|
Chris@0
|
343 $sub_theme = $themes[$key];
|
Chris@0
|
344 // The $base_themes property is optional; only set for sub themes.
|
Chris@0
|
345 // @see ThemeHandlerInterface::listInfo()
|
Chris@0
|
346 $sub_theme->base_themes = $this->getBaseThemes($themes, $key);
|
Chris@0
|
347 // empty() cannot be used here, since ThemeHandler::doGetBaseThemes() adds
|
Chris@0
|
348 // the key of a base theme with a value of NULL in case it is not found,
|
Chris@0
|
349 // in order to prevent needless iterations.
|
Chris@0
|
350 if (!current($sub_theme->base_themes)) {
|
Chris@0
|
351 continue;
|
Chris@0
|
352 }
|
Chris@0
|
353 // Determine the root base theme.
|
Chris@0
|
354 $root_key = key($sub_theme->base_themes);
|
Chris@0
|
355 // Build the list of sub-themes for each of the theme's base themes.
|
Chris@0
|
356 foreach (array_keys($sub_theme->base_themes) as $base_theme) {
|
Chris@0
|
357 $themes[$base_theme]->sub_themes[$key] = $sub_theme->info['name'];
|
Chris@0
|
358 }
|
Chris@0
|
359 // Add the theme engine info from the root base theme.
|
Chris@0
|
360 if (isset($themes[$root_key]->owner)) {
|
Chris@0
|
361 $sub_theme->info['engine'] = $themes[$root_key]->info['engine'];
|
Chris@0
|
362 $sub_theme->owner = $themes[$root_key]->owner;
|
Chris@0
|
363 $sub_theme->prefix = $themes[$root_key]->prefix;
|
Chris@0
|
364 }
|
Chris@0
|
365 }
|
Chris@0
|
366
|
Chris@0
|
367 return $themes;
|
Chris@0
|
368 }
|
Chris@0
|
369
|
Chris@0
|
370 /**
|
Chris@0
|
371 * {@inheritdoc}
|
Chris@0
|
372 */
|
Chris@0
|
373 public function getBaseThemes(array $themes, $theme) {
|
Chris@0
|
374 return $this->doGetBaseThemes($themes, $theme);
|
Chris@0
|
375 }
|
Chris@0
|
376
|
Chris@0
|
377 /**
|
Chris@0
|
378 * Finds the base themes for the specific theme.
|
Chris@0
|
379 *
|
Chris@0
|
380 * @param array $themes
|
Chris@0
|
381 * An array of available themes.
|
Chris@0
|
382 * @param string $theme
|
Chris@0
|
383 * The name of the theme whose base we are looking for.
|
Chris@0
|
384 * @param array $used_themes
|
Chris@0
|
385 * (optional) A recursion parameter preventing endless loops. Defaults to
|
Chris@0
|
386 * an empty array.
|
Chris@0
|
387 *
|
Chris@0
|
388 * @return array
|
Chris@0
|
389 * An array of base themes.
|
Chris@0
|
390 */
|
Chris@0
|
391 protected function doGetBaseThemes(array $themes, $theme, $used_themes = []) {
|
Chris@0
|
392 if (!isset($themes[$theme]->info['base theme'])) {
|
Chris@0
|
393 return [];
|
Chris@0
|
394 }
|
Chris@0
|
395
|
Chris@0
|
396 $base_key = $themes[$theme]->info['base theme'];
|
Chris@0
|
397 // Does the base theme exist?
|
Chris@0
|
398 if (!isset($themes[$base_key])) {
|
Chris@0
|
399 return [$base_key => NULL];
|
Chris@0
|
400 }
|
Chris@0
|
401
|
Chris@0
|
402 $current_base_theme = [$base_key => $themes[$base_key]->info['name']];
|
Chris@0
|
403
|
Chris@0
|
404 // Is the base theme itself a child of another theme?
|
Chris@0
|
405 if (isset($themes[$base_key]->info['base theme'])) {
|
Chris@0
|
406 // Do we already know the base themes of this theme?
|
Chris@0
|
407 if (isset($themes[$base_key]->base_themes)) {
|
Chris@0
|
408 return $themes[$base_key]->base_themes + $current_base_theme;
|
Chris@0
|
409 }
|
Chris@0
|
410 // Prevent loops.
|
Chris@0
|
411 if (!empty($used_themes[$base_key])) {
|
Chris@0
|
412 return [$base_key => NULL];
|
Chris@0
|
413 }
|
Chris@0
|
414 $used_themes[$base_key] = TRUE;
|
Chris@0
|
415 return $this->doGetBaseThemes($themes, $base_key, $used_themes) + $current_base_theme;
|
Chris@0
|
416 }
|
Chris@0
|
417 // If we get here, then this is our parent theme.
|
Chris@0
|
418 return $current_base_theme;
|
Chris@0
|
419 }
|
Chris@0
|
420
|
Chris@0
|
421 /**
|
Chris@0
|
422 * Returns an extension discovery object.
|
Chris@0
|
423 *
|
Chris@0
|
424 * @return \Drupal\Core\Extension\ExtensionDiscovery
|
Chris@0
|
425 * The extension discovery object.
|
Chris@0
|
426 */
|
Chris@0
|
427 protected function getExtensionDiscovery() {
|
Chris@0
|
428 if (!isset($this->extensionDiscovery)) {
|
Chris@0
|
429 $this->extensionDiscovery = new ExtensionDiscovery($this->root);
|
Chris@0
|
430 }
|
Chris@0
|
431 return $this->extensionDiscovery;
|
Chris@0
|
432 }
|
Chris@0
|
433
|
Chris@0
|
434 /**
|
Chris@0
|
435 * {@inheritdoc}
|
Chris@0
|
436 */
|
Chris@0
|
437 public function getName($theme) {
|
Chris@0
|
438 $themes = $this->listInfo();
|
Chris@0
|
439 if (!isset($themes[$theme])) {
|
Chris@0
|
440 throw new \InvalidArgumentException("Requested the name of a non-existing theme $theme");
|
Chris@0
|
441 }
|
Chris@0
|
442 return $themes[$theme]->info['name'];
|
Chris@0
|
443 }
|
Chris@0
|
444
|
Chris@0
|
445 /**
|
Chris@0
|
446 * Wraps system_list_reset().
|
Chris@0
|
447 */
|
Chris@0
|
448 protected function systemListReset() {
|
Chris@0
|
449 system_list_reset();
|
Chris@0
|
450 }
|
Chris@0
|
451
|
Chris@0
|
452 /**
|
Chris@0
|
453 * Wraps system_list().
|
Chris@0
|
454 *
|
Chris@0
|
455 * @return array
|
Chris@0
|
456 * A list of themes keyed by name.
|
Chris@0
|
457 */
|
Chris@0
|
458 protected function systemThemeList() {
|
Chris@0
|
459 return system_list('theme');
|
Chris@0
|
460 }
|
Chris@0
|
461
|
Chris@0
|
462 /**
|
Chris@0
|
463 * {@inheritdoc}
|
Chris@0
|
464 */
|
Chris@0
|
465 public function getThemeDirectories() {
|
Chris@0
|
466 $dirs = [];
|
Chris@0
|
467 foreach ($this->listInfo() as $name => $theme) {
|
Chris@0
|
468 $dirs[$name] = $this->root . '/' . $theme->getPath();
|
Chris@0
|
469 }
|
Chris@0
|
470 return $dirs;
|
Chris@0
|
471 }
|
Chris@0
|
472
|
Chris@0
|
473 /**
|
Chris@0
|
474 * {@inheritdoc}
|
Chris@0
|
475 */
|
Chris@0
|
476 public function themeExists($theme) {
|
Chris@0
|
477 $themes = $this->listInfo();
|
Chris@0
|
478 return isset($themes[$theme]);
|
Chris@0
|
479 }
|
Chris@0
|
480
|
Chris@0
|
481 /**
|
Chris@0
|
482 * {@inheritdoc}
|
Chris@0
|
483 */
|
Chris@0
|
484 public function getTheme($name) {
|
Chris@0
|
485 $themes = $this->listInfo();
|
Chris@0
|
486 if (isset($themes[$name])) {
|
Chris@0
|
487 return $themes[$name];
|
Chris@0
|
488 }
|
Chris@0
|
489 throw new \InvalidArgumentException(sprintf('The theme %s does not exist.', $name));
|
Chris@0
|
490 }
|
Chris@0
|
491
|
Chris@0
|
492 /**
|
Chris@0
|
493 * {@inheritdoc}
|
Chris@0
|
494 */
|
Chris@0
|
495 public function hasUi($name) {
|
Chris@0
|
496 $themes = $this->listInfo();
|
Chris@0
|
497 if (isset($themes[$name])) {
|
Chris@0
|
498 if (!empty($themes[$name]->info['hidden'])) {
|
Chris@0
|
499 $theme_config = $this->configFactory->get('system.theme');
|
Chris@0
|
500 return $name == $theme_config->get('default') || $name == $theme_config->get('admin');
|
Chris@0
|
501 }
|
Chris@0
|
502 return TRUE;
|
Chris@0
|
503 }
|
Chris@0
|
504 return FALSE;
|
Chris@0
|
505 }
|
Chris@0
|
506
|
Chris@0
|
507 }
|