ThemeHandler.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. namespace Drupal\Core\Extension;
  3. use Drupal\Core\Config\ConfigFactoryInterface;
  4. use Drupal\Core\Extension\Exception\UninstalledExtensionException;
  5. use Drupal\Core\Extension\Exception\UnknownExtensionException;
  6. /**
  7. * Default theme handler using the config system to store installation statuses.
  8. */
  9. class ThemeHandler implements ThemeHandlerInterface {
  10. /**
  11. * A list of all currently available themes.
  12. *
  13. * @var array
  14. */
  15. protected $list;
  16. /**
  17. * The config factory to get the installed themes.
  18. *
  19. * @var \Drupal\Core\Config\ConfigFactoryInterface
  20. */
  21. protected $configFactory;
  22. /**
  23. * An extension discovery instance.
  24. *
  25. * @var \Drupal\Core\Extension\ThemeExtensionList
  26. */
  27. protected $themeList;
  28. /**
  29. * The app root.
  30. *
  31. * @var string
  32. */
  33. protected $root;
  34. /**
  35. * Constructs a new ThemeHandler.
  36. *
  37. * @param string $root
  38. * The app root.
  39. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
  40. * The config factory to get the installed themes.
  41. * @param \Drupal\Core\Extension\ThemeExtensionList $theme_list
  42. * A extension discovery instance.
  43. */
  44. public function __construct($root, ConfigFactoryInterface $config_factory, ThemeExtensionList $theme_list) {
  45. $this->root = $root;
  46. $this->configFactory = $config_factory;
  47. $this->themeList = $theme_list;
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function getDefault() {
  53. return $this->configFactory->get('system.theme')->get('default');
  54. }
  55. /**
  56. * {@inheritdoc}
  57. */
  58. public function setDefault($name) {
  59. @trigger_error(__METHOD__ . ' is deprecated in drupal:8.2.0 and is removed from drupal:9.0.0. Use the configuration system to edit the system.theme config directly. See https://www.drupal.org/node/3082630', E_USER_DEPRECATED);
  60. $list = $this->listInfo();
  61. if (!isset($list[$name])) {
  62. throw new UninstalledExtensionException("$name theme is not installed.");
  63. }
  64. $this->configFactory->getEditable('system.theme')
  65. ->set('default', $name)
  66. ->save();
  67. return $this;
  68. }
  69. /**
  70. * {@inheritdoc}
  71. */
  72. public function install(array $theme_list, $install_dependencies = TRUE) {
  73. // We keep the old install() method as BC layer but redirect directly to the
  74. // theme installer.
  75. @trigger_error('\Drupal\Core\Extension\ThemeHandlerInterface::install() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use \Drupal\Core\Extension\ThemeInstallerInterface::install() instead. See https://www.drupal.org/node/3017233', E_USER_DEPRECATED);
  76. return \Drupal::service('theme_installer')->install($theme_list, $install_dependencies);
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. public function uninstall(array $theme_list) {
  82. // We keep the old uninstall() method as BC layer but redirect directly to
  83. // the theme installer.
  84. @trigger_error('\Drupal\Core\Extension\ThemeHandlerInterface::uninstall() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use \Drupal\Core\Extension\ThemeInstallerInterface::uninstall() instead. See https://www.drupal.org/node/3017233', E_USER_DEPRECATED);
  85. \Drupal::service('theme_installer')->uninstall($theme_list);
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function listInfo() {
  91. if (!isset($this->list)) {
  92. $this->list = [];
  93. $installed_themes = $this->configFactory->get('core.extension')->get('theme');
  94. if (!empty($installed_themes)) {
  95. $installed_themes = array_intersect_key($this->themeList->getList(), $installed_themes);
  96. array_map([$this, 'addTheme'], $installed_themes);
  97. }
  98. }
  99. return $this->list;
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. public function addTheme(Extension $theme) {
  105. // Register the namespaces of installed themes.
  106. // @todo Implement proper theme registration
  107. // https://www.drupal.org/project/drupal/issues/2941757
  108. \Drupal::service('class_loader')->addPsr4('Drupal\\' . $theme->getName() . '\\', $this->root . '/' . $theme->getPath() . '/src');
  109. if (!empty($theme->info['libraries'])) {
  110. foreach ($theme->info['libraries'] as $library => $name) {
  111. $theme->libraries[$library] = $name;
  112. }
  113. }
  114. if (isset($theme->info['engine'])) {
  115. $theme->engine = $theme->info['engine'];
  116. }
  117. if (isset($theme->info['base theme'])) {
  118. $theme->base_theme = $theme->info['base theme'];
  119. }
  120. $this->list[$theme->getName()] = $theme;
  121. }
  122. /**
  123. * {@inheritdoc}
  124. */
  125. public function refreshInfo() {
  126. $installed = $this->configFactory->get('core.extension')->get('theme');
  127. // Only refresh the info if a theme has been installed. Modules are
  128. // installed before themes by the installer and this method is called during
  129. // module installation.
  130. if (empty($installed) && empty($this->list)) {
  131. return;
  132. }
  133. $this->reset();
  134. }
  135. /**
  136. * {@inheritdoc}
  137. */
  138. public function reset() {
  139. $this->themeList->reset();
  140. $this->list = NULL;
  141. }
  142. /**
  143. * {@inheritdoc}
  144. */
  145. public function rebuildThemeData() {
  146. return $this->themeList->reset()->getList();
  147. }
  148. /**
  149. * {@inheritdoc}
  150. */
  151. public function getBaseThemes(array $themes, $theme) {
  152. return $this->themeList->getBaseThemes($themes, $theme);
  153. }
  154. /**
  155. * {@inheritdoc}
  156. */
  157. public function getName($theme) {
  158. return $this->themeList->getName($theme);
  159. }
  160. /**
  161. * {@inheritdoc}
  162. */
  163. public function getThemeDirectories() {
  164. $dirs = [];
  165. foreach ($this->listInfo() as $name => $theme) {
  166. $dirs[$name] = $this->root . '/' . $theme->getPath();
  167. }
  168. return $dirs;
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function themeExists($theme) {
  174. $themes = $this->listInfo();
  175. return isset($themes[$theme]);
  176. }
  177. /**
  178. * {@inheritdoc}
  179. */
  180. public function getTheme($name) {
  181. $themes = $this->listInfo();
  182. if (isset($themes[$name])) {
  183. return $themes[$name];
  184. }
  185. throw new UnknownExtensionException(sprintf('The theme %s does not exist.', $name));
  186. }
  187. /**
  188. * {@inheritdoc}
  189. */
  190. public function hasUi($name) {
  191. $themes = $this->listInfo();
  192. if (isset($themes[$name])) {
  193. if (!empty($themes[$name]->info['hidden'])) {
  194. $theme_config = $this->configFactory->get('system.theme');
  195. return $name == $theme_config->get('default') || $name == $theme_config->get('admin');
  196. }
  197. return TRUE;
  198. }
  199. return FALSE;
  200. }
  201. }