$content));
}
else {
$output = t('You do not have any administrative items.');
}
return $output;
}
/**
* Menu callback; displays a listing of all themes.
*/
function system_themes_page() {
// Get current list of themes.
$themes = system_rebuild_theme_data();
uasort($themes, 'system_sort_modules_by_info_name');
$theme_default = Drupal::config('system.theme')->get('default');
$theme_groups = array();
$admin_theme = Drupal::config('system.theme')->get('admin');
foreach ($themes as &$theme) {
if (!empty($theme->info['hidden'])) {
continue;
}
$theme->is_default = ($theme->name == $theme_default);
// Identify theme screenshot.
$theme->screenshot = NULL;
// Create a list which includes the current theme and all its base themes.
if (isset($themes[$theme->name]->base_themes)) {
$theme_keys = array_keys($themes[$theme->name]->base_themes);
$theme_keys[] = $theme->name;
}
else {
$theme_keys = array($theme->name);
}
// Look for a screenshot in the current theme or in its closest ancestor.
foreach (array_reverse($theme_keys) as $theme_key) {
if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
$theme->screenshot = array(
'uri' => $themes[$theme_key]->info['screenshot'],
'alt' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
'title' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
'attributes' => array('class' => array('screenshot')),
);
break;
}
}
if (empty($theme->status)) {
// Ensure this theme is compatible with this version of core.
// Require the 'content' region to make sure the main page
// content has a common place in all themes.
$theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']));
$theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
// Confirmed that the base theme is available.
$theme->incompatible_base = (isset($theme->info['base theme']) && !isset($themes[$theme->info['base theme']]));
// Confirm that the theme engine is available.
$theme->incompatible_engine = (isset($theme->info['engine']) && !isset($theme->owner));
}
$query['token'] = drupal_get_token('system-theme-operation-link');
$theme->operations = array();
if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
// Create the operations links.
$query['theme'] = $theme->name;
if (drupal_theme_access($theme)) {
$theme->operations[] = array(
'title' => t('Settings'),
'href' => 'admin/appearance/settings/' . $theme->name,
'attributes' => array('title' => t('Settings for !theme theme', array('!theme' => $theme->info['name']))),
);
}
if (!empty($theme->status)) {
if (!$theme->is_default) {
if ($theme->name != $admin_theme) {
$theme->operations[] = array(
'title' => t('Disable'),
'href' => 'admin/appearance/disable',
'query' => $query,
'attributes' => array('title' => t('Disable !theme theme', array('!theme' => $theme->info['name']))),
);
}
$theme->operations[] = array(
'title' => t('Set default'),
'href' => 'admin/appearance/default',
'query' => $query,
'attributes' => array('title' => t('Set !theme as default theme', array('!theme' => $theme->info['name']))),
);
}
$admin_theme_options[$theme->name] = $theme->info['name'];
}
else {
$theme->operations[] = array(
'title' => t('Enable'),
'href' => 'admin/appearance/enable',
'query' => $query,
'attributes' => array('title' => t('Enable !theme theme', array('!theme' => $theme->info['name']))),
);
$theme->operations[] = array(
'title' => t('Enable and set default'),
'href' => 'admin/appearance/default',
'query' => $query,
'attributes' => array('title' => t('Enable !theme as default theme', array('!theme' => $theme->info['name']))),
);
}
}
// Add notes to default and administration theme.
$theme->notes = array();
$theme->classes = array();
if ($theme->is_default) {
$theme->classes[] = 'theme-default';
$theme->notes[] = t('default theme');
}
if ($theme->name == $admin_theme || ($theme->is_default && $admin_theme == '0')) {
$theme->classes[] = 'theme-admin';
$theme->notes[] = t('admin theme');
}
// Sort enabled and disabled themes into their own groups.
$theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme;
}
// There are two possible theme groups.
$theme_group_titles = array(
'enabled' => format_plural(count($theme_groups['enabled']), 'Enabled theme', 'Enabled themes'),
);
if (!empty($theme_groups['disabled'])) {
$theme_group_titles['disabled'] = format_plural(count($theme_groups['disabled']), 'Disabled theme', 'Disabled themes');
}
uasort($theme_groups['enabled'], 'system_sort_themes');
drupal_alter('system_themes_page', $theme_groups);
$admin_form = drupal_get_form('system_themes_admin_form', $admin_theme_options);
return theme('system_themes_page', array('theme_groups' => $theme_groups, 'theme_group_titles' => $theme_group_titles)) . drupal_render($admin_form);
}
/**
* Form to select the administration theme.
*
* @ingroup forms
* @see system_themes_admin_form_submit()
*/
function system_themes_admin_form($form, &$form_state, $theme_options) {
// Administration theme settings.
$form['admin_theme'] = array(
'#type' => 'details',
'#title' => t('Administration theme'),
);
$form['admin_theme']['admin_theme'] = array(
'#type' => 'select',
'#options' => array(0 => t('Default theme')) + $theme_options,
'#title' => t('Administration theme'),
'#description' => t('Choose "Default theme" to always use the same theme as the rest of the site.'),
'#default_value' => Drupal::config('system.theme')->get('admin'),
);
$form['admin_theme']['actions'] = array('#type' => 'actions');
$form['admin_theme']['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
return $form;
}
/**
* Process system_themes_admin_form form submissions.
*/
function system_themes_admin_form_submit($form, &$form_state) {
drupal_set_message(t('The configuration options have been saved.'));
Drupal::config('system.theme')->set('admin', $form_state['values']['admin_theme'])->save();
}
/**
* Menu callback; Set the default theme.
*/
function system_theme_default() {
$request = Drupal::request();
$theme = $request->get('theme');
$token = $request->get('token');
if (!empty($theme) && !empty($token) && drupal_valid_token($token, 'system-theme-operation-link')) {
// Get current list of themes.
$themes = list_themes();
// Check if the specified theme is one recognized by the system.
if (!empty($themes[$theme])) {
// Enable the theme if it is currently disabled.
if (empty($themes[$theme]->status)) {
theme_enable(array($theme));
}
// Set the default theme.
Drupal::config('system.theme')
->set('default', $theme)
->save();
// Rebuild the menu. This duplicates the menu_router_rebuild() in
// theme_enable(). However, modules must know the current default theme in
// order to use this information in hook_menu() or hook_menu_alter()
// implementations, and doing the variable_set() before the theme_enable()
// could result in a race condition where the theme is default but not
// enabled.
menu_router_rebuild();
// The status message depends on whether an admin theme is currently in use:
// a value of 0 means the admin theme is set to be the default theme.
$admin_theme = Drupal::config('system.theme')->get('admin');
if ($admin_theme != 0 && $admin_theme != $theme) {
drupal_set_message(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.', array(
'%admin_theme' => $themes[$admin_theme]->info['name'],
'%selected_theme' => $themes[$theme]->info['name'],
)));
}
else {
drupal_set_message(t('%theme is now the default theme.', array('%theme' => $themes[$theme]->info['name'])));
}
}
else {
drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
}
return new RedirectResponse(url('admin/appearance', array('absolute' => TRUE)));
}
throw new AccessDeniedHttpException();
}
/**
* Recursively check compatibility.
*
* @param $incompatible
* An associative array which at the end of the check contains all
* incompatible files as the keys, their values being TRUE.
* @param $files
* The set of files that will be tested.
* @param $file
* The file at which the check starts.
* @return
* Returns TRUE if an incompatible file is found, NULL (no return value)
* otherwise.
*/
function _system_is_incompatible(&$incompatible, $files, $file) {
if (isset($incompatible[$file->name])) {
return TRUE;
}
// Recursively traverse required modules, looking for incompatible modules.
foreach ($file->requires as $requires) {
if (isset($files[$requires]) && _system_is_incompatible($incompatible, $files, $files[$requires])) {
$incompatible[$file->name] = TRUE;
return TRUE;
}
}
}
/**
* Array sorting callback; sorts modules or themes by their name.
*/
function system_sort_modules_by_info_name($a, $b) {
return strcasecmp($a->info['name'], $b->info['name']);
}
/**
* Array sorting callback; sorts modules or themes by their name.
*/
function system_sort_themes($a, $b) {
if ($a->is_default) {
return -1;
}
if ($b->is_default) {
return 1;
}
return strcasecmp($a->info['name'], $b->info['name']);
}
/**
* Default page callback for batches.
*/
function system_batch_page() {
require_once DRUPAL_ROOT . '/core/includes/batch.inc';
$output = _batch_page();
if ($output === FALSE) {
throw new AccessDeniedHttpException();
}
elseif ($output instanceof Response) {
return $output;
}
elseif (isset($output)) {
// Force a page without blocks or messages to
// display a list of collected messages later.
drupal_set_page_content($output);
$page = element_info('page');
$page['#show_messages'] = FALSE;
return $page;
}
}
/**
* Returns HTML for an administrative block for display.
*
* @param $variables
* An associative array containing:
* - block: An array containing information about the block:
* - show: A Boolean whether to output the block. Defaults to FALSE.
* - title: The block's title.
* - content: (optional) Formatted content for the block.
* - description: (optional) Description of the block. Only output if
* 'content' is not set.
*
* @ingroup themeable
*/
function theme_admin_block($variables) {
$block = $variables['block'];
$output = '';
// Don't display the block if it has no content to display.
if (empty($block['show'])) {
return $output;
}
$output .= '
';
if (!empty($block['title'])) {
$output .= '
' . $block['title'] . '
';
}
if (!empty($block['content'])) {
$output .= '
' . render($block['content']) . '
';
}
else {
$output .= '
' . $block['description'] . '
';
}
$output .= '
';
return $output;
}
/**
* Returns HTML for the content of an administrative block.
*
* @param $variables
* An associative array containing:
* - content: An array containing information about the block. Each element
* of the array represents an administrative menu item, and must at least
* contain the keys 'title', 'href', and 'localized_options', which are
* passed to l(). A 'description' key may also be provided.
*
* @ingroup themeable
*/
function theme_admin_block_content($variables) {
$content = $variables['content'];
$output = '';
if (!empty($content)) {
$class = 'admin-list';
if ($compact = system_admin_compact_mode()) {
$class .= ' compact';
}
$output .= '
';
if (!$compact && isset($item['description'])) {
$output .= '
' . filter_xss_admin($item['description']) . '
';
}
}
$output .= '
';
}
return $output;
}
/**
* Returns HTML for an administrative page.
*
* @param $variables
* An associative array containing:
* - blocks: An array of blocks to display. Each array should include a
* 'title', a 'description', a formatted 'content' and a 'position' which
* will control which container it will be in. This is usually 'left' or
* 'right'.
*
* @ingroup themeable
*/
function theme_admin_page($variables) {
$blocks = $variables['blocks'];
$stripe = 0;
$container = array();
foreach ($blocks as $block) {
if ($block_output = theme('admin_block', array('block' => $block))) {
if (empty($block['position'])) {
// perform automatic striping.
$block['position'] = ++$stripe % 2 ? 'left' : 'right';
}
if (!isset($container[$block['position']])) {
$container[$block['position']] = '';
}
$container[$block['position']] .= $block_output;
}
}
$output = '
';
foreach ($requirements as $requirement) {
// Always use the explicit requirement severity, if defined. Otherwise,
// default to REQUIREMENT_OK in the installer to visually confirm that
// installation requirements are met. And default to REQUIREMENT_INFO to
// denote neutral information without special visualization.
if (isset($requirement['severity'])) {
$severity = $severities[(int) $requirement['severity']];
}
elseif (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install') {
$severity = $severities[REQUIREMENT_OK];
}
else {
$severity = $severities[REQUIREMENT_INFO];
}
$severity['icon'] = '
' . $severity['title'] . '
';
// Output table rows.
$output .= '
';
$output .= '
' . $severity['icon'] . '
';
$output .= '
' . $requirement['title'] . '
';
$output .= '
' . $requirement['value'];
if (!empty($requirement['description'])) {
$output .= '
' . $requirement['description'] . '
';
}
$output .= '
';
}
$output .= '
';
return $output;
}
/**
* Returns HTML for the modules form.
*
* @param $variables
* An associative array containing:
* - form: A render element representing the form.
*
* @ingroup themeable
*/
function theme_system_modules_details($variables) {
$form = $variables['form'];
// Individual table headers.
$rows = array();
// Iterate through all the modules, which are children of this element.
foreach (element_children($form) as $key) {
// Stick the key into $module for easier access.
$module = $form[$key];
// Create the row for the table.
$row = array();
// Add the checkbox into the first cell.
unset($module['enable']['#title']);
$module['#requires'] = array_filter($module['#requires']);
$module['#required_by'] = array_filter($module['#required_by']);
$requires = !empty($module['#requires']);
$required_by = !empty($module['#required_by']);
$version = !empty($module['version']['#markup']);
$row[] = array('class' => array('checkbox'), 'data' => drupal_render($module['enable']));
// Add the module label and expand/collapse functionalty.
$col2 = '';
$row[] = array('class' => array('module'), 'data' => $col2);
// Add the description, along with any modules it requires.
$description = '';
if ($version || $requires || $required_by) {
$description .= '
';
}
$details = array(
'#type' => 'details',
'#title' => ' ' . drupal_render($module['description']) . '',
'#attributes' => array('id' => $module['enable']['#id'] . '-description'),
'#description' => $description,
'#collapsed' => TRUE,
);
$col4 = drupal_render($details);
$row[] = array('class' => array('description', 'expand'), 'data' => $col4);
$rows[] = $row;
}
return theme('table', array('header' => $form['#header'], 'rows' => $rows));
}
/**
* Returns HTML for a message about incompatible modules.
*
* @param $variables
* An associative array containing:
* - message: The form array representing the currently disabled modules.
*
* @ingroup themeable
*/
function theme_system_modules_incompatible($variables) {
return '
' . $variables['message'] . '
';
}
/**
* Returns HTML for a table of currently disabled modules.
*
* @param $variables
* An associative array containing:
* - form: A render element representing the form.
*
* @ingroup themeable
*/
function theme_system_modules_uninstall($variables) {
$form = $variables['form'];
// No theming for the confirm form.
if (isset($form['confirm'])) {
return drupal_render($form);
}
// Table headers.
$header = array(t('Uninstall'),
t('Name'),
t('Description'),
);
// Display table.
$rows = array();
foreach (element_children($form['modules']) as $module) {
if (!empty($form['modules'][$module]['#dependents'])) {
$disabled_message = format_plural(count($form['modules'][$module]['#dependents']),
'To uninstall @module, the following module must be uninstalled first: @required_modules',
'To uninstall @module, the following modules must be uninstalled first: @required_modules',
array('@module' => $form['modules'][$module]['#module_name'], '@required_modules' => implode(', ', $form['modules'][$module]['#dependents'])));
$disabled_message = '
' . $disabled_message . '
';
}
else {
$disabled_message = '';
}
$rows[] = array(
array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'),
'',
array('data' => drupal_render($form['modules'][$module]['description']) . $disabled_message, 'class' => array('description')),
);
}
$output = theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No modules are available to uninstall.')));
$output .= drupal_render_children($form);
return $output;
}
/**
* Returns HTML for the Appearance page.
*
* @param $variables
* An associative array containing:
* - theme_groups: An associative array containing groups of themes.
*
* @ingroup themeable
*/
function theme_system_themes_page($variables) {
$theme_groups = $variables['theme_groups'];
$output = '
';
foreach ($variables['theme_group_titles'] as $state => $title) {
if (!count($theme_groups[$state])) {
// Skip this group of themes if no theme is there.
continue;
}
// Start new theme group.
$output .= '
' . t('This theme requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $theme->info['php'], '!php_version' => phpversion())) . '