diff --git includes/common.inc includes/common.inc index 6b0138c..eddbe05 100644 --- includes/common.inc +++ includes/common.inc @@ -3546,7 +3546,9 @@ function drupal_render_page($page) { // Modules alter the $page as needed. Blocks are populated into regions like // 'left', 'footer', etc. drupal_alter('page', $page); - + // Process the elements prior to rendering them. + drupal_process_elements($page); + // Render the page. return drupal_render($page); } @@ -3601,13 +3603,8 @@ function drupal_render(&$elements) { return; } - // If the default values for this element have not been loaded yet, populate - // them. - if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { - $elements += element_info($elements['#type']); - } - else { - $elements += element_basic_defaults(); + if (empty($elements['#render_processed'])) { + drupal_process_elements($elements); } // If #markup is not empty and no theme function is set, use theme_markup. @@ -3616,42 +3613,6 @@ function drupal_render(&$elements) { $elements['#theme'] = 'markup'; } - // 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); - } - } - } - - // Add additional CSS and JavaScript files associated with this element. - foreach (array('css', 'js') as $kind) { - if (!empty($elements['#attached_' . $kind]) && is_array($elements['#attached_' . $kind])) { - foreach ($elements['#attached_' . $kind] as $data => $options) { - // If the value is not an array, it's a filename and passed as first - // (and only) argument. - if (!is_array($options)) { - $data = $options; - $options = NULL; - } - // When drupal_add_js with 'type' => 'setting' is called, the first - // parameter ($data) is an array. Arrays can't be keys in PHP, so we - // have to get $data from the value array. - if (is_numeric($data)) { - $data = $options['data']; - unset($options['data']); - } - call_user_func('drupal_add_' . $kind, $data, $options); - } - } - } - - // Get the children of the element, sorted by weight. - $children = element_children($elements, TRUE); - $elements['#children'] = ''; // Call the element's #theme function if it is set. Then any children of the // element have to be rendered there. @@ -3661,7 +3622,7 @@ function drupal_render(&$elements) { // If #theme was not set and the element has children, render them now // using drupal_render_children(). if ($elements['#children'] == '') { - $elements['#children'] = drupal_render_children($elements, $children); + $elements['#children'] = drupal_render_children($elements); } // Let the theme function in #theme_wrapper add markup around the rendered @@ -3700,18 +3661,123 @@ function drupal_render(&$elements) { * If the keys of the element's children are already known, they can be passed * in to save another run of element_children(). */ -function drupal_render_children(&$element, $children_keys = NULL) { - if ($children_keys === NULL) { - $children_keys = element_children($element); +function drupal_render_children(&$element) { + if (!isset($element['#children_keys'])) { + $element['#children_keys'] = element_children($element); } $output = ''; - foreach ($children_keys as $key) { + foreach ($element['#children_keys'] as $key) { $output .= drupal_render($element[$key]); } return $output; } /** + * Process renderable arrays prior to actually rendering them. + * + * This handles the #attached_css and #attached_js properties. As it is always + * called on the final $page array before rendering it, there is usually no + * need to call this function in other places. + */ +function drupal_process_elements(&$elements) { + // Early-return if user does not have access. + if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { + return; + } + // Do nothing for non-array elements and already processed elements. + if (!is_array($elements) || !empty($elements['#render_processed'])) { + return; + } + // If the default values for this element have not been loaded yet, populate + // them. + if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { + $elements += element_info($elements['#type']); + } + else { + $elements += element_basic_defaults(); + } + + // 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); + } + } + } + + // Get the keys of the element's children and sort them. + if (!isset($elements['#children_keys'])) { + $elements['#children_keys'] = element_children($elements, TRUE); + } + // Process all children. + if (is_array($elements['#children_keys'])) { + foreach($elements['#children_keys'] as $key) { + drupal_process_elements($elements[$key]); + } + } + + // Add additional CSS and JavaScript files associated with this element. + foreach (array('css', 'js') as $kind) { + if (!empty($elements['#attached_' . $kind]) && is_array($elements['#attached_' . $kind])) { + foreach ($elements['#attached_' . $kind] as $data => $options) { + // If the value is not an array, it's a filename and passed as first + // (and only) argument. + if (!is_array($options)) { + $data = $options; + $options = NULL; + } + // When drupal_add_js with 'type' => 'setting' is called, the first + // parameter ($data) is an array. Arrays can't be keys in PHP, so we + // have to get $data from the value array. + if (is_numeric($data)) { + $data = $options['data']; + unset($options['data']); + } + call_user_func('drupal_add_' . $kind, $data, $options); + } + } + } + + $elements['#render_processed'] = TRUE; +} + +/** + * A brief alias for drupal_render(), to be used in templates. + * + * This always prints the top level element. Subsequent elements are only printed + * if they haven't been printed before or have been re-enabled with show(). + */ +function render(&$element) { + if (is_array($element)) { + show($element); + print drupal_render($element); + } + else { + print $element; + } +} + +/** + * Hide an element during rendering. + */ +function hide(&$element) { + $element['#printed'] = TRUE; + return $element; +} + +/** + * Show a hidden or already printed element during rendering. + */ +function show(&$element) { + $element['#printed'] = FALSE; + return $element; +} + + +/** * Function used by uasort to sort structured arrays by weight. */ function element_sort($a, $b) { diff --git includes/form.inc includes/form.inc index b57888e..e49f571 100644 --- includes/form.inc +++ includes/form.inc @@ -2050,7 +2050,7 @@ function theme_checkbox($element) { $checkbox .= $element['#value'] ? ' checked="checked" ' : ' '; $checkbox .= drupal_attributes($element['#attributes']) . ' />'; - if (!is_null($element['#title'])) { + if (isset($element['#title'])) { $checkbox = ''; } @@ -2352,10 +2352,6 @@ function form_process_vertical_tabs($element, &$form_state) { * fieldset. */ function theme_vertical_tabs($element) { - // Add required JavaScript and Stylesheet. - drupal_add_js('misc/vertical-tabs.js', array('weight' => JS_DEFAULT - 1)); - drupal_add_css('misc/vertical-tabs.css'); - return '
' . $element['#children'] . '
'; } @@ -2441,7 +2437,6 @@ function theme_textfield($element) { $output = ''; if ($element['#autocomplete_path'] && menu_valid_path(array('link_path' => $element['#autocomplete_path']))) { - drupal_add_js('misc/autocomplete.js'); $class[] = 'form-autocomplete'; $extra = ''; } @@ -2459,6 +2454,13 @@ function theme_textfield($element) { return $output . $extra; } +function form_pre_render_textfield(&$element) { + if ($element['#autocomplete_path']) { + $element['#attached_js'][] = 'misc/autocomplete.js'; + } + return $element; +} + /** * Format a form. * diff --git includes/theme.inc includes/theme.inc index 03a5c4c..b9d93ae 100644 --- includes/theme.inc +++ includes/theme.inc @@ -1916,10 +1916,6 @@ function template_process(&$variables, $hook) { * Any changes to variables in this preprocessor should also be changed inside * template_preprocess_maintenance_page() to keep all of them consistent. * - * The $variables array contains two keys: - * - 'page': the fully decorated page. - * - 'content': the content of the page, already rendered. - * * @see drupal_render_page * @see page.tpl.php */ @@ -1930,7 +1926,7 @@ function template_preprocess_page(&$variables) { // Render each region into top level variables. foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) { - $variables[$region_key] = empty($variables['page'][$region_key]) ? '' : drupal_render($variables['page'][$region_key]); + $variables[$region_key] = empty($variables['page'][$region_key]) ? array() : $variables['page'][$region_key]; } // Add favicon. diff --git modules/block/block.module modules/block/block.module index de8e99f..475847d 100644 --- modules/block/block.module +++ modules/block/block.module @@ -268,10 +268,13 @@ function block_get_blocks_by_region($region) { $build = array(); if ($list = block_list($region)) { foreach ($list as $key => $block) { + $content = $block->content; + unset($block->content); $build[$key] = array( '#theme' => 'block', '#block' => $block, '#weight' => ++$weight, + 'content' => $content, ); } $build['#sorted'] = TRUE; @@ -777,7 +780,9 @@ function block_flush_caches() { */ function template_preprocess_block(&$variables) { static $block_counter = array(); + $variables['content'] = $variables['block']['content']; $variables['block'] = $variables['block']['#block']; + // All blocks get an independent counter for each region. if (!isset($block_counter[$variables['block']->region])) { $block_counter[$variables['block']->region] = 1; @@ -786,9 +791,9 @@ function template_preprocess_block(&$variables) { $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even'; $variables['block_id'] = $block_counter[$variables['block']->region]++; - if (is_array($variables['block']->content)) { + if (is_array($variables['content'])) { // Render the block contents if it is not already rendered. - $variables['block']->content = drupal_render($variables['block']->content); + $variables['content'] = drupal_render($variables['content']); } $variables['classes_array'][] = 'block-' . $variables['block']->module; diff --git modules/block/block.tpl.php modules/block/block.tpl.php index 5284912..9ad0f70 100644 --- modules/block/block.tpl.php +++ modules/block/block.tpl.php @@ -41,6 +41,6 @@
- content ?> +
diff --git modules/node/node.module modules/node/node.module index 8c77488..30ad4e5 100644 --- modules/node/node.module +++ modules/node/node.module @@ -1358,18 +1358,6 @@ function template_preprocess_node(&$variables) { unset($node->content['links']); } - // Render taxonomy links separately. - $variables['terms'] = !empty($node->content['links']['terms']) ? drupal_render($node->content['links']['terms']) : ''; - - // Render all remaining node links. - $variables['links'] = !empty($node->content['links']) ? drupal_render($node->content['links']) : ''; - - // Render any comments. - $variables['comments'] = !empty($node->content['comments']) ? drupal_render($node->content['comments']) : ''; - - // Render the rest of the node into $content. - $variables['content'] = drupal_render($node->content); - // Flatten the node object's member fields. $variables = array_merge((array)$node, $variables); diff --git modules/node/node.tpl.php modules/node/node.tpl.php index 36ad041..5999ece 100644 --- modules/node/node.tpl.php +++ modules/node/node.tpl.php @@ -7,7 +7,9 @@ * * Available variables: * - $title: the (sanitized) title of the node. - * - $content: Node body or teaser depending on $teaser flag. + * - $content: An array of node items. Use render($content) to print them all, or + * print a subset such as render($content['field_example']). Always call + * render($content) at the end in order to print all remaining items. * - $comments: the themed list of comments (if any). * - $picture: The authors picture of the node output from * theme_user_picture(). @@ -64,6 +66,9 @@ * @see template_preprocess_node() * @see template_process() */ + +// Uncomment the line below to see what variables are available in this template. +// print '
' . check_plain(print_r(get_defined_vars(), TRUE)) . '
'; ?>
@@ -79,16 +84,16 @@ -
+
- +
- + - + \ No newline at end of file diff --git modules/simpletest/simpletest.pages.inc modules/simpletest/simpletest.pages.inc index 7b3c642..abe1e63 100644 --- modules/simpletest/simpletest.pages.inc +++ modules/simpletest/simpletest.pages.inc @@ -59,6 +59,10 @@ function simpletest_test_form() { '#submit' => array('simpletest_clean_environment'), ); + // Attach CSS and JS files. + $form['#attached_css'][] = drupal_get_path('module', 'simpletest') . '/simpletest.css'; + $form['#attached_js'][] = drupal_get_path('module', 'simpletest') . '/simpletest.js'; + return $form; } @@ -69,9 +73,6 @@ function simpletest_test_form() { * @return HTML output. */ function theme_simpletest_test_table($table) { - drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css'); - drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js'); - // Create header for test selection table. $header = array( theme('table_select_header_cell'), diff --git modules/system/page.tpl.php modules/system/page.tpl.php index 0510d4a..47e2869 100644 --- modules/system/page.tpl.php +++ modules/system/page.tpl.php @@ -75,11 +75,11 @@ * - $tabs: Tabs linking to any sub-pages beneath the current page (e.g., the view * and edit tabs when displaying a node). * - $help: Dynamic help text, mostly for admin pages. - * - $content: The main content of the current Drupal page. + * - $content: The main content of the current page. Use render() to render. * - $feed_icons: A string of all feed icons for the current page. - * - $left: The HTML for the left sidebar. - * - $right: The HTML for the right sidebar. - * - $highlight: The HTML for the highlighted content region. + * - $left: Items for the left sidebar. Use render() to render. + * - $right: Items for the right sidebar. Use render() to render. + * - $highlight: Items for the highlighted content region. Use render() to render. * * Footer/closing data: * - $footer : The footer region. @@ -90,6 +90,10 @@ * @see template_preprocess_page() * @see template_process() */ + +// Uncomment the line below to see what variables are available in this template. +// print '
' . check_plain(print_r(get_defined_vars(), TRUE)) . '
'; + ?> @@ -140,7 +144,7 @@
- +
@@ -161,7 +165,7 @@
-
+

@@ -187,7 +191,7 @@
diff --git modules/system/system.module modules/system/system.module index 78ec082..4fff604 100644 --- modules/system/system.module +++ modules/system/system.module @@ -291,6 +291,7 @@ function system_elements() { '#process' => array('form_process_text_format', 'form_process_ahah'), '#theme' => 'textfield', '#theme_wrapper' => 'form_element', + '#pre_render' => array('form_pre_render_textfield'), ); $type['password'] = array( @@ -429,6 +430,8 @@ function system_elements() { '#theme_wrapper' => 'vertical_tabs', '#default_tab' => '', '#process' => array('form_process_vertical_tabs'), + '#attached_js' => array(array('data'=> 'misc/vertical-tabs.js', 'weight' => JS_DEFAULT - 1)), + '#attached_css' => array('misc/vertical-tabs.css'), ); $type['token'] = array( diff --git modules/user/user-profile.tpl.php modules/user/user-profile.tpl.php index 5398d00..a0cf79b 100644 --- modules/user/user-profile.tpl.php +++ modules/user/user-profile.tpl.php @@ -8,27 +8,13 @@ * This template is used when viewing a registered member's profile page, * e.g., example.com/user/123. 123 being the users ID. * - * By default, all user profile data is printed out with the $user_profile - * variable. If there is a need to break it up you can use $profile instead. - * It is keyed to the name of each category or other data attached to the - * account. If it is a category it will contain all the profile items. By - * default $profile['summary'] is provided which contains data on the user's - * history. Other data can be included by modules. $profile['user_picture'] is - * available by default showing the account picture. - * - * Also keep in mind that profile items and their categories can be defined by - * site administrators. They are also available within $profile. For example, - * if a site is configured with a category of "contact" with - * fields for of addresses, phone numbers and other related info, then doing a - * straight print of $profile['contact'] will output everything in the - * category. This is useful for altering source order and adding custom - * markup for the group. - * - * To check for all available data within $profile, use the code below. - * - * @code - * print '
'. check_plain(print_r($profile, 1)) .'
'; - * @endcode + * Use render($user_profile) to print all profile items, or print a subset + * such as render($content['field_example']). Always call render($user_profile) + * at the end in order to print all remaining items. If the item is a category, + * it will contain all it's profile items. By default, $user_profile['summary'] + * is provided which contains data on the user's history. Other data can be + * included by modules. $user_profile['user_picture'] is available + * for showing the account picture. * * @see user-profile-category.tpl.php * Where the html is handled for the group. @@ -36,14 +22,16 @@ * Where the html is handled for each item in the group. * * Available variables: - * - $user_profile: All user profile data. Ready for print. - * - $profile: Keyed array of profile categories and their items or other data - * provided by modules. + * - $user_profile: An array of profile items. Use dr() to print them. * - TODO D7 : document $FIELD_NAME_rendered variables. * * @see template_preprocess_user_profile() */ + +// Uncomment the line below to see what variables are available in this template. +// print '
' . check_plain(print_r(get_defined_vars(), TRUE)) . '
'; + ?>
- +
diff --git modules/user/user.pages.inc modules/user/user.pages.inc index de3f82a..c27fd40 100644 --- modules/user/user.pages.inc +++ modules/user/user.pages.inc @@ -185,20 +185,11 @@ function user_view($account) { * The $variables array contains the following arguments: * - $account * - * @see user-picture.tpl.php + * @see user-profile.tpl.php */ function template_preprocess_user_profile(&$variables) { $account = $variables['elements']['#account']; - - $variables['profile'] = array(); - // Sort sections by weight - uasort($account->content, 'element_sort'); - // Provide keyed variables so themers can print each section independently. - foreach (element_children($account->content) as $key) { - $variables['profile'][$key] = drupal_render($account->content[$key]); - } - // Collect all profiles to make it easier to print all items at once. - $variables['user_profile'] = implode($variables['profile']); + $variables['user_profile'] = $account->content; // Add $FIELD_NAME_rendered variables for fields. $variables += field_attach_preprocess('user', $account); diff --git themes/garland/block.tpl.php themes/garland/block.tpl.php index 6e13ff8..e0dec6f 100644 --- themes/garland/block.tpl.php +++ themes/garland/block.tpl.php @@ -7,5 +7,5 @@

subject ?>

-
content ?>
+
diff --git themes/garland/node.tpl.php themes/garland/node.tpl.php index 7e7a6ed..9508d99 100644 --- themes/garland/node.tpl.php +++ themes/garland/node.tpl.php @@ -14,21 +14,21 @@
- +
- -
+ +
- - + + - +
diff --git themes/garland/page.tpl.php themes/garland/page.tpl.php index c93dfea..f211971 100644 --- themes/garland/page.tpl.php +++ themes/garland/page.tpl.php @@ -15,7 +15,7 @@ -
+
@@ -39,30 +39,30 @@
-
+
>
- +
- +
- +