? bad.patch ? batch-update-pass.txt ? block_list_fix-232037-1.patch ? block_list_fix-232037-13.patch ? block_list_fix-232037-8.patch ? blog_tracker_access_bypass_2.patch ? book_nodeapi_load.patch ? check-POST-222588-1.patch ? check-POST-222588-3.patch ? check-POST-222588-8.patch ? clear-module-list-7x.patch ? created-270567-1.patch ? db-placeholders-sdo-409-6x-7a.patch ? delete-aggregator-blocks-268491-D7-5.patch ? fix-run-tests-243773-127.patch ? fix.patch ? holey-cow-249546-1.patch ? improve-script-254166-4.patch ? improve-script-254166-6.patch ? improve-script=more-254166-13.patch ? make-plain-title-242873-45.patch ? menu-attributes-isset.patch ? menu_rebuild_fix-261148.patch ? menu_rebuild_fix_0.patch ? mw_136.patch ? no-nest-form.patch ? node-type-namespace-206138-3.patch ? node-type-namespace-206138-8.patch ? not-anon-perms-248598-1.patch ? not-anon-perms-248598-2.patch ? perm-conversion-regex.txt ? perm_api_security.patch ? pluggable-passwords.patch ? preserve-link-class-273129-7.patch ? profile-test-quotes-252920-1.patch ? profile.test.patch ? remove-object-d7.patch ? renderers-145551-90.patch ? renderers-145551-91.patch ? result.html ? revert-251239-7x.patch ? rough-idea-134478-125.patch ? simpletest-user-258200-11.patch ? system-test-setup-259871-1.patch ? system-test-setup.patch ? test.php ? test3.php ? test4.php ? test5.php ? toggle-cache-menu-231587.patch ? user-load-cache-91786-10.patch ? user-load-cache-91786-10b.patch ? user-load-cache-91786-8.patch ? user_permissions_3.patch ? writability-225880-31.patch ? writability-225880-32.patch ? xdebug.patch ? sites/all/modules ? sites/default/files ? sites/default/settings.php Index: index.php =================================================================== RCS file: /cvs/drupal/drupal/index.php,v retrieving revision 1.94 diff -u -p -r1.94 index.php --- index.php 26 Dec 2007 08:46:48 -0000 1.94 +++ index.php 27 Jun 2008 18:51:24 -0000 @@ -21,19 +21,21 @@ $return = menu_execute_active_handler(); if (is_int($return)) { switch ($return) { case MENU_NOT_FOUND: - drupal_not_found(); + $elements = drupal_not_found(); break; case MENU_ACCESS_DENIED: - drupal_access_denied(); + $elements = drupal_access_denied(); break; case MENU_SITE_OFFLINE: - drupal_site_offline(); + $elements = drupal_site_offline(); break; } } elseif (isset($return)) { // Print any value (including an empty string) except NULL or undefined: - print theme('page', $return); + $elements = drupal_build_page($return); } +echo drupal_render_page($elements); + drupal_page_footer(); Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.773 diff -u -p -r1.773 common.inc --- includes/common.inc 24 Jun 2008 22:09:52 -0000 1.773 +++ includes/common.inc 27 Jun 2008 18:51:24 -0000 @@ -47,20 +47,18 @@ function drupal_set_content($region = NU * @param $region * A specified region to fetch content for. If NULL, all regions will be * returned. - * @param $delimiter - * Content to be inserted between exploded array elements. */ -function drupal_get_content($region = NULL, $delimiter = ' ') { +function drupal_get_content($region = NULL) { $content = drupal_set_content(); if (isset($region)) { if (isset($content[$region]) && is_array($content[$region])) { - return implode($delimiter, $content[$region]); + return $content[$region]; } } else { foreach (array_keys($content) as $region) { - if (is_array($content[$region])) { - $content[$region] = implode($delimiter, $content[$region]); + if (!is_array($content[$region])) { + $content[$region] = array(); } } return $content; @@ -331,8 +329,16 @@ function drupal_site_offline() { drupal_maintenance_theme(); drupal_set_header('HTTP/1.1 503 Service unavailable'); drupal_set_title(t('Site off-line')); - print theme('maintenance_page', filter_xss_admin(variable_get('site_offline_message', - t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))))); + + $elements['page'] = array( + '#title' => drupal_get_title(), + '#theme' => 'maintenance_page', + '#theme arguments' => array(), + '#content' => array( + '#value' => filter_xss_admin(variable_get('site_offline_message', t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal'))))), + ), + ); + return $elements; } /** @@ -358,11 +364,11 @@ function drupal_not_found() { if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) { drupal_set_title(t('Page not found')); - $return = t('The requested page could not be found.'); + $return = array('#value' => t('The requested page could not be found.')); } // To conserve CPU and bandwidth, omit the blocks. - print theme('page', $return, FALSE); + return drupal_build_page($return, FALSE, TRUE, FALSE); } /** @@ -387,9 +393,82 @@ function drupal_access_denied() { if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) { drupal_set_title(t('Access denied')); - $return = t('You are not authorized to access this page.'); + $return = array('#value' => t('You are not authorized to access this page.')); + } + return drupal_build_page($return, TRUE, TRUE, FALSE); +} + +/** + * Build a structured array with page content and theme parameters. + */ +function drupal_build_page($content, $show_blocks = TRUE, $show_messages = TRUE, $success = TRUE) { + if (!is_array($content)) { + $content = array('#value' => $content); + } + $elements = array( + '#title' => drupal_get_title(), + '#theme' => 'page', + '#theme arguments' => array($show_blocks, $show_messages, $success), + 'content' => $content, + ); + + global $theme; + + $regions = system_region_list($theme); + // Load all region content assigned via blocks. + foreach (array_keys($regions) as $region) { + if (!isset($elements[$region])) { + $elements[$region] = array(); + } + // Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE. + if (!(!$show_blocks && ($region == 'left' || $region == 'right'))) { + $elements[$region]['blocks'] = array('#value' => theme('blocks', $region)); + } + } + return $elements; +} + +function drupal_render_page($elements) { + $render_type = ''; + if (isset($_GET['render'])) { + $render_type = $_GET['render']; + } + // jQuery sets a HTTP_X_REQUESTED_WITH header of 'XMLHttpRequest'. + if (!$render_type) { + // Set the render type based on the request header. + if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { + $render_type = 'json'; + } + else { + $render_type = 'xhtml'; + } } - print theme('page', $return); + switch ($render_type) { + case 'xhtml': + case 'html': + $render = 'drupal_render'; + break; + + default: + $render = 'drupal_' . $render_type . '_render'; + if (!drupal_function_exists($render)) { + $render = 'drupal_render'; + } + break; + } + + return $render($elements); +} + +/** + * Render the elements into simple XML. + */ +function drupal_xml_render($elements) { + return drupal_render($elements, 'theme_xml'); +} + +function render(&$element) { + echo drupal_render($element); } /** @@ -2691,7 +2770,7 @@ function drupal_alter($type, &$data) { /** - * Renders HTML given a structured array tree. + * Renders HTML or other output given a structured array tree. * * Recursively iterates over each of the array elements, generating HTML code. * This function is usually called from within a another function, like @@ -2699,10 +2778,13 @@ function drupal_alter($type, &$data) { * * @param $elements * The structured array describing the data to be rendered. + * @param $callback + * Optional parameter defining which funciton to use to mediate conversion of + * each elemement to a string. Use the default, 'theme', for HTML. * @return * The rendered HTML. */ -function drupal_render(&$elements) { +function drupal_render(&$elements, $callback = 'theme') { if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { return NULL; } @@ -2753,16 +2835,25 @@ function drupal_render(&$elements) { $elements['#type'] = 'markup'; unset($elements['#prefix'], $elements['#suffix']); - $content = theme($elements['#theme'], $elements); + + $args[] = $elements['#theme']; + $args[] = $elements; + if (!empty($elements['#theme arguments'])) { + foreach($elements['#theme arguments'] as $value) { + $args[] = $value; + } + } + // The default $callback is 'theme'. + $content = call_user_func_array($callback, $args); foreach (array('#value', '#type', '#prefix', '#suffix') as $key) { $elements[$key] = isset($previous[$key]) ? $previous[$key] : NULL; } } - /* render each of the children using drupal_render and concatenate them */ + // Render each of the children using drupal_render and concatenate them if (!isset($content) || $content === '') { foreach ($children as $key) { - $content .= drupal_render($elements[$key]); + $content .= drupal_render($elements[$key], $callback); } } } @@ -2772,7 +2863,8 @@ function drupal_render(&$elements) { // Until now, we rendered the children, here we render the element itself if (!isset($elements['#printed'])) { - $content = theme(!empty($elements['#type']) ? $elements['#type'] : 'markup', $elements); + // The default $callback is 'theme'. + $content = $callback(!empty($elements['#type']) ? $elements['#type'] : 'markup', $elements); $elements['#printed'] = TRUE; } @@ -2793,6 +2885,139 @@ function drupal_render(&$elements) { } } + +/** + * Renders elements of structured array tree, retaining the structure. + * + * Recursively iterates over each of the array elements, generating output. + * This function is usually called from within a another function. + * + * @param $elements + * The structured array describing the data to be rendered. + * @param $callback + * Optional parameter defining which funciton to use to mediate conversion of + * each elemement to a string. Use the default, 'theme', for HTML. + * @return + * The rendered HTML. + */ +function drupal_render_array(&$elements, $callback = 'theme') { + if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { + $elements = NULL; + } + + // If the default values for this element haven't been loaded yet, populate + // them. + if (!isset($elements['#defaults_loaded']) || !$elements['#defaults_loaded']) { + if ((!empty($elements['#type'])) && ($info = _element_info($elements['#type']))) { + $elements += $info; + } + } + + // Make any final changes to the element before it is rendered. This means + // that the $element or the children can be altered or corrected before the + // element is rendered into the final text. + if (isset($elements['#pre_render'])) { + foreach ($elements['#pre_render'] as $function) { + if (drupal_function_exists($function)) { + $elements = $function($elements, $callback); + } + } + } + + $content = ''; + // Either the elements did not go through form_builder or one of the children + // has a #weight. + if (!isset($elements['#sorted'])) { + uasort($elements, "element_sort"); + } + $elements += array('#title' => NULL, '#description' => NULL); + if (!isset($elements['#children'])) { + $children = element_children($elements); + /* Render all the children that use a theme function */ + if (!$children && isset($elements['#theme']) && empty($elements['#theme_used'])) { + $elements['#theme_used'] = TRUE; + + $previous = array(); + foreach (array('#type', '#prefix', '#suffix') as $key) { + $previous[$key] = isset($elements[$key]) ? $elements[$key] : NULL; + } + // If we rendered a single element, then we will skip the renderer. + $elements['#printed'] = TRUE; + $elements['#type'] = 'markup'; + $elements['#value'] = ''; + + unset($elements['#prefix'], $elements['#suffix']); + + $args[] = $elements['#theme']; + $args[] = $elements; + if (!empty($elements['#theme arguments'])) { + foreach($elements['#theme arguments'] as $value) { + $args[] = $value; + } + } + // The default $callback is 'theme'. + $content = call_user_func_array($callback, $args); + + foreach (array('#type', '#prefix', '#suffix') as $key) { + $elements[$key] = isset($previous[$key]) ? $previous[$key] : NULL; + } + } + // Render each of the children using drupal_render_array + if (!isset($content) || $content === '') { + foreach ($children as $key) { + drupal_render_array($elements[$key], $callback); + } + } + } + + // Until now, we rendered the children, here we render the element itself + if (!isset($elements['#printed']) && !$children) { + // The default $callback is 'theme'. + $content = $callback(!empty($elements['#type']) ? $elements['#type'] : 'markup', $elements); + $elements['#printed'] = TRUE; + } + + if (isset($content) && $content !== '') { + // Filter the outputted content and make any last changes before the + // content is sent to the browser. The changes are made on $content + // which allows the output'ed text to be filtered. + if (isset($elements['#post_render'])) { + foreach ($elements['#post_render'] as $function) { + if (drupal_function_exists($function)) { + $content = $function($content, $elements, $callback); + } + } + } + $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : ''; + $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; + $elements['#value'] = $prefix . $content . $suffix; + } +} + +function element_property_preserve_in_array($key) { + switch ($key) { + case '#title': + case '#value': + case '#type': + return TRUE; + + default: + return FALSE; + } +} + +function drupal_json_render($elements) { + drupal_set_header('Content-Type: text/javascript; charset=utf-8'); + drupal_render_array($elements); + return drupal_to_js($elements); +} + +function drupal_printr_render($elements) { + drupal_set_header('Content-Type: text/plain; charset=utf-8'); + drupal_render_array($elements); + return print_r($elements, 1); +} + /** * Function used by uasort to sort structured arrays by weight. */ @@ -2843,18 +3068,18 @@ function drupal_common_theme() { 'arguments' => array('text' => NULL) ), 'page' => array( - 'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), + 'arguments' => array('elements' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), 'template' => 'page', ), 'maintenance_page' => array( - 'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), + 'arguments' => array('elements' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), 'template' => 'maintenance-page', ), 'update_page' => array( - 'arguments' => array('content' => NULL, 'show_messages' => TRUE), + 'arguments' => array('elements' => NULL, 'show_messages' => TRUE), ), 'install_page' => array( - 'arguments' => array('content' => NULL), + 'arguments' => array('elements' => NULL), ), 'task_list' => array( 'arguments' => array('items' => NULL, 'active' => NULL), Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.275 diff -u -p -r1.275 form.inc --- includes/form.inc 25 Jun 2008 09:57:07 -0000 1.275 +++ includes/form.inc 27 Jun 2008 18:51:24 -0000 @@ -145,7 +145,8 @@ function drupal_get_form($form_id) { // If we haven't redirected to a new location by now, we want to // render whatever form array is currently in hand. - return drupal_render_form($form_id, $form); + drupal_set_form_theme($form_id, $form); + return $form; } /** @@ -586,7 +587,7 @@ function drupal_validate_form($form_id, * A string containing the path of the page to display when processing * is complete. */ -function drupal_render_form($form_id, &$form) { +function drupal_set_form_theme($form_id, &$form) { // Don't override #theme if someone already set it. if (!isset($form['#theme'])) { init_theme(); @@ -595,9 +596,6 @@ function drupal_render_form($form_id, &$ $form['#theme'] = $form_id; } } - - $output = drupal_render($form); - return $output; } /** Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.428 diff -u -p -r1.428 theme.inc --- includes/theme.inc 25 Jun 2008 09:12:24 -0000 1.428 +++ includes/theme.inc 27 Jun 2008 18:51:24 -0000 @@ -478,6 +478,14 @@ function list_themes($refresh = FALSE) { } /** + * Dummy function for now. + */ +function theme_xml() { + $args = func_get_args(); + return call_user_func_array('theme', $args); +} + +/** * Generate the themed output. * * All requests for theme hooks must go through this function. It examines @@ -1788,17 +1796,8 @@ function template_preprocess_page(&$vari global $theme; // Populate all block regions. $regions = system_region_list($theme); - // Load all region content assigned via blocks. foreach (array_keys($regions) as $region) { - // Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE. - if (!(!$variables['show_blocks'] && ($region == 'left' || $region == 'right'))) { - $blocks = theme('blocks', $region); - } - else { - $blocks = ''; - } - // Assign region to a region variable. - isset($variables[$region]) ? $variables[$region] .= $blocks : $variables[$region] = $blocks; + $variables[$region] = &$variables['elements'][$region]; } // Set up layout variable. @@ -1825,6 +1824,8 @@ function template_preprocess_page(&$vari $head_title[] = variable_get('site_slogan', ''); } } + + $variables['content'] = &$variables['elements']['content']; $variables['head_title'] = implode(' | ', $head_title); $variables['base_path'] = base_path(); $variables['front_page'] = url(); Index: includes/theme.maintenance.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v retrieving revision 1.14 diff -u -p -r1.14 theme.maintenance.inc --- includes/theme.maintenance.inc 25 Jun 2008 09:12:24 -0000 1.14 +++ includes/theme.maintenance.inc 27 Jun 2008 18:51:24 -0000 @@ -164,7 +164,7 @@ function theme_update_page($content, $sh drupal_set_header('Content-Type: text/html; charset=utf-8'); // Assign content and show message flag. - $variables['content'] = $content; + $variables['elements']['content'] = array('#value' => $content); $variables['show_messages'] = $show_messages; // The maintenance preprocess function is recycled here. template_preprocess_maintenance_page($variables); @@ -239,6 +239,8 @@ function template_preprocess_maintenance $head_title[] = variable_get('site_slogan', ''); } } + + $variables['content'] = &$variables['elements']['content']); $variables['head_title'] = implode(' | ', $head_title); $variables['base_path'] = base_path(); $variables['front_page'] = url(); Index: modules/user/user.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v retrieving revision 1.22 diff -u -p -r1.22 user.admin.inc --- modules/user/user.admin.inc 7 May 2008 19:34:24 -0000 1.22 +++ modules/user/user.admin.inc 27 Jun 2008 18:51:24 -0000 @@ -19,8 +19,8 @@ function user_admin($callback_arg = '') $output = drupal_get_form('user_multiple_delete_confirm'); } else { - $output = drupal_get_form('user_filter_form'); - $output .= drupal_get_form('user_admin_account'); + $output[] = drupal_get_form('user_filter_form'); + $output[] = drupal_get_form('user_admin_account'); } } return $output; Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.911 diff -u -p -r1.911 user.module --- modules/user/user.module 27 Jun 2008 07:25:11 -0000 1.911 +++ modules/user/user.module 27 Jun 2008 18:51:25 -0000 @@ -760,7 +760,7 @@ function user_block($op = 'list', $delta if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) { $block['subject'] = t('User login'); - $block['content'] = drupal_get_form('user_login_block'); + $block['content'] = drupal_render(drupal_get_form('user_login_block')); } return $block; Index: themes/garland/page.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/page.tpl.php,v retrieving revision 1.20 diff -u -p -r1.20 page.tpl.php --- themes/garland/page.tpl.php 28 Apr 2008 09:25:27 -0000 1.20 +++ themes/garland/page.tpl.php 27 Jun 2008 18:51:25 -0000 @@ -14,7 +14,7 @@ -
+
@@ -38,7 +38,7 @@ @@ -52,16 +52,16 @@
- +
- +