=== modified file 'includes/theme.inc' --- includes/theme.inc 2009-11-20 04:29:42 +0000 +++ includes/theme.inc 2009-11-22 22:29:31 +0000 @@ -1243,6 +1243,78 @@ function theme_render_template($template } /** + * Enable a given list of themes. + * + * @param $theme_list + * An array of theme names. + */ +function theme_enable($theme_list) { + drupal_clear_css_cache(); + + foreach ($theme_list as $key) { + db_update('system') + ->fields(array('status' => 1)) + ->condition('type', 'theme') + ->condition('name', $key) + ->execute(); + } + + list_themes(TRUE); + menu_rebuild(); + drupal_theme_rebuild(); + + // Notify locale module about new themes being enabled, so translations can + // be imported. This might start a batch, and only return to the redirect + // path after that. + module_invoke('locale', 'system_update', $theme_list); + + // Invoke hook_themes_enabled after the themes have been enabled. + module_invoke_all('themes_enabled', $theme_list); + + return; +} + +/** + * Disable a given list of themes. + * + * @param $theme_list + * An array of theme names. + */ +function theme_disable($theme_list) { + // Don't disable the default theme. + if ($pos = array_search(variable_get('theme_default', 'garland'), $theme_list) !== FALSE) { + unset($theme_list[$pos]); + if (empty($theme_list)) { + return; + } + } + + // If the admin theme is disabled, turn off the setting. + if (in_array(variable_get('admin_theme', 0), $theme_list)) { + variable_del('admin_theme'); + } + + drupal_clear_css_cache(); + + foreach ($theme_list as $key) { + db_update('system') + ->fields(array('status' => 0)) + ->condition('type', 'theme') + ->condition('name', $key) + ->execute(); + } + + list_themes(TRUE); + menu_rebuild(); + drupal_theme_rebuild(); + + // Invoke hook_themes_enabled after the themes have been enabled. + module_invoke_all('themes_disabled', $theme_list); + + return; +} + +/** * @defgroup themeable Default theme implementations * @{ * Functions and templates that present output to the user, and can be === modified file 'modules/block/block.module' --- modules/block/block.module 2009-11-22 21:24:37 +0000 +++ modules/block/block.module 2009-11-22 22:29:31 +0000 @@ -497,34 +497,11 @@ function block_form_user_profile_form_al } /** - * Implement hook_form_FORM_ID_alter(). - */ -function block_form_system_themes_form_alter(&$form, &$form_state) { - // This function needs to fire before the theme changes are recorded in the - // database, otherwise it will populate the default list of blocks from the - // new theme, which is empty. - array_unshift($form['#submit'], 'block_system_themes_form_submit'); -} - -/** * Initialize blocks for enabled themes. */ -function block_system_themes_form_submit(&$form, &$form_state) { - if ($form_state['values']['op'] == t('Save configuration')) { - if (is_array($form_state['values']['status'])) { - foreach ($form_state['values']['status'] as $key => $choice) { - if ($choice || $form_state['values']['theme_default'] == $key) { - block_theme_initialize($key); - } - } - } - if ($form_state['values']['admin_theme'] && $form_state['values']['admin_theme'] !== variable_get('admin_theme', 0)) { - // If we're changing themes, make sure the theme has its blocks initialized. - $has_blocks = (bool) db_query_range('SELECT 1 FROM {block} WHERE theme = :theme', 0, 1, array(':theme' => $form_state['values']['admin_theme']))->fetchField(); - if (!$has_blocks) { - block_theme_initialize($form_state['values']['admin_theme']); - } - } +function block_themes_enabled($theme_list) { + foreach ($theme_list as $theme) { + block_theme_initialize($theme); } } === modified file 'modules/system/system-rtl.css' --- modules/system/system-rtl.css 2009-08-24 03:11:34 +0000 +++ modules/system/system-rtl.css 2009-11-11 13:10:31 +0000 @@ -90,6 +90,28 @@ input.password-confirm { margin-left: 10px; margin-right: 0; } + +.system-themes-list-enabled .theme-selector .screenshot { + float: right; + margin: 0 0 0 20px; +} +.system-themes-list-disabled .theme-selector { + float: right; + padding: 20px 0 20px 20px; +} +.theme-selector .operations li { + float: right; + border-right: none; + border-left: 1px solid #cdcdcd; +} +.theme-selector .operations li.last { + padding: 0 0.7em 0 0; + border-left: none; +} +.theme-selector .operations li.first { + padding: 0 0 0 0.7em; +} + .password-strength-title { float: right; } === modified file 'modules/system/system.admin.inc' --- modules/system/system.admin.inc 2009-11-22 18:42:55 +0000 +++ modules/system/system.admin.inc 2009-11-23 14:05:39 +0000 @@ -192,12 +192,9 @@ function system_settings_overview() { } /** - * Menu callback; displays a listing of all themes. - * - * @ingroup forms - * @see system_themes_form_submit() + * Retrieve the list of themes that are not hidden. */ -function system_themes_form() { +function _system_theme_list() { // Get current list of themes. $themes = system_rebuild_theme_data(); @@ -209,13 +206,26 @@ function system_themes_form() { } uasort($themes, 'system_sort_modules_by_info_name'); + return $themes; +} + +/** + * Menu callback; displays a listing of all themes. + */ +function system_themes_page() { + // Get current list of themes. + $themes =& _system_theme_list(); - $status = array(); - $incompatible_core = array(); - $incompatible_php = array(); + $theme_default = variable_get('theme_default', 'garland'); + $theme_groups = array(); - foreach ($themes as $theme) { - $screenshot = NULL; + foreach ($themes as &$theme) { + + $admin_theme_options[$theme->name] = $theme->info['name']; + $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); @@ -227,50 +237,61 @@ function system_themes_form() { // 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'])) { - $screenshot = $themes[$theme_key]->info['screenshot']; + $theme->screenshot = $themes[$theme_key]->info['screenshot']; break; } } - $screenshot = $screenshot ? theme('image', array('path' => $screenshot, 'alt' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])), 'title' => '', 'attributes' => array('class' => array('screenshot')), 'getsize' => FALSE)) : t('no screenshot'); - $form[$theme->name]['screenshot'] = array('#markup' => $screenshot); - $form[$theme->name]['info'] = array( - '#type' => 'value', - '#value' => $theme->info, - ); - $options[$theme->name] = $theme->info['name']; - - $form[$theme->name]['operations'] = drupal_theme_access($theme) ? array('#type' => 'link', '#title' => t('configure'), '#href' => 'admin/appearance/settings/' . $theme->name) : array(); - - if (!empty($theme->status)) { - $status[] = $theme->name; + if (drupal_theme_access($theme)) { + $theme->operations = array( + l(t('Configure'), 'admin/appearance/settings/' . $theme->name), + ); + if (!$theme->is_default) { + $theme->operations[] = l(t('Disable'), 'admin/appearance/disable', array('query' => array('theme' => $theme->name))); + $theme->operations[] = l(t('Set default'), 'admin/appearance/default', array('query' => array('theme' => $theme->name))); + } } else { - // 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. - if (!isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']))) { - $incompatible_core[] = $theme->name; - } - if (version_compare(phpversion(), $theme->info['php']) < 0) { - $incompatible_php[$theme->name] = $theme->info['php']; - } + $theme->operations = array( + l(t('Enable'), 'admin/appearance/enable', array('query' => array('theme' => $theme->name))), + l(t('Set default'), 'admin/appearance/default', array('query' => array('theme' => $theme->name))), + ); + } + + 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; } + + // 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; } - $form['status'] = array( - '#type' => 'checkboxes', - '#options' => array_fill_keys(array_keys($options), ''), - '#default_value' => $status, - '#incompatible_themes_core' => drupal_map_assoc($incompatible_core), - '#incompatible_themes_php' => $incompatible_php, - ); - $form['theme_default'] = array( - '#type' => 'radios', - '#options' => array_fill_keys(array_keys($options), ''), - '#default_value' => variable_get('theme_default', 'garland'), - ); + 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)) . 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', @@ -280,7 +301,7 @@ function system_themes_form() { ); $form['admin_theme']['admin_theme'] = array( '#type' => 'select', - '#options' => array(0 => t('Default theme')) + $options, + '#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), @@ -290,84 +311,158 @@ function system_themes_form() { '#title' => t('Use the administration theme when editing or creating content'), '#default_value' => variable_get('node_admin_theme', '0'), ); - - $form['buttons']['submit'] = array( + $form['admin_theme']['submit'] = array( '#type' => 'submit', '#value' => t('Save configuration'), ); - return $form; } /** - * Process system_themes_form form submissions. + * Process system_themes_admin_form form submissions. */ -function system_themes_form_submit($form, &$form_state) { - drupal_clear_css_cache(); +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']); +} + +/** + * Form to enable a theme. + * + * @ingroup forms + * @see system_theme_enable_form_submit() + */ +function system_theme_enable_form($form, &$form_state) { + // Get current list of themes. + $themes =& _system_theme_list(); - // Store list of previously enabled themes and disable all themes - $old_theme_list = $new_theme_list = array(); - foreach (list_themes() as $theme) { - if ($theme->status) { - $old_theme_list[] = $theme->name; + foreach ($themes as $theme) { + // Only allow disabled themes to be enabled. + if (empty($theme->status)) { + $options[$theme->name] = $theme->info['name']; } } - db_update('system') - ->fields(array('status' => 0)) - ->condition('type', 'theme') - ->execute(); - if ($form_state['values']['op'] == t('Save configuration')) { - if (is_array($form_state['values']['status'])) { - foreach ($form_state['values']['status'] as $key => $choice) { - // Always enable the default theme, despite its status checkbox being checked: - if ($choice || $form_state['values']['theme_default'] == $key) { - $new_theme_list[] = $key; - db_update('system') - ->fields(array('status' => 1)) - ->condition('type', 'theme') - ->condition('name', $key) - ->execute(); - } - } - } - if ($form_state['values']['admin_theme'] && $form_state['values']['admin_theme'] != $form_state['values']['theme_default']) { - 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' => $form_state['values']['admin_theme'], - '%selected_theme' => $form_state['values']['theme_default'], - ))); - } + // We normally submit this form via a link with GET variables. + $form['#method'] = 'get'; + $form['#redirect'] = 'admin/appearance'; + $form['theme'] = array( + '#title' => t('Select a theme to enable'), + '#type' => 'select', + '#options' => array(0 => t('- Please choose -')) + $options, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save configuration'), + ); + return $form; +} - // Save the variables. - variable_set('theme_default', $form_state['values']['theme_default']); - variable_set('admin_theme', $form_state['values']['admin_theme']); - variable_set('node_admin_theme', $form_state['values']['node_admin_theme']); - } - else { - // Revert to defaults: only Garland is enabled. - variable_del('theme_default'); - variable_del('admin_theme'); - variable_del('node_admin_theme'); - db_update('system') - ->fields(array('status' => 1)) - ->condition('type', 'theme') - ->condition('name', 'garland') - ->execute(); - $new_theme_list = array('garland'); +/** + * Process system_theme_enable_form form submissions. + */ +function system_theme_enable_form_submit($form, &$form_state) { + drupal_set_message(t('The configuration options have been saved.')); +} + +/** + * Form to disable a theme. + * + * @ingroup forms + * @see system_theme_disable_form_submit() + */ +function system_theme_disable_form($form, &$form_state) { + // Get current list of themes. + $themes =& _system_theme_list(); + + $theme_default = variable_get('theme_default', 'garland'); + foreach ($themes as $theme) { + // Only allow enabled themes that aren't the default theme to be disabled. + if (!empty($theme->status) && $theme->name != $theme_default) { + $options[$theme->name] = $theme->info['name']; + } } - list_themes(TRUE); - menu_rebuild(); - drupal_theme_rebuild(); + // We normally submit this form via a link with GET variables. + $form['#method'] = 'get'; + $form['#redirect'] = 'admin/appearance'; + $form['theme'] = array( + '#title' => t('Select a theme to disable'), + '#type' => 'select', + '#options' => array(0 => t('- Please choose -')) + $options, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save configuration'), + ); + return $form; +} + +/** + * Process system_theme_disable_form form submissions. + */ +function system_theme_disable_form_submit($form, &$form_state) { +dsm($form_state); + $theme_default = variable_get('theme_default', 'garland'); drupal_set_message(t('The configuration options have been saved.')); - $form_state['redirect'] = 'admin/appearance'; +} - // Notify locale module about new themes being enabled, so translations can - // be imported. This might start a batch, and only return to the redirect - // path after that. - module_invoke('locale', 'system_update', array_diff($new_theme_list, $old_theme_list)); +/** + * Form to select the default theme. + * + * @ingroup forms + * @see system_theme_default_form_submit() + */ +function system_theme_default_form($form, &$form_state) { + // Get current list of themes. + $themes =& _system_theme_list(); - return; + foreach ($themes as $theme) { + $options[$theme->name] = $theme->info['name']; + } + + // We normally submit this form via a link with GET variables. + $form['#method'] = 'get'; + $form['#redirect'] = 'admin/appearance'; + $form['theme'] = array( + '#title' => t('Select a theme to set as the default'), + '#type' => 'select', + '#options' => array(0 => t('- Please choose -')) + $options, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save configuration'), + ); + return $form; +} + +/** + * Process system_theme_default_form form submissions. + */ +function system_theme_default_form_submit($form, &$form_state) { + // Get current list of themes. + $themes =& _system_theme_list(); + + $theme = $form['theme']; + + // Enable the theme if it is currently disabled. + if (empty($themes[$theme]->status)) { + theme_enable(array($theme)); + } + + $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' => $admin_theme, + '%selected_theme' => $theme, + ))); + } + else { + drupal_set_message(t('The configuration options have been saved.')); + } + + variable_set('theme_default', $theme); } /** @@ -803,6 +898,19 @@ function system_sort_modules_by_info_nam } /** + * 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) { @@ -2418,61 +2526,58 @@ function theme_system_modules_uninstall( * * @param $variables * An associative array containing: - * - form: An associative array containing the structure of the form. + * - theme_groups: An associative array containing groups of themes. * * @ingroup themeable */ -function theme_system_themes_form($variables) { - $form = $variables['form']; +function theme_system_themes_page($variables) { + $theme_groups = $variables['theme_groups']; - foreach (element_children($form) as $key) { - // Only look for themes - if (!isset($form[$key]['info'])) { + $output = '