Newer
Older
Dries Buytaert
committed
<?php
Dries Buytaert
committed
/**
* @file
* Admin page callbacks for the system module.
*/
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 'description' in hook_menu()
// or customized via menu module is used as title attribute.
Dries Buytaert
committed
if (!empty($item['localized_options']['attributes']['title'])) {
$item['description'] = $item['localized_options']['attributes']['title'];
unset($item['localized_options']['attributes']['title']);
Dries Buytaert
committed
}
$block = $item;
$block['content'] = '';
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)));
if (!empty($block['content'])) {
$block['show'] = TRUE;
}
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, organized by module.
function system_admin_index() {
Angie Byron
committed
$module_info = system_get_info('module');
foreach ($module_info as $module => $info) {
Dries Buytaert
committed
$module_info[$module] = new stdClass();
$module_info[$module]->info = $info;
}
uasort($module_info, 'system_sort_modules_by_info_name');
$menu_items = array();
Angie Byron
committed
foreach ($module_info as $module => $info) {
// Only display a section if there are any available tasks.
if ($admin_tasks = system_get_module_admin_tasks($module, $info->info)) {
// Sort links by title.
uasort($admin_tasks, 'system_sort_by_title');
// Move 'Configure permissions' links to the bottom of each section.
$permission_key = "admin/people/permissions#module-$module";
if (isset($admin_tasks[$permission_key])) {
$permission_task = $admin_tasks[$permission_key];
unset($admin_tasks[$permission_key]);
$admin_tasks[$permission_key] = $permission_task;
$menu_items[$info->info['name']] = array($info->info['description'], $admin_tasks);
return theme('system_admin_index', 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
/**
* Menu callback; displays a listing of all themes.
*/
function system_themes_page() {
// Get current list of themes.
Dries Buytaert
committed
$themes = system_rebuild_theme_data();
uasort($themes, 'system_sort_modules_by_info_name');
Dries Buytaert
committed
$theme_default = variable_get('theme_default', 'bartik');
Dries Buytaert
committed
$theme_groups = array();
foreach ($themes as &$theme) {
if (!empty($theme->info['hidden'])) {
continue;
}
Dries Buytaert
committed
$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']))),
);
$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']))),
);
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');
Angie Byron
committed
}
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']['actions'] = array('#type' => 'actions');
$form['admin_theme']['actions']['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 = list_themes();
Dries Buytaert
committed
// 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 = list_themes();
Dries Buytaert
committed
// Check if the specified theme is one recognized by the system.
if (!empty($themes[$theme])) {
if ($theme == variable_get('theme_default', 'bartik')) {
Dries Buytaert
committed
// 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
/**
* 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 = list_themes();
Dries Buytaert
committed
// 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);
Dries Buytaert
committed
// 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.
Dries Buytaert
committed
$admin_theme = variable_get('admin_theme', 0);
Dries Buytaert
committed
if ($admin_theme != 0 && $admin_theme != $theme) {
Dries Buytaert
committed
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;
}
Dries Buytaert
committed
if (!module_exists('comment')) {
$disabled['toggle_comment_user_picture'] = TRUE;
$disabled['toggle_comment_user_verification'] = 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.
Dries Buytaert
committed
if (isset($default_theme)) {
Dries Buytaert
committed
$GLOBALS['theme_key'] = $default_theme;
}
else {
unset($GLOBALS['theme_key']);
}
Dries Buytaert
committed
$form = system_settings_form($form);
// 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
/**
* 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.'));
}
}
$validators = array('file_validate_extensions' => array('ico png gif jpg jpeg apng svg'));
Angie Byron
committed
// Check for a new uploaded favicon.
$file = file_save_upload('favicon_upload', $validators);
Angie Byron
committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
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
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
// 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.
*
Dries Buytaert
committed
* The list of modules gets populated by module.info files, which contain each
* module's name, 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.
Dries Buytaert
committed
*
* @return
* The form array.
*
* @ingroup forms
Gábor Hojtsy
committed
* @see theme_system_modules()
* @see system_modules_submit()
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.
Angie Byron
committed
$visible_files = $files;
foreach ($visible_files as $filename => $file) {
Angie Byron
committed
if (!empty($file->info['hidden'])) {
Angie Byron
committed
unset($visible_files[$filename]);
}
}
Angie Byron
committed
uasort($visible_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'])) {
Angie Byron
committed
return system_modules_confirm_form($visible_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;
Angie Byron
committed
// Used when displaying modules that are required by the install profile.
require_once DRUPAL_ROOT . '/includes/install.inc';
$distribution_name = check_plain(drupal_install_profile_distribution_name());
// Iterate through each of the modules.
Angie Byron
committed
foreach ($visible_files as $filename => $module) {
$extra = array();
$extra['enabled'] = (bool) $module->status;
Angie Byron
committed
if (!empty($module->info['required'] )) {
$extra['disabled'] = TRUE;
$extra['required_by'][] = $distribution_name;
}
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;
}
Angie Byron
committed
// Only display visible modules.
elseif (isset($visible_files[$requires])) {
Dries Buytaert
committed
$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'),
Angie Byron
committed
'#href' => 'admin/people/permissions',
Dries Buytaert
committed
'#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
// 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.
Angie Byron
committed
if (isset($visible_files[$required_by])) {
if ($files[$required_by]->status == 1 && $module->status == 1) {
Dries Buytaert
committed
$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);
Angie Byron
committed
// 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),
// Ensure that the "Core" package fieldset comes first.
'#weight' => $package == 'Core' ? -10 : NULL,
// Lastly, sort all fieldsets by title.
uasort($form['modules'], 'element_sort_by_title');
Dries Buytaert
committed
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
Angie Byron
committed
$form['#action'] = url('admin/modules/list/confirm');
return $form;
}
/**
* Array sorting callback; sorts elements by 'title' key.
*/
function system_sort_by_title($a, $b) {
if (!isset($b['title'])) {
return -1;
}
if (!isset($a['title'])) {
return 1;
}
return strcasecmp($a['title'], $b['title']);
}
/**
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'],
);
Dries Buytaert
committed
$form['#requires'] = $extra['requires'];
$form['#required_by'] = $extra['required_by'];
// Check the compatibilities.
$compatible = TRUE;
$status_short = '';
$status_long = '';
// Check the core compatibility.
Dries Buytaert
committed
if (!isset($info['core']) || $info['core'] != DRUPAL_CORE_COMPATIBILITY) {
$compatible = FALSE;
$status_short .= t('Incompatible with this version of Drupal core. ');
Dries Buytaert
committed
$status_long .= t('This version is not compatible with Drupal !core_version and should be replaced.', array('!core_version' => DRUPAL_CORE_COMPATIBILITY));
}
// Ensure this module is compatible with the currently installed version of PHP.
if (version_compare(phpversion(), $info['php']) < 0) {
$compatible = FALSE;
$status_short .= t('Incompatible with this version of PHP');
Dries Buytaert
committed
$php_required = $info['php'];
if (substr_count($info['php'], '.') < 2) {
$php_required .= '.*';
}
$status_long .= t('This module requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $php_required, '!php_version' => phpversion()));
}
// If this module is compatible, present a checkbox indicating
// this module may be installed. Otherwise, show a big red X.
if ($compatible) {
$form['enable'] = array(
'#type' => 'checkbox',
'#title' => t('Enable'),
'#default_value' => $extra['enabled'],
);