? .project
? custom_theme.patch
? custom_theme_0.patch
? profiles/systemseed
? sites/default/files
? sites/default/settings.php
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.418
diff -u -p -r1.418 menu.inc
--- includes/menu.inc	7 Nov 2010 21:51:40 -0000	1.418
+++ includes/menu.inc	14 Nov 2010 13:21:12 -0000
@@ -1620,22 +1620,22 @@ function menu_get_custom_theme($initiali
   // Skip this if the site is offline or being installed or updated, since the
   // menu system may not be correctly initialized then.
   if ($initialize && !_menu_site_is_offline(TRUE) && (!defined('MAINTENANCE_MODE') || (MAINTENANCE_MODE != 'update' && MAINTENANCE_MODE != 'install'))) {
-    // First allow modules to dynamically set a custom theme for the current
-    // page. Since we can only have one, the last module to return a valid
-    // theme takes precedence.
-    $custom_themes = array_filter(module_invoke_all('custom_theme'), 'drupal_theme_access');
-    if (!empty($custom_themes)) {
-      $custom_theme = array_pop($custom_themes);
+    // First check if the current page requires a particular theme.
+    $router_item = menu_get_item();
+    if (!empty($router_item['access']) && !empty($router_item['theme_callback']) && function_exists($router_item['theme_callback'])) {
+      $theme_name = call_user_func_array($router_item['theme_callback'], $router_item['theme_arguments']);
+      if (drupal_theme_access($theme_name)) {
+        $custom_theme = $theme_name;
+      }
     }
-    // Otherwise, execute the theme callback function for the current page, if
-    // there is one, in order to determine the custom theme to set.
+
+    // Otherwise, allow modules to dynamically set a custom theme for the
+    // current page. Since we can only have one, the last module to return a
+    // valid theme takes precedence.
     if (!isset($custom_theme)) {
-      $router_item = menu_get_item();
-      if (!empty($router_item['access']) && !empty($router_item['theme_callback']) && function_exists($router_item['theme_callback'])) {
-        $theme_name = call_user_func_array($router_item['theme_callback'], $router_item['theme_arguments']);
-        if (drupal_theme_access($theme_name)) {
-          $custom_theme = $theme_name;
-        }
+      $custom_themes = array_filter(module_invoke_all('custom_theme'), 'drupal_theme_access');
+      if (!empty($custom_themes)) {
+        $custom_theme = array_pop($custom_themes);
       }
     }
   }
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.555
diff -u -p -r1.555 book.module
--- modules/book/book.module	5 Nov 2010 19:47:20 -0000	1.555
+++ modules/book/book.module	14 Nov 2010 13:21:12 -0000
@@ -170,7 +170,6 @@ function book_menu() {
     'page arguments' => array(1),
     'access callback' => '_book_outline_access',
     'access arguments' => array(1),
-    'theme callback' => '_node_custom_theme',
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
     'file' => 'book.pages.inc',
@@ -181,7 +180,6 @@ function book_menu() {
     'page arguments' => array('book_remove_form', 1),
     'access callback' => '_book_outline_remove_access',
     'access arguments' => array(1),
-    'theme callback' => '_node_custom_theme',
     'file' => 'book.pages.inc',
   );
 
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1317
diff -u -p -r1.1317 node.module
--- modules/node/node.module	9 Nov 2010 08:36:38 -0000	1.1317
+++ modules/node/node.module	14 Nov 2010 13:21:13 -0000
@@ -255,19 +255,35 @@ function node_uri($node) {
  * Implements hook_admin_paths().
  */
 function node_admin_paths() {
-  $paths = array(
-    'node/*/edit' => TRUE,
-    'node/*/delete' => TRUE,
-    'node/*/revisions' => TRUE,
-    'node/*/revisions/*/revert' => TRUE,
-    'node/*/revisions/*/delete' => TRUE,
-    'node/add' => TRUE,
-    'node/add/*' => TRUE,
-  );
+  $paths = array();
+  if (variable_get('node_admin_theme')) {
+    $paths += array(
+      'node/*/edit' => TRUE,
+      'node/*/delete' => TRUE,
+      'node/*/revisions' => TRUE,
+      'node/*/revisions/*/revert' => TRUE,
+      'node/*/revisions/*/delete' => TRUE,
+      'node/add' => TRUE,
+      'node/add/*' => TRUE,
+    );
+  }
   return $paths;
 }
 
 /**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Add the "node_admin_theme" checkbox to the admin theme selection form.
+ */
+function node_form_system_themes_admin_form_alter(&$form, &$form_state) {
+  $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),
+  );
+}
+
+/**
  * Gathers a listing of links to nodes.
  *
  * @param $result
@@ -1901,7 +1917,6 @@ function node_menu() {
     'title' => 'Add content',
     'page callback' => 'node_add_page',
     'access callback' => '_node_add_access',
-    'theme callback' => '_node_custom_theme',
     'file' => 'node.pages.inc',
   );
   $items['rss.xml'] = array(
@@ -1948,7 +1963,6 @@ function node_menu() {
     'page arguments' => array(1),
     'access callback' => 'node_access',
     'access arguments' => array('update', 1),
-    'theme callback' => '_node_custom_theme',
     'weight' => 0,
     'type' => MENU_LOCAL_TASK,
     'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
@@ -1960,7 +1974,6 @@ function node_menu() {
     'page arguments' => array('node_delete_confirm', 1),
     'access callback' => 'node_access',
     'access arguments' => array('delete', 1),
-    'theme callback' => '_node_custom_theme',
     'weight' => 1,
     'type' => MENU_LOCAL_TASK,
     'context' => MENU_CONTEXT_INLINE,
@@ -1972,7 +1985,6 @@ function node_menu() {
     'page arguments' => array(1),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1),
-    'theme callback' => '_node_custom_theme',
     'weight' => 2,
     'type' => MENU_LOCAL_TASK,
     'file' => 'node.pages.inc',
@@ -1992,7 +2004,6 @@ function node_menu() {
     'page arguments' => array('node_revision_revert_confirm', 1),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1, 'update'),
-    'theme callback' => '_node_custom_theme',
     'file' => 'node.pages.inc',
   );
   $items['node/%node/revisions/%/delete'] = array(
@@ -2002,7 +2013,6 @@ function node_menu() {
     'page arguments' => array('node_revision_delete_confirm', 1),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1, 'delete'),
-    'theme callback' => '_node_custom_theme',
     'file' => 'node.pages.inc',
   );
   return $items;
@@ -2038,17 +2048,6 @@ function node_page_title($node) {
   return $node->title;
 }
 
-/**
- * Theme callback for creating and editing nodes.
- */
-function _node_custom_theme() {
-  // Use the administration theme if the site is configured to use it for
-  // nodes.
-  if (variable_get('node_admin_theme')) {
-    return variable_get('admin_theme');
-  }
-}
-
 function node_last_changed($nid) {
   return db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed;
 }
Index: modules/overlay/overlay.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/overlay/overlay.module,v
retrieving revision 1.32
diff -u -p -r1.32 overlay.module
--- modules/overlay/overlay.module	6 Nov 2010 00:18:24 -0000	1.32
+++ modules/overlay/overlay.module	14 Nov 2010 13:21:13 -0000
@@ -80,6 +80,21 @@ function overlay_theme() {
 }
 
 /**
+ * Implement hook_custom_theme().
+ */
+function overlay_custom_theme() {
+  global $user;
+
+  // Either a module already set the overlay mode or overlay_init() did not
+  // run, so we have no mode. Reproduce its logic here, because we run earlier.
+  $use_overlay = !isset($user->data['overlay']) || $user->data['overlay'];
+  if (overlay_get_mode() == 'child' || (user_access('access overlay') && $use_overlay && isset($_GET['render']) && $_GET['render'] == 'overlay' && path_is_admin(current_path()))) {
+    // Force pages displayed in overlay to use the admin theme.
+    return variable_get('admin_theme');
+  }
+}
+
+/**
  * Implements hook_form_FORM_ID_alter().
  */
 function overlay_form_user_profile_form_alter(&$form, &$form_state) {
Index: modules/simpletest/tests/menu.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu.test,v
retrieving revision 1.38
diff -u -p -r1.38 menu.test
--- modules/simpletest/tests/menu.test	15 Oct 2010 04:46:58 -0000	1.38
+++ modules/simpletest/tests/menu.test	14 Nov 2010 13:21:13 -0000
@@ -159,26 +159,35 @@ class MenuRouterTestCase extends DrupalW
   }
 
   /**
-   * Test that the result of hook_custom_theme() overrides the theme callback.
+   * Test that the theme callback overrides the result of hook_custom_theme().
    */
   function testHookCustomTheme() {
     // Trigger hook_custom_theme() to dynamically request the Stark theme for
     // the requested page.
     variable_set('menu_test_hook_custom_theme_name', 'stark');
+    theme_enable(array('stark'));
 
-    // Request a page whose theme callback returns the Seven theme. Since Stark
-    // is not a currently enabled theme, our above request should be ignored,
-    // and Seven should still be used.
-    $this->drupalGet('menu-test/theme-callback/use-admin-theme');
-    $this->assertText('Custom theme: seven. Actual theme: seven.', t('The result of hook_custom_theme() does not override a theme callback when it returns a theme that is not enabled.'));
-    $this->assertRaw('seven/style.css', t("The Seven theme's CSS appears on the page."));
+    // The menu "theme callback" should take precedence over a value set in
+    // hook_custom_theme().
+    $this->drupalGet('menu-test/no-theme-callback');
+    $this->assertText('Custom theme: stark. Actual theme: stark.', t('The result of hook_custom_theme() is used as the theme for the current page.'));
+    $this->assertRaw('stark/layout.css', t("The Stark theme's CSS appears on the page."));
+  }
 
-    // Now enable the Stark theme and request the same page as above. This
-    // time, we expect hook_custom_theme() to prevail.
+  /**
+   * Test that the theme callback wins out over hook_custom_theme().
+   */
+  function testThemeCallbackHookCustomTheme() {
+    // Trigger hook_custom_theme() to dynamically request the Stark theme for
+    // the requested page.
+    variable_set('menu_test_hook_custom_theme_name', 'stark');
     theme_enable(array('stark'));
+
+    // The menu "theme callback" should take precedence over a value set in
+    // hook_custom_theme().
     $this->drupalGet('menu-test/theme-callback/use-admin-theme');
-    $this->assertText('Custom theme: stark. Actual theme: stark.', t('The result of hook_custom_theme() overrides what was set in a theme callback.'));
-    $this->assertRaw('stark/layout.css', t("The Stark theme's CSS appears on the page."));
+    $this->assertText('Custom theme: seven. Actual theme: seven.', t('The result of hook_custom_theme() does not override what was set in a theme callback.'));
+    $this->assertRaw('seven/style.css', t("The Seven theme's CSS appears on the page."));
   }
 
   /**
Index: modules/simpletest/tests/menu_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu_test.module,v
retrieving revision 1.18
diff -u -p -r1.18 menu_test.module
--- modules/simpletest/tests/menu_test.module	15 Oct 2010 04:46:59 -0000	1.18
+++ modules/simpletest/tests/menu_test.module	14 Nov 2010 13:21:13 -0000
@@ -58,6 +58,11 @@ function menu_test_menu() {
     'page arguments' => array(TRUE),
     'access arguments' => array('access content'),
   );
+  $items['menu-test/no-theme-callback'] = array(
+    'title' => 'Page that displays different themes without using a theme callback.',
+    'page callback' => 'menu_test_theme_page_callback',
+    'access arguments' => array('access content'),
+  );
   // Path containing "exotic" characters.
   $path = "menu-test/ -._~!$'\"()*@[]?&+%#,;=:" . // "Special" ASCII characters.
     "%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string.
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.324
diff -u -p -r1.324 system.admin.inc
--- modules/system/system.admin.inc	7 Nov 2010 18:33:53 -0000	1.324
+++ modules/system/system.admin.inc	14 Nov 2010 13:21:13 -0000
@@ -261,26 +261,17 @@ function system_themes_admin_form($form,
     '#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'),
-  );
-  $form['admin_theme']['actions'] = array('#type' => 'actions');
-  $form['admin_theme']['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save configuration'),
-  );
-  return $form;
+  $form['#submit'][] = 'system_themes_admin_form_submit';
+  return system_settings_form($form);
 }
 
 /**
  * Process system_themes_admin_form form submissions.
  */
 function system_themes_admin_form_submit($form, &$form_state) {
-  drupal_set_message(t('The configuration options have been saved.'));
-  variable_set('admin_theme', $form_state['values']['admin_theme']);
-  variable_set('node_admin_theme', $form_state['values']['node_admin_theme']);
+  // A menu rebuild is needed in case admin paths might be different because
+  // of changed administration theme settings.
+  variable_set('menu_rebuild_needed', TRUE);
 }
 
 /**
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.212
diff -u -p -r1.212 system.api.php
--- modules/system/system.api.php	13 Nov 2010 02:00:56 -0000	1.212
+++ modules/system/system.api.php	14 Nov 2010 13:21:14 -0000
@@ -1010,13 +1010,13 @@ function hook_page_build(&$page) {
  *   - "access arguments": An array of arguments to pass to the access callback
  *     function, with path component substitution as described above.
  *   - "theme callback": (optional) A function returning the machine-readable
- *     name of the default theme that will be used to render the page. If this
- *     function is provided, it is expected to return a currently-active theme
- *     on the site (otherwise, the main site theme will be used instead). If no
- *     function is provided, the main site theme will also be used, unless a
- *     value is inherited from a parent menu item. In all cases, the results of
- *     this function can be dynamically overridden for a particular page
- *     request by modules which implement hook_custom_theme().
+ *     name of the theme that will be used to render the page. If this function
+ *     is provided, it is expected to return a currently-active theme on the
+ *     site (otherwise, the default theme will be used instead). The results
+ *     of this function will override both the default theme and any theme
+ *     returned by modules implementing hook_custom_theme(). If no function is
+ *     provided, the default theme will be used, unless a value is inherited
+ *     from a parent menu item.
  *   - "theme arguments": An array of arguments to pass to the theme callback
  *     function, with path component substitution as described above.
  *   - "file": A file that will be included before the page callback is called;
@@ -2011,10 +2011,10 @@ function hook_theme_registry_alter(&$the
  * Return the machine-readable name of the theme to use for the current page.
  *
  * This hook can be used to dynamically set the theme for the current page
- * request. It overrides the default theme as well as any per-page or
- * per-section theme set by the theme callback function in hook_menu(). This
- * should be used by modules which need to override the theme based on dynamic
- * conditions.
+ * request. Note however that the theme callback function in hook_theme() has
+ * higher precedence; if that function is set for the current page and it
+ * returned a valid theme that theme will be used. In that case
+ * hook_custom_theme() won't be fired.
  *
  * Since only one theme can be used at a time, the last (i.e., highest
  * weighted) module which returns a valid theme name from this hook will
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.988
diff -u -p -r1.988 system.module
--- modules/system/system.module	12 Nov 2010 01:36:08 -0000	1.988
+++ modules/system/system.module	14 Nov 2010 13:21:14 -0000
@@ -543,8 +543,6 @@ function system_menu() {
     'page callback' => 'system_admin_menu_block_page',
     'weight' => 9,
     'menu_name' => 'management',
-    'theme callback' => 'variable_get',
-    'theme arguments' => array('admin_theme'),
     'file' => 'system.admin.inc',
   );
   $items['admin/compact'] = array(
@@ -1840,9 +1838,6 @@ function system_init() {
   // Add the CSS for this module. These aren't in system.info, because they
   // need to be in the CSS_SYSTEM group rather than the CSS_DEFAULT group.
   drupal_add_css($path . '/system.base.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
-  if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit' || arg(2) == 'delete'))) {
-    drupal_add_css($path . '/system.admin.css', array('group' => CSS_SYSTEM));
-  }
   drupal_add_css($path . '/system.menus.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
   drupal_add_css($path . '/system.messages.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
   drupal_add_css($path . '/system.theme.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
@@ -1894,6 +1889,16 @@ function system_add_module_assets() {
 }
 
 /**
+ * Implements hook_custom_theme().
+ */
+function system_custom_theme() {
+  if (user_access('access administration pages') && path_is_admin(current_path())) {
+    drupal_add_css(drupal_get_path('module', 'system') . '/admin.css', array('weight' => CSS_SYSTEM));
+    return variable_get('admin_theme');
+  }
+}
+
+/**
  * Implements hook_form_FORM_ID_alter().
  */
 function system_form_user_profile_form_alter(&$form, &$form_state) {
Index: modules/translation/translation.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/translation/translation.module,v
retrieving revision 1.89
diff -u -p -r1.89 translation.module
--- modules/translation/translation.module	25 Oct 2010 15:14:33 -0000	1.89
+++ modules/translation/translation.module	14 Nov 2010 13:21:14 -0000
@@ -65,7 +65,6 @@ function translation_menu() {
     'access arguments' => array(1),
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
-    'theme callback' => '_node_custom_theme',
     'file' => 'translation.pages.inc',
   );
   return $items;
