annotate core/modules/system/src/Controller/SystemController.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\system\Controller;
Chris@0 4
Chris@0 5 use Drupal\Core\Cache\CacheableMetadata;
Chris@0 6 use Drupal\Core\Controller\ControllerBase;
Chris@0 7 use Drupal\Core\Extension\ThemeHandlerInterface;
Chris@0 8 use Drupal\Core\Form\FormBuilderInterface;
Chris@0 9 use Drupal\Core\Menu\MenuLinkTreeInterface;
Chris@0 10 use Drupal\Core\Menu\MenuTreeParameters;
Chris@0 11 use Drupal\Core\Theme\ThemeAccessCheck;
Chris@0 12 use Drupal\Core\Url;
Chris@0 13 use Drupal\system\SystemManager;
Chris@0 14 use Symfony\Component\DependencyInjection\ContainerInterface;
Chris@0 15
Chris@0 16 /**
Chris@0 17 * Returns responses for System routes.
Chris@0 18 */
Chris@0 19 class SystemController extends ControllerBase {
Chris@0 20
Chris@0 21 /**
Chris@0 22 * System Manager Service.
Chris@0 23 *
Chris@0 24 * @var \Drupal\system\SystemManager
Chris@0 25 */
Chris@0 26 protected $systemManager;
Chris@0 27
Chris@0 28 /**
Chris@0 29 * The theme access checker service.
Chris@0 30 *
Chris@0 31 * @var \Drupal\Core\Theme\ThemeAccessCheck
Chris@0 32 */
Chris@0 33 protected $themeAccess;
Chris@0 34
Chris@0 35 /**
Chris@0 36 * The form builder service.
Chris@0 37 *
Chris@0 38 * @var \Drupal\Core\Form\FormBuilderInterface
Chris@0 39 */
Chris@0 40 protected $formBuilder;
Chris@0 41
Chris@0 42 /**
Chris@0 43 * The theme handler service.
Chris@0 44 *
Chris@0 45 * @var \Drupal\Core\Extension\ThemeHandlerInterface
Chris@0 46 */
Chris@0 47 protected $themeHandler;
Chris@0 48
Chris@0 49 /**
Chris@0 50 * The menu link tree service.
Chris@0 51 *
Chris@0 52 * @var \Drupal\Core\Menu\MenuLinkTreeInterface
Chris@0 53 */
Chris@0 54 protected $menuLinkTree;
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Constructs a new SystemController.
Chris@0 58 *
Chris@0 59 * @param \Drupal\system\SystemManager $systemManager
Chris@0 60 * System manager service.
Chris@0 61 * @param \Drupal\Core\Theme\ThemeAccessCheck $theme_access
Chris@0 62 * The theme access checker service.
Chris@0 63 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
Chris@0 64 * The form builder.
Chris@0 65 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
Chris@0 66 * The theme handler.
Chris@0 67 * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_link_tree
Chris@0 68 * The menu link tree service.
Chris@0 69 */
Chris@0 70 public function __construct(SystemManager $systemManager, ThemeAccessCheck $theme_access, FormBuilderInterface $form_builder, ThemeHandlerInterface $theme_handler, MenuLinkTreeInterface $menu_link_tree) {
Chris@0 71 $this->systemManager = $systemManager;
Chris@0 72 $this->themeAccess = $theme_access;
Chris@0 73 $this->formBuilder = $form_builder;
Chris@0 74 $this->themeHandler = $theme_handler;
Chris@0 75 $this->menuLinkTree = $menu_link_tree;
Chris@0 76 }
Chris@0 77
Chris@0 78 /**
Chris@0 79 * {@inheritdoc}
Chris@0 80 */
Chris@0 81 public static function create(ContainerInterface $container) {
Chris@0 82 return new static(
Chris@0 83 $container->get('system.manager'),
Chris@0 84 $container->get('access_check.theme'),
Chris@0 85 $container->get('form_builder'),
Chris@0 86 $container->get('theme_handler'),
Chris@0 87 $container->get('menu.link_tree')
Chris@0 88 );
Chris@0 89 }
Chris@0 90
Chris@0 91 /**
Chris@0 92 * Provide the administration overview page.
Chris@0 93 *
Chris@0 94 * @param string $link_id
Chris@0 95 * The ID of the administrative path link for which to display child links.
Chris@0 96 *
Chris@0 97 * @return array
Chris@0 98 * A renderable array of the administration overview page.
Chris@0 99 */
Chris@0 100 public function overview($link_id) {
Chris@0 101 // Check for status report errors.
Chris@0 102 if ($this->systemManager->checkRequirements() && $this->currentUser()->hasPermission('administer site configuration')) {
Chris@17 103 $this->messenger()->addError($this->t('One or more problems were detected with your Drupal installation. Check the <a href=":status">status report</a> for more information.', [':status' => $this->url('system.status')]));
Chris@0 104 }
Chris@0 105 // Load all menu links below it.
Chris@0 106 $parameters = new MenuTreeParameters();
Chris@0 107 $parameters->setRoot($link_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks();
Chris@0 108 $tree = $this->menuLinkTree->load(NULL, $parameters);
Chris@0 109 $manipulators = [
Chris@0 110 ['callable' => 'menu.default_tree_manipulators:checkAccess'],
Chris@0 111 ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
Chris@0 112 ];
Chris@0 113 $tree = $this->menuLinkTree->transform($tree, $manipulators);
Chris@0 114 $tree_access_cacheability = new CacheableMetadata();
Chris@0 115 $blocks = [];
Chris@0 116 foreach ($tree as $key => $element) {
Chris@0 117 $tree_access_cacheability = $tree_access_cacheability->merge(CacheableMetadata::createFromObject($element->access));
Chris@0 118
Chris@0 119 // Only render accessible links.
Chris@0 120 if (!$element->access->isAllowed()) {
Chris@0 121 continue;
Chris@0 122 }
Chris@0 123
Chris@0 124 $link = $element->link;
Chris@0 125 $block['title'] = $link->getTitle();
Chris@0 126 $block['description'] = $link->getDescription();
Chris@0 127 $block['content'] = [
Chris@0 128 '#theme' => 'admin_block_content',
Chris@0 129 '#content' => $this->systemManager->getAdminBlock($link),
Chris@0 130 ];
Chris@0 131
Chris@0 132 if (!empty($block['content']['#content'])) {
Chris@0 133 $blocks[$key] = $block;
Chris@0 134 }
Chris@0 135 }
Chris@0 136
Chris@0 137 if ($blocks) {
Chris@0 138 ksort($blocks);
Chris@0 139 $build = [
Chris@0 140 '#theme' => 'admin_page',
Chris@0 141 '#blocks' => $blocks,
Chris@0 142 ];
Chris@0 143 $tree_access_cacheability->applyTo($build);
Chris@0 144 return $build;
Chris@0 145 }
Chris@0 146 else {
Chris@0 147 $build = [
Chris@0 148 '#markup' => $this->t('You do not have any administrative items.'),
Chris@0 149 ];
Chris@0 150 $tree_access_cacheability->applyTo($build);
Chris@0 151 return $build;
Chris@0 152 }
Chris@0 153 }
Chris@0 154
Chris@0 155 /**
Chris@0 156 * Sets whether the admin menu is in compact mode or not.
Chris@0 157 *
Chris@0 158 * @param string $mode
Chris@0 159 * Valid values are 'on' and 'off'.
Chris@0 160 *
Chris@0 161 * @return \Symfony\Component\HttpFoundation\RedirectResponse
Chris@0 162 */
Chris@0 163 public function compactPage($mode) {
Chris@0 164 user_cookie_save(['admin_compact_mode' => ($mode == 'on')]);
Chris@0 165 return $this->redirect('<front>');
Chris@0 166 }
Chris@0 167
Chris@0 168 /**
Chris@0 169 * Provides a single block from the administration menu as a page.
Chris@0 170 */
Chris@0 171 public function systemAdminMenuBlockPage() {
Chris@0 172 return $this->systemManager->getBlockContents();
Chris@0 173 }
Chris@0 174
Chris@0 175 /**
Chris@0 176 * Returns a theme listing.
Chris@0 177 *
Chris@0 178 * @return string
Chris@0 179 * An HTML string of the theme listing page.
Chris@0 180 *
Chris@0 181 * @todo Move into ThemeController.
Chris@0 182 */
Chris@0 183 public function themesPage() {
Chris@0 184 $config = $this->config('system.theme');
Chris@0 185 // Get all available themes.
Chris@0 186 $themes = $this->themeHandler->rebuildThemeData();
Chris@0 187 uasort($themes, 'system_sort_modules_by_info_name');
Chris@0 188
Chris@0 189 $theme_default = $config->get('default');
Chris@17 190 $theme_groups = ['installed' => [], 'uninstalled' => []];
Chris@0 191 $admin_theme = $config->get('admin');
Chris@0 192 $admin_theme_options = [];
Chris@0 193
Chris@0 194 foreach ($themes as &$theme) {
Chris@0 195 if (!empty($theme->info['hidden'])) {
Chris@0 196 continue;
Chris@0 197 }
Chris@0 198 $theme->is_default = ($theme->getName() == $theme_default);
Chris@0 199 $theme->is_admin = ($theme->getName() == $admin_theme || ($theme->is_default && $admin_theme == '0'));
Chris@0 200
Chris@0 201 // Identify theme screenshot.
Chris@0 202 $theme->screenshot = NULL;
Chris@0 203 // Create a list which includes the current theme and all its base themes.
Chris@0 204 if (isset($themes[$theme->getName()]->base_themes)) {
Chris@0 205 $theme_keys = array_keys($themes[$theme->getName()]->base_themes);
Chris@0 206 $theme_keys[] = $theme->getName();
Chris@0 207 }
Chris@0 208 else {
Chris@0 209 $theme_keys = [$theme->getName()];
Chris@0 210 }
Chris@0 211 // Look for a screenshot in the current theme or in its closest ancestor.
Chris@0 212 foreach (array_reverse($theme_keys) as $theme_key) {
Chris@0 213 if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
Chris@0 214 $theme->screenshot = [
Chris@0 215 'uri' => $themes[$theme_key]->info['screenshot'],
Chris@0 216 'alt' => $this->t('Screenshot for @theme theme', ['@theme' => $theme->info['name']]),
Chris@0 217 'title' => $this->t('Screenshot for @theme theme', ['@theme' => $theme->info['name']]),
Chris@0 218 'attributes' => ['class' => ['screenshot']],
Chris@0 219 ];
Chris@0 220 break;
Chris@0 221 }
Chris@0 222 }
Chris@0 223
Chris@0 224 if (empty($theme->status)) {
Chris@0 225 // Ensure this theme is compatible with this version of core.
Chris@0 226 $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != \DRUPAL::CORE_COMPATIBILITY);
Chris@0 227 // Require the 'content' region to make sure the main page
Chris@0 228 // content has a common place in all themes.
Chris@0 229 $theme->incompatible_region = !isset($theme->info['regions']['content']);
Chris@0 230 $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
Chris@0 231 // Confirm that all base themes are available.
Chris@0 232 $theme->incompatible_base = (isset($theme->info['base theme']) && !($theme->base_themes === array_filter($theme->base_themes)));
Chris@0 233 // Confirm that the theme engine is available.
Chris@0 234 $theme->incompatible_engine = isset($theme->info['engine']) && !isset($theme->owner);
Chris@0 235 }
Chris@0 236 $theme->operations = [];
Chris@0 237 if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
Chris@0 238 // Create the operations links.
Chris@0 239 $query['theme'] = $theme->getName();
Chris@0 240 if ($this->themeAccess->checkAccess($theme->getName())) {
Chris@0 241 $theme->operations[] = [
Chris@0 242 'title' => $this->t('Settings'),
Chris@0 243 'url' => Url::fromRoute('system.theme_settings_theme', ['theme' => $theme->getName()]),
Chris@0 244 'attributes' => ['title' => $this->t('Settings for @theme theme', ['@theme' => $theme->info['name']])],
Chris@0 245 ];
Chris@0 246 }
Chris@0 247 if (!empty($theme->status)) {
Chris@0 248 if (!$theme->is_default) {
Chris@0 249 $theme_uninstallable = TRUE;
Chris@0 250 if ($theme->getName() == $admin_theme) {
Chris@0 251 $theme_uninstallable = FALSE;
Chris@0 252 }
Chris@0 253 // Check it isn't the base of theme of an installed theme.
Chris@0 254 foreach ($theme->required_by as $themename => $dependency) {
Chris@0 255 if (!empty($themes[$themename]->status)) {
Chris@0 256 $theme_uninstallable = FALSE;
Chris@0 257 }
Chris@0 258 }
Chris@0 259 if ($theme_uninstallable) {
Chris@0 260 $theme->operations[] = [
Chris@0 261 'title' => $this->t('Uninstall'),
Chris@0 262 'url' => Url::fromRoute('system.theme_uninstall'),
Chris@0 263 'query' => $query,
Chris@0 264 'attributes' => ['title' => $this->t('Uninstall @theme theme', ['@theme' => $theme->info['name']])],
Chris@0 265 ];
Chris@0 266 }
Chris@0 267 $theme->operations[] = [
Chris@0 268 'title' => $this->t('Set as default'),
Chris@0 269 'url' => Url::fromRoute('system.theme_set_default'),
Chris@0 270 'query' => $query,
Chris@0 271 'attributes' => ['title' => $this->t('Set @theme as default theme', ['@theme' => $theme->info['name']])],
Chris@0 272 ];
Chris@0 273 }
Chris@0 274 $admin_theme_options[$theme->getName()] = $theme->info['name'];
Chris@0 275 }
Chris@0 276 else {
Chris@0 277 $theme->operations[] = [
Chris@0 278 'title' => $this->t('Install'),
Chris@0 279 'url' => Url::fromRoute('system.theme_install'),
Chris@0 280 'query' => $query,
Chris@0 281 'attributes' => ['title' => $this->t('Install @theme theme', ['@theme' => $theme->info['name']])],
Chris@0 282 ];
Chris@0 283 $theme->operations[] = [
Chris@0 284 'title' => $this->t('Install and set as default'),
Chris@0 285 'url' => Url::fromRoute('system.theme_set_default'),
Chris@0 286 'query' => $query,
Chris@0 287 'attributes' => ['title' => $this->t('Install @theme as default theme', ['@theme' => $theme->info['name']])],
Chris@0 288 ];
Chris@0 289 }
Chris@0 290 }
Chris@0 291
Chris@0 292 // Add notes to default and administration theme.
Chris@0 293 $theme->notes = [];
Chris@0 294 if ($theme->is_default) {
Chris@0 295 $theme->notes[] = $this->t('default theme');
Chris@0 296 }
Chris@0 297 if ($theme->is_admin) {
Chris@0 298 $theme->notes[] = $this->t('administration theme');
Chris@0 299 }
Chris@0 300
Chris@0 301 // Sort installed and uninstalled themes into their own groups.
Chris@0 302 $theme_groups[$theme->status ? 'installed' : 'uninstalled'][] = $theme;
Chris@0 303 }
Chris@0 304
Chris@0 305 // There are two possible theme groups.
Chris@0 306 $theme_group_titles = [
Chris@0 307 'installed' => $this->formatPlural(count($theme_groups['installed']), 'Installed theme', 'Installed themes'),
Chris@0 308 ];
Chris@0 309 if (!empty($theme_groups['uninstalled'])) {
Chris@0 310 $theme_group_titles['uninstalled'] = $this->formatPlural(count($theme_groups['uninstalled']), 'Uninstalled theme', 'Uninstalled themes');
Chris@0 311 }
Chris@0 312
Chris@0 313 uasort($theme_groups['installed'], 'system_sort_themes');
Chris@0 314 $this->moduleHandler()->alter('system_themes_page', $theme_groups);
Chris@0 315
Chris@0 316 $build = [];
Chris@0 317 $build[] = [
Chris@0 318 '#theme' => 'system_themes_page',
Chris@0 319 '#theme_groups' => $theme_groups,
Chris@0 320 '#theme_group_titles' => $theme_group_titles,
Chris@0 321 ];
Chris@0 322 $build[] = $this->formBuilder->getForm('Drupal\system\Form\ThemeAdminForm', $admin_theme_options);
Chris@0 323
Chris@0 324 return $build;
Chris@0 325 }
Chris@0 326
Chris@0 327 }