Newer
Older
Dries Buytaert
committed
<?php
Dries Buytaert
committed
/**
* @file
* Admin page callbacks for the system module.
*/
/**
* Menu callback; Provide the administration overview page.
Dries Buytaert
committed
*/
function system_main_admin_page($arg = NULL) {
// If we received an argument, they probably meant some other page.
// Let's 404 them since the menu system cannot be told we do not
// accept arguments.
if (isset($arg) && substr($arg, 0, 3) != 'by-') {
return drupal_not_found();
}
// Check for status report errors.
Gábor Hojtsy
committed
if (system_status(TRUE) && user_access('administer site configuration')) {
drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
Dries Buytaert
committed
}
$blocks = array();
Dries Buytaert
committed
if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin' AND module = 'system'")->fetchAssoc()) {
Gábor Hojtsy
committed
$result = db_query("
SELECT m.*, ml.*
FROM {menu_links} ml
INNER JOIN {menu_router} m ON ml.router_path = m.path
Dries Buytaert
committed
WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
foreach ($result as $item) {
Gábor Hojtsy
committed
_menu_link_translate($item);
if (!$item['access']) {
continue;
}
// The link 'description' either derived from the hook_menu 'description'
// or entered by the user via menu module is saved as the title attribute.
if (!empty($item['localized_options']['attributes']['title'])) {
$item['description'] = $item['localized_options']['attributes']['title'];
Gábor Hojtsy
committed
}
$block = $item;
$block['content'] = '';
Angie Byron
committed
$block['show'] = FALSE;
Gábor Hojtsy
committed
if ($item['block_callback'] && function_exists($item['block_callback'])) {
$function = $item['block_callback'];
$block['content'] .= $function();
}
Angie Byron
committed
$content = system_admin_menu_block($item);
if ((isset($item['page_callback']) && !in_array($item['page_callback'], array('system_admin_menu_block_page', 'system_admin_config_page', 'system_settings_overview'))) || count($content)) {
// Only show blocks for items which are not containers, or those which
// are containers and do have items we can show.
$block['show'] = TRUE;
if (empty($content)) {
// If no items found below, but access checks did not fail, show.
$block['title'] = l($item['title'], $item['href'], $item['localized_options']);
Angie Byron
committed
}
else {
// Theme items below.
Dries Buytaert
committed
$block['content'] .= theme('admin_block_content', array('content' => $content));
Angie Byron
committed
}
}
Gábor Hojtsy
committed
// Prepare for sorting as in function _menu_tree_check_access().
// The weight is offset so it is always positive, with a uniform 5-digits.
$blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
Dries Buytaert
committed
}
}
Gábor Hojtsy
committed
if ($blocks) {
ksort($blocks);
Dries Buytaert
committed
return theme('admin_page', array('blocks' => $blocks));
Gábor Hojtsy
committed
}
else {
return t('You do not have any administrative items.');
}
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Menu callback; Provide the administration overview page.
*/
function system_admin_config_page() {
// Check for status report errors.
if (system_status(TRUE) && user_access('administer site configuration')) {
drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
}
$blocks = array();
if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin/config' AND module = 'system'")->fetchAssoc()) {
$result = db_query("
SELECT m.*, ml.*
FROM {menu_links} ml
INNER JOIN {menu_router} m ON ml.router_path = m.path
WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
foreach ($result as $item) {
_menu_link_translate($item);
if (!$item['access']) {
continue;
}
// The link 'description' either derived from the hook_menu 'description'
// or entered by the user via menu module is saved as the title attribute.
if (!empty($item['localized_options']['attributes']['title'])) {
$item['description'] = $item['localized_options']['attributes']['title'];
}
$block = $item;
$block['content'] = '';
Angie Byron
committed
$block['show'] = TRUE;
Dries Buytaert
committed
if ($item['block_callback'] && function_exists($item['block_callback'])) {
$function = $item['block_callback'];
$block['content'] .= $function();
}
Dries Buytaert
committed
$block['content'] .= theme('admin_block_content', array('content' => system_admin_menu_block($item)));
Dries Buytaert
committed
// Prepare for sorting as in function _menu_tree_check_access().
// The weight is offset so it is always positive, with a uniform 5-digits.
$blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
}
}
if ($blocks) {
ksort($blocks);
Dries Buytaert
committed
return theme('admin_page', array('blocks' => $blocks));
Dries Buytaert
committed
}
else {
return t('You do not have any administrative items.');
}
}
Dries Buytaert
committed
/**
* Provide a single block from the administration menu as a page.
* This function is often a destination for these blocks.
Dries Buytaert
committed
* For example, 'admin/structure/types' needs to have a destination to be valid
Dries Buytaert
committed
* in the Drupal menu system, but too much information there might be
* hidden, so we supply the contents of the block.
*
* @return
* The output HTML.
Dries Buytaert
committed
*/
function system_admin_menu_block_page() {
$item = menu_get_item();
Dries Buytaert
committed
if ($content = system_admin_menu_block($item)) {
Dries Buytaert
committed
$output = theme('admin_block_content', array('content' => $content));
Dries Buytaert
committed
}
else {
$output = t('You do not have any administrative items.');
}
Dries Buytaert
committed
return $output;
}
/**
* Menu callback; prints a listing of admin tasks for each installed module.
*/
function system_admin_by_module() {
Angie Byron
committed
$module_info = system_get_info('module');
$menu_items = array();
Gábor Hojtsy
committed
$help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
Angie Byron
committed
foreach ($module_info as $module => $info) {
if ($module == 'help') {
continue;
}
$admin_tasks = system_get_module_admin_tasks($module);
// Only display a section if there are any available tasks.
if (count($admin_tasks)) {
// Check for help links.
Gábor Hojtsy
committed
if ($help_arg && module_invoke($module, 'help', "admin/help#$module", $help_arg)) {
$admin_tasks[100] = l(t('Get help'), "admin/help/$module");
}
// Sort.
ksort($admin_tasks);
Angie Byron
committed
$menu_items[$info['name']] = array($info['description'], $admin_tasks);
Dries Buytaert
committed
return theme('system_admin_by_module', array('menu_items' => $menu_items));
}
/**
* Menu callback; displays a module's settings page.
*/
function system_settings_overview() {
// Check database setup if necessary
if (function_exists('db_check_setup') && empty($_POST)) {
db_check_setup();
}
Dries Buytaert
committed
$item = menu_get_item('admin/config');
$content = system_admin_menu_block($item);
Dries Buytaert
committed
$output = theme('admin_block_content', array('content' => $content));
return $output;
}
/**
Dries Buytaert
committed
* Retrieve the list of themes that are not hidden.
Dries Buytaert
committed
function _system_theme_list() {
Angie Byron
committed
// Get current list of themes.
Angie Byron
committed
$themes = system_rebuild_theme_data();
Angie Byron
committed
// Remove hidden themes from the display list.
foreach ($themes as $theme_key => $theme) {
if (!empty($theme->info['hidden'])) {
unset($themes[$theme_key]);
}
}
Gábor Hojtsy
committed
uasort($themes, 'system_sort_modules_by_info_name');
Dries Buytaert
committed
return $themes;
}
Gábor Hojtsy
committed
Dries Buytaert
committed
/**
* Menu callback; displays a listing of all themes.
*/
function system_themes_page() {
// Get current list of themes.
$themes =& _system_theme_list();
$theme_default = variable_get('theme_default', 'garland');
$theme_groups = array();
foreach ($themes as &$theme) {
$admin_theme_options[$theme->name] = $theme->info['name'];
$theme->is_default = ($theme->name == $theme_default);
Dries Buytaert
committed
// Identify theme screenshot.
$theme->screenshot = NULL;
Angie Byron
committed
// 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;
Angie Byron
committed
}
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'])) {
Dries Buytaert
committed
$theme->screenshot = array(
'path' => $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')),
'getsize' => FALSE,
);
break;
}
}
Gábor Hojtsy
committed
Dries Buytaert
committed
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;
Gábor Hojtsy
committed
}
Dries Buytaert
committed
$query['token'] = drupal_get_token('system-theme-operation-link');
$theme->operations = array();
if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php) {
// 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']))),
);
Dries Buytaert
committed
if (!empty($theme->status)) {
if (!$theme->is_default) {
$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']))),
);
}
}
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']))),
);
Dries Buytaert
committed
// 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');
}
// Sort enabled and disabled themes into their own groups.
$theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme;
Dries Buytaert
committed
// 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');
};
Dries Buytaert
committed
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' => 'fieldset',
'#title' => t('Administration theme'),
);
$form['admin_theme']['admin_theme'] = array(
'#type' => 'select',
Dries Buytaert
committed
'#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' => variable_get('admin_theme', 0),
);
$form['admin_theme']['node_admin_theme'] = array(
'#type' => 'checkbox',
'#title' => t('Use the administration theme when editing or creating content'),
'#default_value' => variable_get('node_admin_theme', '0'),
);
Dries Buytaert
committed
$form['admin_theme']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
return $form;
}
/**
Dries Buytaert
committed
* Process system_themes_admin_form form submissions.
*/
Dries Buytaert
committed
function system_themes_admin_form_submit($form, &$form_state) {
drupal_set_message(t('The configuration options have been saved.'));
variable_set('admin_theme', $form_state['values']['admin_theme']);
variable_set('node_admin_theme', $form_state['values']['node_admin_theme']);
}
Dries Buytaert
committed
/**
* Menu callback; Enables a theme.
*/
function system_theme_enable() {
if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) {
$theme = $_REQUEST['theme'];
// Get current list of themes.
$themes =& _system_theme_list();
// Check if the specified theme is one recognized by the system.
if (!empty($themes[$theme])) {
theme_enable(array($theme));
drupal_set_message(t('The %theme theme has been enabled.', array('%theme' => $themes[$theme]->info['name'])));
}
else {
drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
Dries Buytaert
committed
drupal_goto('admin/appearance');
Dries Buytaert
committed
return drupal_access_denied();
}
Dries Buytaert
committed
/**
* Menu callback; Disables a theme.
*/
function system_theme_disable() {
if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) {
$theme = $_REQUEST['theme'];
// Get current list of themes.
$themes =& _system_theme_list();
// Check if the specified theme is one recognized by the system.
if (!empty($themes[$theme])) {
if ($theme == variable_get('theme_default', 'garland')) {
// Don't disable the default theme.
drupal_set_message(t('%theme is the default theme and cannot be disabled.', array('%theme' => $themes[$theme]->info['name'])), 'error');
}
else {
theme_disable(array($theme));
drupal_set_message(t('The %theme theme has been disabled.', array('%theme' => $themes[$theme]->info['name'])));
Dries Buytaert
committed
else {
drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
Dries Buytaert
committed
drupal_goto('admin/appearance');
Dries Buytaert
committed
return drupal_access_denied();
}
Dries Buytaert
committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
/**
* Menu callback; Set the default theme.
*/
function system_theme_default() {
if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) {
$theme = $_REQUEST['theme'];
// Get current list of themes.
$themes =& _system_theme_list();
// 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.
variable_set('theme_default', $theme);
// The status message depends on whether an admin theme is currently in use.
$admin_theme = variable_get('admin_theme', 0);
if ($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');
}
drupal_goto('admin/appearance');
}
return drupal_access_denied();
}
/**
* Form builder; display theme configuration for entire site and individual themes.
*
* @param $key
* A theme name.
* @return
* The form structure.
* @ingroup forms
Gábor Hojtsy
committed
* @see system_theme_settings_submit()
function system_theme_settings($form, &$form_state, $key = '') {
Dries Buytaert
committed
// Default settings are defined in theme_get_setting() in includes/theme.inc
if ($key) {
Dries Buytaert
committed
$var = 'theme_' . $key . '_settings';
Angie Byron
committed
$themes = system_rebuild_theme_data();
$features = $themes[$key]->info['features'];
}
else {
$var = 'theme_settings';
}
$form['var'] = array('#type' => 'hidden', '#value' => $var);
// Toggle settings
$toggles = array(
Dries Buytaert
committed
'logo' => t('Logo'),
'name' => t('Site name'),
'slogan' => t('Site slogan'),
'node_user_picture' => t('User pictures in posts'),
'comment_user_picture' => t('User pictures in comments'),
'comment_user_verification' => t('User verification status in comments'),
'favicon' => t('Shortcut icon'),
'main_menu' => t('Main menu'),
'secondary_menu' => t('Secondary menu'),
);
// Some features are not always available
$disabled = array();
if (!variable_get('user_pictures', 0)) {
$disabled['toggle_node_user_picture'] = TRUE;
$disabled['toggle_comment_user_picture'] = TRUE;
}
$form['theme_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Toggle display'),
'#description' => t('Enable or disable the display of certain page elements.'),
);
foreach ($toggles as $name => $title) {
if ((!$key) || in_array($name, $features)) {
Dries Buytaert
committed
$form['theme_settings']['toggle_' . $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => theme_get_setting('toggle_' . $name, $key));
Gábor Hojtsy
committed
// Disable checkboxes for features not supported in the current configuration.
if (isset($disabled['toggle_' . $name])) {
$form['theme_settings']['toggle_' . $name]['#disabled'] = TRUE;
}
}
}
Angie Byron
committed
if (!element_children($form['theme_settings'])) {
// If there is no element in the theme settings fieldset then do not show
// it -- but keep it in the form if another module wants to alter.
$form['theme_settings']['#access'] = FALSE;
}
// Logo settings
if ((!$key) || in_array('logo', $features)) {
$form['logo'] = array(
'#type' => 'fieldset',
'#title' => t('Logo image settings'),
'#description' => t('If toggled on, the following logo will be displayed.'),
'#attributes' => array('class' => array('theme-settings-bottom')),
Angie Byron
committed
$form['logo']['default_logo'] = array(
'#type' => 'checkbox',
'#title' => t('Use the default logo'),
Dries Buytaert
committed
'#default_value' => theme_get_setting('default_logo', $key),
'#tree' => FALSE,
'#description' => t('Check here if you want the theme to use the logo supplied with it.')
);
Dries Buytaert
committed
$form['logo']['settings'] = array(
'#type' => 'container',
'#states' => array(
// Hide the logo settings when using the default logo.
'invisible' => array(
'input[name="default_logo"]' => array('checked' => TRUE),
),
),
);
Angie Byron
committed
$logo_path = theme_get_setting('logo_path', $key);
// If $logo_path is a public:// URI, display the path relative to the files
// directory; stream wrappers are not end-user friendly.
if (file_uri_scheme($logo_path) == 'public') {
$logo_path = file_uri_target($logo_path);
}
Dries Buytaert
committed
$form['logo']['settings']['logo_path'] = array(
'#type' => 'textfield',
'#title' => t('Path to custom logo'),
Angie Byron
committed
'#default_value' => $logo_path,
Dries Buytaert
committed
'#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'),
);
$form['logo']['settings']['logo_upload'] = array(
'#type' => 'file',
'#title' => t('Upload logo image'),
'#maxlength' => 40,
'#description' => t("If you don't have direct file access to the server, use this field to upload your logo.")
);
}
if ((!$key) || in_array('favicon', $features)) {
$form['favicon'] = array(
'#type' => 'fieldset',
'#title' => t('Shortcut icon settings'),
Angie Byron
committed
'#description' => t("Your shortcut icon, or 'favicon', is displayed in the address bar and bookmarks of most browsers."),
);
$form['favicon']['default_favicon'] = array(
'#type' => 'checkbox',
'#title' => t('Use the default shortcut icon.'),
Dries Buytaert
committed
'#default_value' => theme_get_setting('default_favicon', $key),
'#description' => t('Check here if you want the theme to use the default shortcut icon.')
);
Dries Buytaert
committed
$form['favicon']['settings'] = array(
'#type' => 'container',
'#states' => array(
// Hide the favicon settings when using the default favicon.
'invisible' => array(
'input[name="default_favicon"]' => array('checked' => TRUE),
),
),
);
Angie Byron
committed
$favicon_path = theme_get_setting('favicon_path', $key);
// If $favicon_path is a public:// URI, display the path relative to the
// files directory; stream wrappers are not end-user friendly.
if (file_uri_scheme($favicon_path) == 'public') {
$favicon_path = file_uri_target($favicon_path);
}
Dries Buytaert
committed
$form['favicon']['settings']['favicon_path'] = array(
'#type' => 'textfield',
'#title' => t('Path to custom icon'),
Angie Byron
committed
'#default_value' => $favicon_path,
'#description' => t('The path to the image file you would like to use as your custom shortcut icon.')
);
Dries Buytaert
committed
$form['favicon']['settings']['favicon_upload'] = array(
'#type' => 'file',
'#title' => t('Upload icon image'),
'#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon.")
);
}
if ($key) {
Gábor Hojtsy
committed
// Call engine-specific settings.
$function = $themes[$key]->prefix . '_engine_settings';
if (function_exists($function)) {
Dries Buytaert
committed
$form['engine_specific'] = array(
'#type' => 'fieldset',
'#title' => t('Theme-engine-specific settings'),
'#description' => t('These settings only exist for the themes based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)),
);
$function($form, $form_state);
Gábor Hojtsy
committed
}
Dries Buytaert
committed
// Create a list which includes the current theme and all its base themes.
if (isset($themes[$key]->base_themes)) {
$theme_keys = array_keys($themes[$key]->base_themes);
$theme_keys[] = $key;
Gábor Hojtsy
committed
}
Dries Buytaert
committed
else {
$theme_keys = array($key);
}
// Save the name of the current theme (if any), so that we can temporarily
// override the current theme and allow theme_get_setting() to work
// without having to pass the theme name to it.
$default_theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : NULL;
$GLOBALS['theme_key'] = $key;
// Process the theme and all its base themes.
foreach ($theme_keys as $theme) {
// Include the theme-settings.php file.
$filename = DRUPAL_ROOT . '/' . str_replace("/$theme.info", '', $themes[$theme]->filename) . '/theme-settings.php';
if (file_exists($filename)) {
require_once $filename;
}
// Call theme-specific settings.
$function = $theme . '_form_system_theme_settings_alter';
if (function_exists($function)) {
$function($form, $form_state);
Dries Buytaert
committed
// Restore the original current theme.
if (!is_null($default_theme)) {
$GLOBALS['theme_key'] = $default_theme;
}
else {
unset($GLOBALS['theme_key']);
}
Dries Buytaert
committed
$form = system_settings_form($form, FALSE);
// We don't want to call system_settings_form_submit(), so change #submit.
Dries Buytaert
committed
array_pop($form['#submit']);
$form['#submit'][] = 'system_theme_settings_submit';
Angie Byron
committed
$form['#validate'][] = 'system_theme_settings_validate';
return $form;
}
Angie Byron
committed
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
/**
* Validator for the system_theme_settings() form.
*/
function system_theme_settings_validate($form, &$form_state) {
// Handle file uploads.
$validators = array('file_validate_is_image' => array());
// Check for a new uploaded logo.
$file = file_save_upload('logo_upload', $validators);
if (isset($file)) {
// File upload was attempted.
if ($file) {
// Put the temporary file in form_values so we can save it on submit.
$form_state['values']['logo_upload'] = $file;
}
else {
// File upload failed.
form_set_error('logo_upload', t('The logo could not be uploaded.'));
}
}
// Check for a new uploaded favicon.
$file = file_save_upload('favicon_upload');
if (isset($file)) {
// File upload was attempted.
if ($file) {
// Put the temporary file in form_values so we can save it on submit.
$form_state['values']['favicon_upload'] = $file;
}
else {
// File upload failed.
form_set_error('logo_upload', t('The favicon could not be uploaded.'));
}
}
// If the user provided a path for a logo or favicon file, make sure a file
// exists at that path.
if ($form_state['values']['logo_path']) {
$path = _system_theme_settings_validate_path($form_state['values']['logo_path']);
if (!$path) {
form_set_error('logo_path', t('The custom logo path is invalid.'));
}
}
if ($form_state['values']['favicon_path']) {
$path = _system_theme_settings_validate_path($form_state['values']['favicon_path']);
if (!$path) {
form_set_error('favicon_path', t('The custom favicon path is invalid.'));
}
}
}
/**
* Helper function for the system_theme_settings form.
*
* Attempts to validate normal system paths, paths relative to the public files
* directory, or stream wrapper URIs. If the given path is any of the above,
* returns a valid path or URI that the theme system can display.
*
* @param $path
* A path relative to the Drupal root or to the public files directory, or
* a stream wrapper URI.
* @return mixed
* A valid path that can be displayed through the theme system, or FALSE if
* the path could not be validated.
*/
function _system_theme_settings_validate_path($path) {
if (drupal_realpath($path)) {
// The path is relative to the Drupal root, or is a valid URI.
return $path;
}
$uri = 'public://' . $path;
if (file_exists($uri)) {
return $uri;
}
return FALSE;
}
/**
* Process system_theme_settings form submissions.
*/
function system_theme_settings_submit($form, &$form_state) {
$values = $form_state['values'];
Angie Byron
committed
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
// If the user uploaded a new logo or favicon, save it to a permanent location
// and use it in place of the default theme-provided file.
if ($file = $values['logo_upload']) {
unset($values['logo_upload']);
$filename = file_unmanaged_copy($file->uri);
$values['default_logo'] = 0;
$values['logo_path'] = $filename;
$values['toggle_logo'] = 1;
}
if ($file = $values['favicon_upload']) {
unset($values['favicon_upload']);
$filename = file_unmanaged_copy($file->uri);
$values['default_favicon'] = 0;
$values['favicon_path'] = $filename;
$values['toggle_favicon'] = 1;
}
// If the user entered a path relative to the system files directory for
// a logo or favicon, store a public:// URI so the theme system can handle it.
if (!empty($values['logo_path'])) {
$values['logo_path'] = _system_theme_settings_validate_path($values['logo_path']);
}
if (!empty($values['favicon_path'])) {
$values['favicon_path'] = _system_theme_settings_validate_path($values['favicon_path']);
}
if (empty($values['default_favicon']) && !empty($values['favicon_path'])) {
$values['favicon_mimetype'] = file_get_mimetype($values['favicon_path']);
}
$key = $values['var'];
// Exclude unnecessary elements before saving.
unset($values['var'], $values['submit'], $values['reset'], $values['form_id'], $values['op'], $values['form_build_id'], $values['form_token']);
variable_set($key, $values);
drupal_set_message(t('The configuration options have been saved.'));
cache_clear_all();
}
Dries Buytaert
committed
/**
* Recursively check compatibility.
*
* @param $incompatible
Dries Buytaert
committed
* 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
Dries Buytaert
committed
* Returns TRUE if an incompatible file is found, NULL (no return value)
* otherwise.
Dries Buytaert
committed
*/
function _system_is_incompatible(&$incompatible, $files, $file) {
if (isset($incompatible[$file->name])) {
return TRUE;
}
Dries Buytaert
committed
// Recursively traverse required modules, looking for incompatible modules.
foreach ($file->requires as $requires) {
if (isset($files[$requires]) && _system_is_incompatible($incompatible, $files, $files[$requires])) {
Dries Buytaert
committed
$incompatible[$file->name] = TRUE;
return TRUE;
}
}
}
/**
* Menu callback; provides module enable/disable interface.
*
* The list of modules gets populated by module.info files, which contain each module's name,
Dries Buytaert
committed
* description and information about which modules it requires.
* @see drupal_parse_info_file for information on module.info descriptors.
*
Dries Buytaert
committed
* Dependency checking is performed to ensure that a module:
* - can not be enabled if there are disabled modules it requires.
* - can not be disabled if there are enabled modules which depend on it.
* @param $form_state
* An associative array containing the current state of the form.
* @ingroup forms
Gábor Hojtsy
committed
* @see theme_system_modules()
* @see system_modules_submit()
* @return
* The form array.
*/
function system_modules($form, $form_state = array()) {
// Get current list of modules.
Angie Byron
committed
$files = system_rebuild_module_data();
// Remove hidden modules from display list.
foreach ($files as $filename => $file) {
if (!empty($file->info['hidden']) || !empty($file->info['required'])) {
unset($files[$filename]);
}
}
uasort($files, 'system_sort_modules_by_info_name');
Dries Buytaert
committed
// If the modules form was submitted, then system_modules_submit() runs first
// and if there are unfilled required modules, then $form_state['storage'] is
Dries Buytaert
committed
// filled, triggering a rebuild. In this case we need to display a
// confirmation form.
if (!empty($form_state['storage'])) {
return system_modules_confirm_form($files, $form_state['storage']);
}
Dries Buytaert
committed
$modules = array();
$form['modules'] = array('#tree' => TRUE);
Dries Buytaert
committed
Dries Buytaert
committed
// Used when checking if module implements a help page.
$help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
// Iterate through each of the modules.
foreach ($files as $filename => $module) {
$extra = array();
$extra['enabled'] = (bool) $module->status;
Dries Buytaert
committed
// If this module requires other modules, add them to the array.
foreach ($module->requires as $requires => $v) {
if (!isset($files[$requires])) {
$extra['requires'][$requires] = t('@module (<span class="admin-missing">missing</span>)', array('@module' => drupal_ucfirst($requires)));
Dries Buytaert
committed
$extra['disabled'] = TRUE;
}
else {
$requires_name = $files[$requires]->info['name'];
Angie Byron
committed
if ($incompatible_version = drupal_check_incompatibility($v, str_replace(DRUPAL_CORE_COMPATIBILITY . '-', '', $files[$requires]->info['version']))) {
$extra['requires'][$requires] = t('@module (<span class="admin-missing">incompatible with</span> version @version)', array(
'@module' => $requires_name . $incompatible_version,
'@version' => $files[$requires]->info['version'],
));
$extra['disabled'] = TRUE;
Angie Byron
committed
elseif ($files[$requires]->status) {
$extra['requires'][$requires] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $requires_name));
}
else {
$extra['requires'][$requires] = t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => $requires_name));
}
// Generate link for module's help page, if there is one.
Dries Buytaert
committed
if ($help_arg && $module->status && in_array($filename, module_implements('help'))) {
if (module_invoke($filename, 'help', "admin/help#$filename", $help_arg)) {
Dries Buytaert
committed
$extra['links']['help'] = array(
'#type' => 'link',
'#title' => t('Help'),
'#href' => "admin/help/$filename",
'#options' => array('attributes' => array('class' => array('module-link', 'module-link-help'), 'title' => t('Help'))),
);
Dries Buytaert
committed
// Generate link for module's permission, if the user has access to it.
if ($module->status && user_access('administer permissions') && in_array($filename, module_implements('permission'))) {
$extra['links']['permissions'] = array(
'#type' => 'link',
'#title' => t('Permissions'),
'#href' => 'admin/config/people/permissions',
'#options' => array('fragment' => 'module-' . $filename, 'attributes' => array('class' => array('module-link', 'module-link-permissions'), 'title' => t('Configure permissions'))),
);
}
// Generate link for module's configuration page, if the module provides
// one.
if ($module->status && isset($module->info['configure'])) {
$configure_link = menu_get_item($module->info['configure']);
if ($configure_link['access']) {
$extra['links']['configure'] = array(
'#type' => 'link',
'#title' => t('Configure'),
'#href' => $configure_link['href'],
'#options' => array('attributes' => array('class' => array('module-link', 'module-link-configure'), 'title' => $configure_link['description'])),
);
}
}
Dries Buytaert
committed
// Mark dependents disabled so the user cannot remove required modules.
$dependents = array();
Dries Buytaert
committed
// If this module is required by other modules, list those, and then make it
// impossible to disable this one.
foreach ($module->required_by as $required_by => $v) {
// Hidden modules are unset already.
Dries Buytaert
committed
if (isset($files[$required_by])) {
if ($files[$required_by]->status == 1) {
$extra['required_by'][] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $files[$required_by]->info['name']));
$extra['disabled'] = TRUE;
}
else {
Dries Buytaert
committed
$extra['required_by'][] = t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => $files[$required_by]->info['name']));
$form['modules'][$module->info['package']][$filename] = _system_modules_build_row($module->info, $extra);
// Add basic information to the fieldsets.
foreach (element_children($form['modules']) as $package) {
$form['modules'][$package] += array(
'#type' => 'fieldset',
'#title' => t($package),
'#collapsible' => TRUE,
'#theme' => 'system_modules_fieldset',
'#header' => array(
array('data' => t('Enabled'), 'class' => array('checkbox')),
t('Name'),
t('Version'),
t('Description'),
Dries Buytaert
committed
array('data' => t('Operations'), 'colspan' => 3),
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
$form['#action'] = url('admin/config/modules/list/confirm');
return $form;
}
/**
Gábor Hojtsy
committed
* 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']);
}
Dries Buytaert
committed
/**
* 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']);
}
/**
* Build a table row for the system modules page.
function _system_modules_build_row($info, $extra) {
// Add in the defaults.
$extra += array(
Dries Buytaert
committed
'requires' => array(),
'required_by' => array(),
'disabled' => FALSE,
'enabled' => FALSE,
Dries Buytaert
committed
'links' => array(),
);
$form = array(
'#tree' => TRUE,
);
// Set the basic properties.
$form['name'] = array(
Angie Byron
committed
'#markup' => $info['name'],
);
$form['description'] = array(
'#markup' => t($info['description']),
);
$form['version'] = array(
'#markup' => $info['version'],
);