Index: index.php =================================================================== RCS file: /Users/Shared/code/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 12 Aug 2008 00:58:45 -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: /Users/Shared/code/drupal/includes/common.inc,v retrieving revision 1.781 diff -u -p -r1.781 common.inc --- includes/common.inc 2 Aug 2008 19:01:02 -0000 1.781 +++ includes/common.inc 12 Aug 2008 00:58:45 -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,15 @@ function drupal_site_offline() { drupal_maintenance_theme(); drupal_set_header('HTTP/1.1 503 Service unavailable'); drupal_set_title(t('Site offline')); - 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', + '#content' => array( + '#markup' => 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 +363,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('#markup' => 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 +392,122 @@ 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('#markup' => t('You are not authorized to access this page.')); } - print theme('page', $return); + 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('#markup' => $content); + } + $elements = array( + '#title' => drupal_get_title(), + '#theme' => 'page', + '#show_blocks' => $show_blocks, + '#show_messages' => $show_messages, + '#success' => $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('#markup' => theme('blocks', $region)); + } + } + + // Alter any part of the page before it's rendered. + drupal_alter('page', $elements); + return page_elements_builder($elements); +} + +/** + * Adds any required properties non-form elements on the page. + * + * Similar to form_builder(). + */ +function page_elements_builder($elements) { + // Use element defaults. + if ((!empty($elements['#type'])) && ($info = _element_info($elements['#type']))) { + // Overlay $info onto $elements, retaining preexisting keys. + $elements += $info; + } + + // We start off assuming all elements are in the correct order. + $elements['#sorted'] = TRUE; + + // Recurse through all child elements. + $count = 0; + foreach (element_children($elements) as $key) { + // Assign a decimal placeholder weight to preserve original array order. + if (!isset($form[$key]['#weight'])) { + $elements[$key]['#weight'] = $count/1000; + } + else { + // If one of the child elements has a weight then we will need to sort + // later. + unset($elements['#sorted']); + } + if (empty($elements[$key]['#type']) || $elements[$key]['#type'] != 'form') { + $elements[$key] = page_elements_builder($elements[$key]); + } + $count++; + } + 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'; + } + } + 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); } /** @@ -2068,7 +2186,7 @@ function drupal_get_js($scope = 'header' // with HTML 4, we need to comment out the CDATA-tag. $embed_prefix = "\n\n"; - + foreach ($javascript as $type => $data) { if (!$data) continue; @@ -2699,7 +2817,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 @@ -2707,10 +2825,13 @@ function drupal_alter($type, &$data) { * * @param $elements * The structured array describing the data to be rendered. + * @param $callback + * Optional parameter defining which function to use to mediate conversion of + * each elemement to a string. Use the default, 'theme', for XHTML. * @return - * The rendered HTML. + * The rendered content (XHTML or other depending on $callback). */ -function drupal_render(&$elements) { +function drupal_render(&$elements, $callback = 'theme') { if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { return NULL; } @@ -2729,7 +2850,7 @@ function drupal_render(&$elements) { if (isset($elements['#pre_render'])) { foreach ($elements['#pre_render'] as $function) { if (drupal_function_exists($function)) { - $elements = $function($elements); + $elements = $function($elements, $callback); } } } @@ -2754,12 +2875,12 @@ function drupal_render(&$elements) { $elements['#markup'] = ''; } - $content = theme($elements['#theme'], $elements); + $content = $callback($elements['#theme'], $elements); } // 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); } } } @@ -2769,7 +2890,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; } @@ -2780,7 +2902,7 @@ function drupal_render(&$elements) { if (isset($elements['#post_render'])) { foreach ($elements['#post_render'] as $function) { if (drupal_function_exists($function)) { - $content = $function($content, $elements); + $content = $function($content, $elements, $callback); } } } @@ -2790,6 +2912,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. */ @@ -2840,18 +3095,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), '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: /Users/Shared/code/drupal/includes/form.inc,v retrieving revision 1.277 diff -u -p -r1.277 form.inc --- includes/form.inc 18 Jul 2008 07:06:24 -0000 1.277 +++ includes/form.inc 12 Aug 2008 00:58:45 -0000 @@ -143,9 +143,10 @@ function drupal_get_form($form_id) { $form = drupal_rebuild_form($form_id, $form_state, $args); } - // 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); + // If we haven't redirected to a new location by now, we want to prepare for + // rendering whatever form array is currently in hand. + 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: /Users/Shared/code/drupal/includes/theme.inc,v retrieving revision 1.431 diff -u -p -r1.431 theme.inc --- includes/theme.inc 2 Aug 2008 19:01:02 -0000 1.431 +++ includes/theme.inc 12 Aug 2008 00:58:45 -0000 @@ -476,6 +476,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 @@ -637,12 +645,9 @@ function theme() { } if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) { - // This construct ensures that we can keep a reference through - // call_user_func_array. - $args = array(&$variables, $hook); foreach ($info['preprocess functions'] as $preprocess_function) { if (drupal_function_exists($preprocess_function)) { - call_user_func_array($preprocess_function, $args); + $preprocess_function($variables, $hook); } } } @@ -1278,7 +1283,13 @@ function theme_submenu($links) { * @return * An HTML string representing the table. */ -function theme_table($header, $rows, $attributes = array(), $caption = NULL, $colgroups = array()) { +function theme_table($element) { + + $header = $element['#header']; + $rows = $element['#rows']; + $attributes = $element['#attributes']; + $caption = $element['#caption']; + $colgroups = $element['#colgroups']; // Add sticky headers, if applicable. if (count($header)) { @@ -1478,7 +1489,12 @@ function theme_mark($type = MARK_NEW) { * @return * A string containing the list output. */ -function theme_item_list($items = array(), $title = NULL, $type = 'ul', $attributes = array()) { +function theme_item_list($list) { + $items = $list['#items']; + $title = $list['#title']; + $type = $list['#list_type']; + $attributes = $list['#attributes']; + $output = '
'; if (isset($title)) { $output .= '

' . $title . '

'; @@ -1786,17 +1802,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. @@ -1823,6 +1830,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(); @@ -1834,7 +1843,7 @@ function template_preprocess_page(&$vari $variables['language'] = $GLOBALS['language']; $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr'; $variables['logo'] = theme_get_setting('logo'); - $variables['messages'] = $variables['show_messages'] ? theme('status_messages') : ''; + $variables['messages'] = $variables['elements']['#show_messages'] ? theme('status_messages') : ''; $variables['mission'] = isset($mission) ? $mission : ''; $variables['main_menu'] = theme_get_setting('toggle_main_menu') ? menu_main_menu() : array(); $variables['secondary_menu'] = theme_get_setting('toggle_secondary_menu') ? menu_secondary_menu() : array(); @@ -1986,6 +1995,7 @@ function template_preprocess_node(&$vari */ function template_preprocess_block(&$variables) { static $block_counter = array(); + // All blocks get an independent counter for each region. if (!isset($block_counter[$variables['block']->region])) { $block_counter[$variables['block']->region] = 1; Index: includes/theme.maintenance.inc =================================================================== RCS file: /Users/Shared/code/drupal/includes/theme.maintenance.inc,v retrieving revision 1.15 diff -u -p -r1.15 theme.maintenance.inc --- includes/theme.maintenance.inc 1 Jul 2008 20:36:40 -0000 1.15 +++ includes/theme.maintenance.inc 12 Aug 2008 00:58:45 -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/aggregator/aggregator.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/aggregator/aggregator.admin.inc,v retrieving revision 1.12 diff -u -p -r1.12 aggregator.admin.inc --- modules/aggregator/aggregator.admin.inc 11 Aug 2008 07:05:26 -0000 1.12 +++ modules/aggregator/aggregator.admin.inc 12 Aug 2008 01:07:13 -0000 @@ -22,25 +22,33 @@ function aggregator_admin_overview() { function aggregator_view() { $result = db_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.etag, f.modified, f.image, f.block ORDER BY f.title'); - $output = '

' . t('Feed overview') . '

'; + $output['feed_overview'] = array('#markup' => '

' . t('Feed overview') . '

'); $header = array(t('Title'), t('Items'), t('Last update'), t('Next update'), array('data' => t('Operations'), 'colspan' => '3')); $rows = array(); while ($feed = db_fetch_object($result)) { $rows[] = array(l($feed->title, "aggregator/sources/$feed->fid"), format_plural($feed->items, '1 item', '@count items'), ($feed->checked ? t('@time ago', array('@time' => format_interval(time() - $feed->checked))) : t('never')), ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - time()))) : t('never')), l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"), l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"), l(t('update items'), "admin/content/aggregator/update/$feed->fid")); } - $output .= theme('table', $header, $rows); + $output['feed_table'] = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); $result = db_query('SELECT c.cid, c.title, count(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title'); - $output .= '

' . t('Category overview') . '

'; + $output['category_overview'] = array('#markup' => '

' . t('Category overview') . '

'); $header = array(t('Title'), t('Items'), t('Operations')); $rows = array(); while ($category = db_fetch_object($result)) { $rows[] = array(l($category->title, "aggregator/categories/$category->cid"), format_plural($category->items, '1 item', '@count items'), l(t('edit'), "admin/content/aggregator/edit/category/$category->cid")); } - $output .= theme('table', $header, $rows); + $output['category_table'] = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); return $output; } Index: modules/aggregator/aggregator.pages.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/aggregator/aggregator.pages.inc,v retrieving revision 1.15 diff -u -p -r1.15 aggregator.pages.inc --- modules/aggregator/aggregator.pages.inc 16 Jul 2008 21:59:25 -0000 1.15 +++ modules/aggregator/aggregator.pages.inc 12 Aug 2008 01:12:46 -0000 @@ -231,7 +231,11 @@ function theme_aggregator_categorize_ite } } } - $output .= theme('table', array('', t('Categorize')), $rows); + $table = array( + '#header' => array('', t('Categorize')), + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); $output .= drupal_render($form['submit']); $output .= drupal_render($form); Index: modules/blog/blog.pages.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/blog/blog.pages.inc,v retrieving revision 1.10 diff -u -p -r1.10 blog.pages.inc --- modules/blog/blog.pages.inc 22 May 2008 19:27:13 -0000 1.10 +++ modules/blog/blog.pages.inc 12 Aug 2008 00:58:45 -0000 @@ -23,18 +23,21 @@ function blog_page_user($account) { $items[] = t('You are not allowed to post a new blog entry.'); } - $output = theme('item_list', $items); + $output[] = array( + '#type' => 'item_list', + '#items' => $items + ); $result = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid); $has_posts = FALSE; while ($node = db_fetch_object($result)) { - $output .= node_view(node_load($node->nid), 1); + $output[] = array('#markup' => node_view(node_load($node->nid), 1)); $has_posts = TRUE; } if ($has_posts) { - $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); + $output['pager'] = array('#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10))); } else { if ($account->uid == $user->uid) { @@ -55,25 +58,27 @@ function blog_page_user($account) { function blog_page_last() { global $user; - $output = ''; $items = array(); if (user_access('edit own blog')) { $items[] = l(t('Create new blog entry.'), "node/add/blog"); } - $output = theme('item_list', $items); + $output['blog_links'] = array( + '#type' => 'item_list', + '#items' => $items + ); $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10)); $has_posts = FALSE; while ($node = db_fetch_object($result)) { - $output .= node_view(node_load($node->nid), 1); + $output['nodes'][] = array('#markup' => node_view(node_load($node->nid), 1)); $has_posts = TRUE; } if ($has_posts) { - $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); + $output['pager'] = array('#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10))); } else { drupal_set_message(t('No blog entries have been created.')); Index: modules/book/book.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/book/book.admin.inc,v retrieving revision 1.12 diff -u -p -r1.12 book.admin.inc --- modules/book/book.admin.inc 5 Jul 2008 06:00:51 -0000 1.12 +++ modules/book/book.admin.inc 12 Aug 2008 01:22:47 -0000 @@ -16,7 +16,11 @@ function book_admin_overview() { } $headers = array(t('Book'), t('Operations')); - return theme('table', $headers, $rows); + return array( + '#type' => 'table', + '#header' => $headers, + '#rows' => $rows, + ); } /** @@ -248,6 +252,11 @@ function theme_book_admin_table($form) { $rows[] = $row; } - return theme('table', $header, $rows, array('id' => 'book-outline')); + $table = array( + '#header' => $header, + '#rows' => $rows, + '#attributes' => array('id' => 'book-outline'), + ) + _element_info('table'); + return theme('table', $table); } Index: modules/comment/comment.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/comment/comment.admin.inc,v retrieving revision 1.10 diff -u -p -r1.10 comment.admin.inc --- modules/comment/comment.admin.inc 16 Jul 2008 21:59:26 -0000 1.10 +++ modules/comment/comment.admin.inc 12 Aug 2008 00:58:45 -0000 @@ -167,8 +167,12 @@ function theme_comment_admin_overview($f else { $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6')); } + $table = array( + '#header' => $form['header']['#value'], + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); - $output .= theme('table', $form['header']['#value'], $rows); if ($form['pager']['#markup']) { $output .= drupal_render($form['pager']); } Index: modules/comment/comment.module =================================================================== RCS file: /Users/Shared/code/drupal/modules/comment/comment.module,v retrieving revision 1.645 diff -u -p -r1.645 comment.module --- modules/comment/comment.module 3 Aug 2008 18:52:27 -0000 1.645 +++ modules/comment/comment.module 12 Aug 2008 00:58:45 -0000 @@ -981,7 +981,11 @@ function comment_render($node, $cid = 0) $comments .= '
'; } $output .= $comments; - $output .= theme('pager', NULL, $comments_per_page, 0); + $element = array( + '#type' => 'pager', + '#limit' => $comments_per_page, + ) + _element_info('pager'); + $output .= theme('pager', $element); } // If enabled, show new comment form if it's not already being displayed. @@ -1408,7 +1412,7 @@ function comment_form(&$form_state, $edi * The form title. */ function comment_form_box($edit, $title = NULL) { - return theme('box', $title, drupal_get_form('comment_form', $edit, $title)); + return theme('box', $title, drupal_render(drupal_get_form('comment_form', $edit, $title))); } /** Index: modules/dblog/dblog.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/dblog/dblog.admin.inc,v retrieving revision 1.8 diff -u -p -r1.8 dblog.admin.inc --- modules/dblog/dblog.admin.inc 19 Jul 2008 07:44:45 -0000 1.8 +++ modules/dblog/dblog.admin.inc 12 Aug 2008 00:58:45 -0000 @@ -51,7 +51,7 @@ function dblog_overview() { WATCHDOG_EMERG => 'dblog-emerg', ); - $output = drupal_get_form('dblog_filter_form'); + $output['filter_form'] = drupal_get_form('dblog_filter_form'); $header = array( ' ', @@ -90,9 +90,16 @@ function dblog_overview() { if (!$rows) { $rows[] = array(array('data' => t('No log messages available.'), 'colspan' => 6)); } - - $output .= theme('table', $header, $rows, array('id' => 'admin-dblog')); - $output .= theme('pager', NULL, 50, 0); + $output['messages_table'] = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + '#attributes' => array('id' => 'admin-dblog'), + ); + $output['pager'] = array( + '#type' => 'pager', + '#limit' => 50, + ); return $output; } @@ -118,8 +125,12 @@ function dblog_top($type) { if (empty($rows)) { $rows[] = array(array('data' => t('No log messages available.'), 'colspan' => 2)); } - - $output = theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output = theme('table', $table); $output .= theme('pager', NULL, 30, 0); return $output; @@ -171,8 +182,13 @@ function dblog_event($id) { $dblog->link, ), ); - $attributes = array('class' => 'dblog-event'); - $output = theme('table', array(), $rows, $attributes); + $table = array( + '#type' => 'table', + '#header' => array(), + '#rows' => $rows, + '#attributes' => array('class' => 'dblog-event'), + ); + $output = theme('table', $table); } return $output; } Index: modules/filter/filter.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/filter/filter.admin.inc,v retrieving revision 1.13 diff -u -p -r1.13 filter.admin.inc --- modules/filter/filter.admin.inc 24 Jul 2008 16:27:51 -0000 1.13 +++ modules/filter/filter.admin.inc 12 Aug 2008 01:28:11 -0000 @@ -80,8 +80,12 @@ function theme_filter_admin_overview($fo unset($form[$id]); } } - $header = array(t('Name'), t('Roles'), t('Default'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2)); - $output = theme('table', $header, $rows, array('id' => 'input-format-order')); + $table = array( + '#header' => array(t('Name'), t('Roles'), t('Default'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2)), + '#rows' => $rows, + '#attributes' => array('id' => 'input-format-order'), + ) + _element_info('table'); + $output = theme('table', $table); $output .= drupal_render($form); drupal_add_tabledrag('input-format-order', 'order', 'sibling', 'input-format-order-weight'); @@ -375,7 +379,6 @@ function filter_admin_order(&$form_state * @ingroup themeable */ function theme_filter_admin_order($form) { - $header = array(t('Name'), t('Weight')); $rows = array(); foreach (element_children($form['names']) as $id) { // Don't take form control structures. @@ -387,8 +390,12 @@ function theme_filter_admin_order($form) ); } } - - $output = theme('table', $header, $rows, array('id' => 'filter-order')); + $table = array( + '#header' => array(t('Name'), t('Weight')), + '#rows' => $rows, + '#attributes' => array('id' => 'filter-order'), + ) + _element_info('table'); + $output = theme('table', $table); $output .= drupal_render($form); drupal_add_tabledrag('filter-order', 'order', 'sibling', 'filter-order-weight', NULL, NULL, FALSE); Index: modules/filter/filter.module =================================================================== RCS file: /Users/Shared/code/drupal/modules/filter/filter.module,v retrieving revision 1.218 diff -u -p -r1.218 filter.module --- modules/filter/filter.module 11 Aug 2008 18:01:51 -0000 1.218 +++ modules/filter/filter.module 12 Aug 2008 01:35:05 -0000 @@ -233,7 +233,11 @@ function filter_filter_tips($delta, $for ); } } - $output .= theme('table', $header, $rows); + $table = array( + '#header' => $header, + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); $output .= '

' . t('Most unusual characters can be directly entered without any problems.') . '

'; $output .= '

' . t('If you do encounter problems, try using HTML character entities. A common example looks like & for an ampersand & character. For a full list of entities see HTML\'s entities page. Some of the available characters include:', array('@html-entities' => 'http://www.w3.org/TR/html4/sgml/entities.html')) . '

'; @@ -253,7 +257,11 @@ function filter_filter_tips($delta, $for array('data' => $entity[1], 'class' => 'get') ); } - $output .= theme('table', $header, $rows); + $table = array( + '#header' => $header, + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); return $output; } } Index: modules/menu/menu.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/menu/menu.admin.inc,v retrieving revision 1.32 diff -u -p -r1.32 menu.admin.inc --- modules/menu/menu.admin.inc 16 Jul 2008 21:59:27 -0000 1.32 +++ modules/menu/menu.admin.inc 12 Aug 2008 01:44:46 -0000 @@ -214,7 +214,12 @@ function theme_menu_overview_form($form) } $output = ''; if ($rows) { - $output .= theme('table', $header, $rows, array('id' => 'menu-overview')); + $table = array( + '#header' => $header, + '#rows' => $rows, + '#attributes' => array('id' => 'menu-overview'), + ) + _element_info('table'); + $output .= theme('table', $table); } $output .= drupal_render($form); return $output; Index: modules/node/content_types.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/node/content_types.inc,v retrieving revision 1.57 diff -u -p -r1.57 content_types.inc --- modules/node/content_types.inc 16 Jul 2008 21:59:27 -0000 1.57 +++ modules/node/content_types.inc 12 Aug 2008 01:47:40 -0000 @@ -42,7 +42,11 @@ function node_overview_types() { $rows[] = array(array('data' => t('No content types available.'), 'colspan' => '5', 'class' => 'message')); } - return theme('table', $header, $rows); + return array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); } /** Index: modules/node/node.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/node/node.admin.inc,v retrieving revision 1.24 diff -u -p -r1.24 node.admin.inc --- modules/node/node.admin.inc 19 Jul 2008 19:04:24 -0000 1.24 +++ modules/node/node.admin.inc 12 Aug 2008 01:49:05 -0000 @@ -585,8 +585,11 @@ function theme_node_admin_nodes($form) { else { $rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6')); } - - $output .= theme('table', $header, $rows); + $table = array( + '#header' => $header, + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); if ($form['pager']['#markup']) { $output .= drupal_render($form['pager']); } Index: modules/node/node.module =================================================================== RCS file: /Users/Shared/code/drupal/modules/node/node.module,v retrieving revision 1.971 diff -u -p -r1.971 node.module --- modules/node/node.module 3 Aug 2008 19:02:06 -0000 1.971 +++ modules/node/node.module 12 Aug 2008 02:17:19 -0000 @@ -1398,7 +1398,11 @@ function theme_node_search_admin($form) $row[] = drupal_render($form['factors'][$key]); $rows[] = $row; } - $output .= theme('table', $header, $rows); + $table = array( + '#header' => $header, + '#rows' => $rows, + ) + _element_info('table'); + $output .= theme('table', $table); $output .= drupal_render($form); return $output; @@ -1789,17 +1793,17 @@ function node_feed($nids = FALSE, $chann function node_page_default() { $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10)); - $output = ''; + $output = array(); $num_rows = FALSE; while ($node = db_fetch_object($result)) { - $output .= node_view(node_load($node->nid), 1); + $output[] = array('#markup' => node_view(node_load($node->nid), 1)); $num_rows = TRUE; } if ($num_rows) { $feed_url = url('rss.xml', array('absolute' => TRUE)); drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') . ' ' . t('RSS')); - $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); + $output[] = array('#markup' => theme('pager', NULL, variable_get('default_nodes_main', 10))); } else { $default_message = '

' . t('Welcome to your new Drupal website!') . '

'; @@ -1812,7 +1816,7 @@ function node_page_default() { $default_message .= ''; $default_message .= '

' . t('For more information, please refer to the help section, or the online Drupal handbooks. You may also post at the Drupal forum, or view the wide range of other support options available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '

'; - $output = '
' . $default_message . '
'; + $output = array('#markup' => '
' . $default_message . '
'); } drupal_set_title(''); Index: modules/openid/openid.pages.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/openid/openid.pages.inc,v retrieving revision 1.6 diff -u -p -r1.6 openid.pages.inc --- modules/openid/openid.pages.inc 14 Apr 2008 17:48:38 -0000 1.6 +++ modules/openid/openid.pages.inc 12 Aug 2008 01:59:04 -0000 @@ -47,8 +47,12 @@ function openid_user_identities($account $rows[] = array($identity->authname, l(t('Delete'), 'user/' . $account->uid . '/openid/delete/' . $identity->aid)); } - $output = theme('table', $header, $rows); - $output .= drupal_get_form('openid_user_add'); + $output['accounts'] = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output['openid_user_add'] = drupal_get_form('openid_user_add'); return $output; } Index: modules/path/path.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/path/path.admin.inc,v retrieving revision 1.9 diff -u -p -r1.9 path.admin.inc --- modules/path/path.admin.inc 3 Aug 2008 05:21:20 -0000 1.9 +++ modules/path/path.admin.inc 12 Aug 2008 02:00:33 -0000 @@ -13,7 +13,7 @@ */ function path_admin_overview($keys = NULL) { // Add the filter form above the overview table. - $output = drupal_get_form('path_admin_filter_form', $keys); + $output['path_admin_filter_form'] = drupal_get_form('path_admin_filter_form', $keys); // Enable language column if locale is enabled or if we have any alias with language $count = db_result(db_query("SELECT COUNT(*) FROM {url_alias} WHERE language != ''")); $multilanguage = (module_exists('locale') || $count); @@ -55,8 +55,12 @@ function path_admin_overview($keys = NUL $rows[] = array(array('data' => $empty_message, 'colspan' => ($multilanguage ? 5 : 4))); } - $output .= theme('table', $header, $rows); - $output .= theme('pager', NULL, 50, 0); + $output['aliases'] = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output['pager'] = array('#markup' => theme('pager', NULL, 50, 0)); return $output; } Index: modules/system/system.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/system/system.admin.inc,v retrieving revision 1.84 diff -u -p -r1.84 system.admin.inc --- modules/system/system.admin.inc 9 Aug 2008 12:41:23 -0000 1.84 +++ modules/system/system.admin.inc 12 Aug 2008 00:58:45 -0000 @@ -1117,8 +1117,12 @@ function system_ip_blocking() { } $output .= drupal_get_form('system_ip_blocking_form'); - - $output .= theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output .= theme('table', $table); return $output; } @@ -1823,8 +1827,12 @@ function _system_sql($data, $keys) { $rows[] = array(check_plain($key), check_plain($data[$key]), $explanation); } } - - return theme('table', array(t('Variable'), t('Value'), t('Description')), $rows); + $table = array( + '#type' => 'table', + '#header' => array(t('Variable'), t('Value'), t('Description')), + '#rows' => $rows, + ); + return theme('table', $table); } /** @@ -2107,8 +2115,12 @@ function theme_system_modules_fieldset($ $row[] = array('data' => $description, 'class' => 'description'); $rows[] = $row; } - - return theme('table', $form['#header'], $rows); + $table = array( + '#type' => 'table', + '#header' => $form['#header'], + '#rows' => $rows, + ); + return theme('table', $table); } /** @@ -2159,8 +2171,12 @@ function theme_system_modules_uninstall( if (empty($rows)) { $rows[] = array(array('data' => t('No modules are available to uninstall.'), 'colspan' => '3', 'align' => 'center', 'class' => 'message')); } - - $output = theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output = theme('table', $table); $output .= drupal_render($form); return $output; @@ -2183,8 +2199,12 @@ function theme_system_theme_select_form( $rows[] = $row; } - $header = array(t('Screenshot'), t('Name'), t('Selected')); - $output = theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => array(t('Screenshot'), t('Name'), t('Selected')), + '#rows' => $rows, + ); + $output = theme('table', $table); return $output; } @@ -2241,8 +2261,12 @@ function theme_system_themes_form($form) $rows[] = $row; } - $header = array(t('Screenshot'), t('Name'), t('Version'), t('Enabled'), t('Default'), t('Operations')); - $output = theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => array(t('Screenshot'), t('Name'), t('Version'), t('Enabled'), t('Default'), t('Operations')), + '#rows' => $rows, + ); + $output = theme('table', $table); $output .= drupal_render($form); return $output; } \ No newline at end of file Index: modules/system/system.module =================================================================== RCS file: /Users/Shared/code/drupal/modules/system/system.module,v retrieving revision 1.612 diff -u -p -r1.612 system.module --- modules/system/system.module 2 Aug 2008 19:01:02 -0000 1.612 +++ modules/system/system.module 12 Aug 2008 02:20:53 -0000 @@ -323,6 +323,21 @@ function system_elements() { '#input' => TRUE, ); + /** + * Common page elements. + */ + $type['table'] = array( + '#header' => array(), + '#rows' => array(), + '#caption' => NULL, + '#colgroups' => array(), + ); + + $type['item_list'] = array( + '#items' => array(), + '#title' => NULL, + '#list_type' => 'ul', + ); return $type; } Index: modules/user/user.admin.inc =================================================================== RCS file: /Users/Shared/code/drupal/modules/user/user.admin.inc,v retrieving revision 1.24 diff -u -p -r1.24 user.admin.inc --- modules/user/user.admin.inc 24 Jul 2008 16:28:52 -0000 1.24 +++ modules/user/user.admin.inc 12 Aug 2008 00:58:45 -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; @@ -606,7 +606,13 @@ function theme_user_admin_perm($form) { } } $output = theme('system_compact_link'); - $output .= theme('table', $header, $rows, array('id' => 'permissions')); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + '#attributes' => array('id' => 'permissions'), + ); + $output .= theme('table', $table); $output .= drupal_render($form); return $output; } @@ -738,8 +744,12 @@ function theme_user_admin_account($form) else { $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7')); } - - $output .= theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output .= theme('table', $table); if ($form['pager']['#markup']) { $output .= drupal_render($form['pager']); } @@ -768,7 +778,12 @@ function theme_user_admin_new_role($form $rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), 'colspan' => 2)); $output = drupal_render($form); - $output .= theme('table', $header, $rows); + $table = array( + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + $output .= theme('table', $table); return $output; } Index: modules/user/user.module =================================================================== RCS file: /Users/Shared/code/drupal/modules/user/user.module,v retrieving revision 1.914 diff -u -p -r1.914 user.module --- modules/user/user.module 8 Aug 2008 19:48:43 -0000 1.914 +++ modules/user/user.module 12 Aug 2008 00:58:45 -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: /Users/Shared/code/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 12 Aug 2008 00:58:45 -0000 @@ -14,7 +14,7 @@ -
+
@@ -38,7 +38,7 @@ @@ -52,16 +52,16 @@
- +
- +