Commit ce85b7c7 authored by Dries's avatar Dries

- Patch #74326 by Eaton, Royboy, chx, et al: building $node->body with arrays...

- Patch #74326 by Eaton, Royboy, chx, et al: building $node->body with arrays like FAPI for viewing.

  Once again, we're paving the path for CCK in core ... :)
parent ba9f7f17
......@@ -1570,3 +1570,116 @@ function drupal_cron_run() {
// Return TRUE so other functions can check if it did run successfully
return TRUE;
}
/**
* Renders HTML 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 drupal_get_form() or node_view().
*
* @param $elements
* The structured array describing the data to be rendered.
* @return
* The rendered HTML.
*/
function drupal_render(&$elements) {
if (!isset($elements)) {
return NULL;
}
$content = '';
uasort($elements, "_element_sort");
if (!isset($elements['#children'])) {
$children = element_children($elements);
/* Render all the children that use a theme function */
if (isset($elements['#theme']) && !$elements['#theme_used']) {
$elements['#theme_used'] = TRUE;
$previous_value = $elements['#value'];
$previous_type = $elements['#type'];
// If we rendered a single element, then we will skip the renderer.
if (empty($children)) {
$elements['#printed'] = TRUE;
}
else {
$elements['#value'] = '';
}
$elements['#type'] = 'markup';
$content = theme($elements['#theme'], $elements);
$elements['#value'] = $previous_value;
$elements['#type'] = $previous_type;
unset($elements['#prefix'], $elements['#suffix']);
}
/* render each of the children using drupal_render and concatenate them */
if (!isset($content) || $content === '') {
foreach ($children as $key) {
$content .= drupal_render($elements[$key]);
}
}
}
if (isset($content) && $content !== '') {
$elements['#children'] = $content;
}
// Until now, we rendered the children, here we render the element itself
if (!isset($elements['#printed'])) {
$content = theme(($elements['#type']) ? $elements['#type']: 'markup', $elements);
$elements['#printed'] = TRUE;
}
if (isset($content) && $content !== '') {
$prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
$suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
$content = $prefix . $content . $suffix;
if (isset($elements['#after_render'])) {
foreach ($elements['#after_render'] as $function) {
$function($elements, $content);
}
}
return $content;
}
}
/**
* Function used by uasort in drupal_render() to sort structured arrays
* by weight.
*/
function _element_sort($a, $b) {
$a_weight = (is_array($a) && isset($a['#weight'])) ? $a['#weight'] : 0;
$b_weight = (is_array($b) && isset($b['#weight'])) ? $b['#weight'] : 0;
if ($a_weight == $b_weight) {
return 0;
}
return ($a_weight < $b_weight) ? -1 : 1;
}
/**
* Check if the key is a property.
*/
function element_property($key) {
return $key[0] == '#';
}
/**
* Get properties of a structured array element. Properties begin with '#'.
*/
function element_properties($element) {
return array_filter(array_keys((array) $element), 'element_property');
}
/**
* Check if the key is a child.
*/
function element_child($key) {
return $key[0] != '#';
}
/**
* Get keys of a structured array tree element that are not properties
* (i.e., do not begin with '#').
*/
function element_children($element) {
return array_filter(array_keys((array) $element), 'element_child');
}
\ No newline at end of file
......@@ -14,34 +14,6 @@
* http://api.drupal.org/api/HEAD/file/developer/topics/forms_api.html
*/
/**
* Check if the key is a property.
*/
function element_property($key) {
return $key[0] == '#';
}
/**
* Get properties of a form tree element. Properties begin with '#'.
*/
function element_properties($element) {
return array_filter(array_keys((array) $element), 'element_property');
}
/**
* Check if the key is a child.
*/
function element_child($key) {
return $key[0] != '#';
}
/**
* Get keys of a form tree element that are not properties (i.e., do not begin with '#').
*/
function element_children($element) {
return array_filter(array_keys((array) $element), 'element_child');
}
/**
* Processes a form array and produces the HTML output of a form.
* If there is input in the $_POST['edit'] variable, this function
......@@ -263,7 +235,7 @@ function drupal_render_form($form_id, &$form, $callback = NULL) {
}
}
$output = form_render($form);
$output = drupal_render($form);
return $output;
}
......@@ -588,82 +560,6 @@ function _form_set_value(&$form_values, $form, $parents, $value) {
return $form;
}
/**
* Renders a HTML form given a form tree. Recursively iterates over each of
* the form elements, generating HTML code. This function is usually
* called from within a theme. To render a form from within a module, use
* drupal_get_form().
*
* @param $elements
* The form tree describing the form.
* @return
* The rendered HTML form.
*/
function form_render(&$elements) {
if (!isset($elements)) {
return NULL;
}
$content = '';
uasort($elements, "_form_sort");
if (!isset($elements['#children'])) {
$children = element_children($elements);
/* Render all the children that use a theme function */
if (isset($elements['#theme']) && !$elements['#theme_used']) {
$elements['#theme_used'] = TRUE;
$previous_value = $elements['#value'];
$previous_type = $elements['#type'];
// If we rendered a single element, then we will skip the renderer.
if (empty($children)) {
$elements['#printed'] = TRUE;
}
else {
$elements['#value'] = '';
}
$elements['#type'] = 'markup';
$content = theme($elements['#theme'], $elements);
$elements['#value'] = $previous_value;
$elements['#type'] = $previous_type;
unset($elements['#prefix'], $elements['#suffix']);
}
/* render each of the children using form_render and concatenate them */
if (!isset($content) || $content === '') {
foreach ($children as $key) {
$content .= form_render($elements[$key]);
}
}
}
if (isset($content) && $content !== '') {
$elements['#children'] = $content;
}
// Until now, we rendered the children, here we render the element itself
if (!isset($elements['#printed'])) {
$content = theme(($elements['#type']) ? $elements['#type']: 'markup', $elements);
$elements['#printed'] = TRUE;
}
if (isset($content) && $content !== '') {
$prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
$suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
return $prefix . $content . $suffix;
}
}
/**
* Function used by uasort in form_render() to sort form by weight.
*/
function _form_sort($a, $b) {
$a_weight = (is_array($a) && isset($a['#weight'])) ? $a['#weight'] : 0;
$b_weight = (is_array($b) && isset($b['#weight'])) ? $b['#weight'] : 0;
if ($a_weight == $b_weight) {
return 0;
}
return ($a_weight < $b_weight) ? -1 : 1;
}
/**
* Retrieve the default properties for the defined element type.
*/
......
......@@ -86,12 +86,12 @@ function theme_locale_admin_manage_screen($form) {
foreach ($form['name'] as $key => $element) {
// Do not take form control structures.
if (is_array($element) && element_child($key)) {
$rows[] = array(check_plain($key), form_render($form['name'][$key]), form_render($form['enabled'][$key]), form_render($form['site_default'][$key]), ($key != 'en' ? form_render($form['translation'][$key]) : t('n/a')), ($key != 'en' ? l(t('delete'), 'admin/settings/locale/language/delete/'. $key) : ''));
$rows[] = array(check_plain($key), drupal_render($form['name'][$key]), drupal_render($form['enabled'][$key]), drupal_render($form['site_default'][$key]), ($key != 'en' ? drupal_render($form['translation'][$key]) : t('n/a')), ($key != 'en' ? l(t('delete'), 'admin/settings/locale/language/delete/'. $key) : ''));
}
}
$header = array(array('data' => t('Code')), array('data' => t('English name')), array('data' => t('Enabled')), array('data' => t('Default')), array('data' => t('Translated')), array('data' => t('Operations')));
$output = theme('table', $header, $rows);
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......
......@@ -1105,19 +1105,19 @@ function _aggregator_page_list($sql, $op, $header = '') {
function theme_aggregator_page_list($form) {
$output = '<div id="aggregator">';
$output .= form_render($form['header']);
$output .= drupal_render($form['header']);
$rows = array();
if ($form['items']) {
foreach (element_children($form['items']) as $key) {
if (is_array($form['items'][$key])) {
$rows[] = array(form_render($form['items'][$key]), array('data' => form_render($form['categories'][$key]), 'class' => 'categorize-item'));
$rows[] = array(drupal_render($form['items'][$key]), array('data' => drupal_render($form['categories'][$key]), 'class' => 'categorize-item'));
}
}
}
$output .= theme('table', array('', t('Categorize')), $rows);
$output .= form_render($form['submit']);
$output .= drupal_render($form['submit']);
$output .= '</div>';
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......
......@@ -320,16 +320,16 @@ function theme_block_admin_display($form) {
// Generate block row
$row = array(
array('data' => form_render($block['info']), 'class' => 'block'),
form_render($block['status']) . form_render($block['theme']),
form_render($block['weight']),
form_render($block['region'])
array('data' => drupal_render($block['info']), 'class' => 'block'),
drupal_render($block['status']) . drupal_render($block['theme']),
drupal_render($block['weight']),
drupal_render($block['region'])
);
if ($throttle) {
$row[] = form_render($block['throttle']);
$row[] = drupal_render($block['throttle']);
}
$row[] = form_render($block['configure']);
$row[] = $block['delete'] ? form_render($block['delete']) : '';
$row[] = drupal_render($block['configure']);
$row[] = $block['delete'] ? drupal_render($block['delete']) : '';
$rows[] = $row;
}
}
......@@ -342,10 +342,10 @@ function theme_block_admin_display($form) {
$header[] = array('data' => t('Operations'), 'colspan' => 2);
$output = theme('table', $header, $rows, array('id' => 'blocks'));
$output .= form_render($form['submit']);
// Also render the form_id as there is no form_render($form) call (as form_render does not appear to handle the
$output .= drupal_render($form['submit']);
// Also render the form_id as there is no drupal_render($form) call (as drupal_render does not appear to handle the
// multi-dimensional block form array very well).
$output .= form_render($form['form_id']);
$output .= drupal_render($form['form_id']);
return $output;
}
......
......@@ -235,7 +235,7 @@ function blog_form(&$node) {
/**
* Implementation of hook_view().
*/
function blog_view(&$node, $teaser = FALSE, $page = FALSE) {
function blog_view($node, $teaser = FALSE, $page = FALSE) {
if ($page) {
// Breadcrumb navigation
$breadcrumb[] = array('path' => 'blog', 'title' => t('blogs'));
......@@ -243,7 +243,7 @@ function blog_view(&$node, $teaser = FALSE, $page = FALSE) {
$breadcrumb[] = array('path' => 'node/'. $node->nid);
menu_set_location($breadcrumb);
}
$node = node_prepare($node, $teaser);
return node_prepare($node, $teaser);
}
/**
......
......@@ -439,16 +439,6 @@ function book_content($node, $teaser = FALSE) {
return node_prepare($node, $teaser);
}
/**
* Implementation of hook_view().
*
* If not displayed on the main page, we render the node as a page in the
* book with extra links to the previous and next pages.
*/
function book_view(&$node, $teaser = FALSE, $page = FALSE) {
$node = node_prepare($node, $teaser);
}
/**
* Implementation of hook_nodeapi().
*
......@@ -472,7 +462,10 @@ function book_nodeapi(&$node, $op, $teaser, $page) {
}
$node->breadcrumb[] = array('path' => 'node/'. $node->nid);
$node->body .= theme('book_navigation', $node);
$node->content['book_navigation'] = array(
'#value' => theme('book_navigation', $node),
'#weight' => 100,
);
if ($page) {
menu_set_location($node->breadcrumb);
......@@ -807,7 +800,7 @@ function book_node_visitor_html_pre($node, $depth, $nid) {
$output .= "<h1 class=\"book-heading\">". check_plain($node->title) ."</h1>\n";
if ($node->body) {
$output .= $node->body;
$output .= drupal_render($node->content);
}
return $output;
}
......@@ -868,8 +861,8 @@ function theme_book_admin_table($form) {
$nid = $form[$key]['nid']['#value'];
$pid = $form[0]['nid']['#value'];
$rows[] = array(
'<div style="padding-left: '. (25 * $form[$key]['depth']['#value']) .'px;">'. form_render($form[$key]['title']) .'</div>',
form_render($form[$key]['weight']),
'<div style="padding-left: '. (25 * $form[$key]['depth']['#value']) .'px;">'. drupal_render($form[$key]['title']) .'</div>',
drupal_render($form[$key]['weight']),
l(t('view'), 'node/'. $nid),
l(t('edit'), 'node/'. $nid .'/edit'),
l(t('delete'), 'node/'. $nid .'/delete', NULL, 'destination=admin/content/book'. (arg(3) == 'orphan' ? '/orphan' : '') . ($pid != $nid ? '/'.$pid : ''))
......
......@@ -1085,15 +1085,15 @@ function comment_admin_overview_submit($form_id, $edit) {
}
function theme_comment_admin_overview($form) {
$output = form_render($form['options']);
$output = drupal_render($form['options']);
if (isset($form['subject']) && is_array($form['subject'])) {
foreach (element_children($form['subject']) as $key) {
$row = array();
$row[] = form_render($form['comments'][$key]);
$row[] = form_render($form['subject'][$key]);
$row[] = form_render($form['username'][$key]);
$row[] = form_render($form['timestamp'][$key]);
$row[] = form_render($form['operations'][$key]);
$row[] = drupal_render($form['comments'][$key]);
$row[] = drupal_render($form['subject'][$key]);
$row[] = drupal_render($form['username'][$key]);
$row[] = drupal_render($form['timestamp'][$key]);
$row[] = drupal_render($form['operations'][$key]);
$rows[] = $row;
}
}
......@@ -1103,10 +1103,10 @@ function theme_comment_admin_overview($form) {
$output .= theme('table', $form['header']['#value'], $rows);
if ($form['pager']['#value']) {
$output .= form_render($form['pager']);
$output .= drupal_render($form['pager']);
}
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......@@ -1580,7 +1580,7 @@ function comment_controls($mode = COMMENT_MODE_THREADED_EXPANDED, $order = COMME
function theme_comment_controls($form) {
$output .= '<div class="container-inline">';
$output .= form_render($form);
$output .= drupal_render($form);
$output .= '</div>';
$output .= '<div class="description">'. t('Select your preferred way to display the comments and click "Save settings" to activate your changes.') .'</div>';
return theme('box', t('Comment viewing options'), $output);
......
......@@ -331,18 +331,18 @@ function theme_filter_admin_overview($form) {
foreach ($form as $name => $element) {
if (isset($element['roles']) && is_array($element['roles'])) {
$rows[] = array(
form_render($form['default'][$element['id']['#value']]),
drupal_render($form['default'][$element['id']['#value']]),
check_plain($name),
form_render($element['roles']),
form_render($element['configure']),
form_render($element['delete'])
drupal_render($element['roles']),
drupal_render($element['configure']),
drupal_render($element['delete'])
);
unset($form[$name]);
}
}
$header = array(t('Default'), t('Name'), t('Roles'), array('data' => t('Operations'), 'colspan' => 2));
$output = theme('table', $header, $rows);
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......@@ -561,12 +561,12 @@ function theme_filter_admin_order($form) {
foreach (element_children($form['names']) as $id) {
// Don't take form control structures
if (is_array($form['names'][$id])) {
$rows[] = array(form_render($form['names'][$id]), form_render($form['weights'][$id]));
$rows[] = array(drupal_render($form['names'][$id]), drupal_render($form['weights'][$id]));
}
}
$output = theme('table', $header, $rows);
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......
......@@ -313,8 +313,11 @@ function forum_view(&$node, $teaser = FALSE, $page = FALSE) {
}
$node = node_prepare($node, $teaser);
$node->body .= theme('forum_topic_navigation', $node);
$node->content['forum_navigation'] = array(
'#value' => theme('forum_topic_navigation', $node),
'#weight' => 100,
);
return $node;
}
/**
......
This diff is collapsed.
......@@ -56,12 +56,11 @@ function poll_block($op = 'list', $delta = 0) {
$poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'status' => 1));
if ($poll->nid) {
// poll_view() dumps the output into $poll->body.
poll_view($poll, 1, 0, 1);
$poll = poll_view($poll, TRUE, FALSE, TRUE);
}
}
$block['subject'] = t('Poll');
$block['content'] = $poll->body;
$block['content'] = drupal_render($poll->content);
return $block;
}
}
......@@ -343,12 +342,12 @@ function theme_poll_view_voting($form) {
$output .= '<div class="poll">';
$output .= ' <div class="vote-form">';
$output .= ' <div class="choices">';
$output .= form_render($form['choice']);
$output .= drupal_render($form['choice']);
$output .= ' </div>';
$output .= form_render($form['nid']);
$output .= form_render($form['vote']);
$output .= drupal_render($form['nid']);
$output .= drupal_render($form['vote']);
$output .= ' </div>';
$output .= form_render($form);
$output .= drupal_render($form);
$output .= '</div>';
return $output;
}
......@@ -541,14 +540,14 @@ function poll_cancel(&$node) {
* An extra parameter that adapts the hook to display a block-ready
* rendering of the poll.
*/
function poll_view(&$node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
function poll_view($node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
global $user;
$output = '';
// Special display for side-block
if ($block) {
// No 'read more' link
$node->body = $node->teaser = '';
$node->readmore = FALSE;
$links = module_invoke_all('link', 'node', $node, 1);
$links[] = array('title' => t('older polls'), 'href' => 'poll', 'attributes' => array('title' => t('View the list of polls on this site.')));
......@@ -560,13 +559,16 @@ function poll_view(&$node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
}
if ($node->allowvotes && ($block || arg(2) != 'results')) {
$output .= poll_view_voting($node, $teaser, $page, $block);
$node->content['body'] = array(
'#value' => poll_view_voting($node, $teaser, $page, $block),
);
}
else {
$output .= poll_view_results($node, $teaser, $page, $block);
$node->content['body'] = array(
'#value' => poll_view_results($node, $teaser, $page, $block),
);
}
$node->body = $node->teaser = $output;
return $node;
}
/**
......
......@@ -1062,14 +1062,14 @@ function search_box_form_submit($form_id, $form_values) {
* Theme the theme search form.
*/
function theme_search_theme_form($form) {
return '<div id="search" class="container-inline">'. form_render($form) .'</div>';
return '<div id="search" class="container-inline">'. drupal_render($form) .'</div>';
}
/**
* Theme the block search form.
*/
function theme_search_block_form($form) {
return '<div class="container-inline">'. form_render($form) .'</div>';
return '<div class="container-inline">'. drupal_render($form) .'</div>';
}
/**
......
......@@ -429,9 +429,9 @@ function theme_system_theme_select_form($form) {
foreach (element_children($form) as $key) {
$row = array();
if (is_array($form[$key]['description'])) {
$row[] = form_render($form[$key]['screenshot']);
$row[] = form_render($form[$key]['description']);
$row[] = form_render($form['theme'][$key]);
$row[] = drupal_render($form[$key]['screenshot']);
$row[] = drupal_render($form[$key]['description']);
$row[] = drupal_render($form['theme'][$key]);
}
$rows[] = $row;
}
......@@ -1101,7 +1101,7 @@ function system_themes() {
$form[$info->name]['operations'] = array('#type' => 'markup', '#value' => l(t('configure'), 'admin/build/themes/settings/' . $info->name) );
}
else {
// Dummy element for form_render. Cleaner than adding a check in the theme function.
// Dummy element for drupal_render. Cleaner than adding a check in the theme function.
$form[$info->name]['operations'] = array();
}
}
......@@ -1118,12 +1118,12 @@ function theme_system_themes($form) {
foreach (element_children($form) as $key) {
$row = array();
if (is_array($form[$key]['description'])) {
$row[] = form_render($form[$key]['screenshot']);
$row[] = form_render($form[$key]['description']);
$row[] = array('data' => form_render($form['status'][$key]), 'align' => 'center');
$row[] = drupal_render($form[$key]['screenshot']);
$row[] = drupal_render($form[$key]['description']);
$row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
if ($form['theme_default']) {
$row[] = array('data' => form_render($form['theme_default'][$key]), 'align' => 'center');
$row[] = array('data' => form_render($form[$key]['operations']), 'align' => 'center');
$row[] = array('data' => drupal_render($form['theme_default'][$key]), 'align' => 'center');
$row[] = array('data' => drupal_render($form[$key]['operations']), 'align' => 'center');
}
}
$rows[] = $row;
......@@ -1131,7 +1131,7 @@ function theme_system_themes($form) {
$header = array(t('Screenshot'), t('Name'), t('Enabled'), t('Default'), t('Operations'));
$output = theme('table', $header, $rows);
$output .= form_render($form);
$output .= drupal_render($form);
return $output;
}
......@@ -1216,12 +1216,12 @@ function system_modules() {
function theme_system_modules($form) {
foreach (element_children($form['name']) as $key) {