? error_log ? files ? generate-content.php ? generate-users.php ? patch.patch ? modules/devel Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.130 diff -u -F^f -r1.130 form.inc --- includes/form.inc 22 Jul 2006 19:26:58 -0000 1.130 +++ includes/form.inc 1 Aug 2006 13:54:12 -0000 @@ -603,6 +603,7 @@ function form_render(&$elements) { if (!isset($elements)) { return NULL; } + $content = ''; uasort($elements, "_form_sort"); if (!isset($elements['#children'])) { @@ -648,7 +649,32 @@ function form_render(&$elements) { if (isset($content) && $content !== '') { $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : ''; $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; - return $prefix . $content . $suffix; + $content = $prefix . $content . $suffix; + + if (isset($elements['#after_render']) && !isset($elements['#after_render_done'])) { + foreach ($elements['#after_render'] as $function) { + $function($elements, $content); + } + $elements['#after_render_done'] = TRUE; + } + + return $content; + } +} + +/** + * Iterates through the form array and strips out any + * sub-elements keyed by the second parameter. Useful for + * resetting a form to be rendered a second time without + * rebuilding. + */ +function form_strip_key(&$elements, $key_to_strip) { + if (isset($elements[$key_to_strip])) { + unset($elements[$key_to_strip]); + } + $children = element_children($elements); + foreach ($children as $key) { + form_strip_key($elements[$key], $key_to_strip); } } Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.252 diff -u -F^f -r1.252 blog.module --- modules/blog/blog.module 27 Jul 2006 08:07:04 -0000 1.252 +++ modules/blog/blog.module 1 Aug 2006 13:54:12 -0000 @@ -238,7 +238,7 @@ function blog_view(&$node, $teaser = FAL $breadcrumb[] = array('path' => 'node/'. $node->nid); menu_set_location($breadcrumb); } - $node = node_prepare($node, $teaser); + return node_prepare($node, $teaser); } /** Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.375 diff -u -F^f -r1.375 book.module --- modules/book/book.module 19 Jul 2006 07:15:34 -0000 1.375 +++ modules/book/book.module 1 Aug 2006 13:54:12 -0000 @@ -438,16 +438,6 @@ function book_content($node, $teaser = F } /** - * 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(). * * Appends book navigation to all nodes in the book. @@ -474,11 +464,18 @@ function book_nodeapi(&$node, $op, $teas } $node->breadcrumb[] = array('path' => 'node/'. $node->nid); - $node->body .= theme('book_navigation', $node); + $content = array(); + $content['book_navigation'] = array( + '#type' => 'markup', + '#value' => theme('book_navigation', $node), + '#weight' => 100, + ); if ($page) { menu_set_location($node->breadcrumb); } + + return $content; } } break; Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.339 diff -u -F^f -r1.339 forum.module --- modules/forum/forum.module 29 Jul 2006 17:56:41 -0000 1.339 +++ modules/forum/forum.module 1 Aug 2006 13:54:12 -0000 @@ -305,9 +305,14 @@ function forum_view(&$node, $teaser = FA menu_set_location($breadcrumb); } - $node = node_prepare($node, $teaser); + $content = node_prepare($node, $teaser); + $content['forum_navigation'] = array( + '#type' => 'markup', + '#value' => theme('forum_topic_navigation', $node), + '#weight' => 100, + ); - $node->body .= theme('forum_topic_navigation', $node); + return $content } /** Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.662 diff -u -F^f -r1.662 node.module --- modules/node/node.module 26 Jul 2006 08:25:25 -0000 1.662 +++ modules/node/node.module 1 Aug 2006 13:54:13 -0000 @@ -515,21 +515,7 @@ function node_view($node, $teaser = FALS // Remove the delimiter (if any) that separates the teaser from the body. // TODO: this strips legitimate uses of '' also. $node->body = str_replace('', '', $node->body); - - if ($node->log != '' && !$teaser) { - $node->body .= '
'. t('Log') .':
'. filter_xss($node->log) .'
'; - } - - // The 'view' hook can be implemented to overwrite the default function - // to display nodes. - if (node_hook($node, 'view')) { - node_invoke($node, 'view', $teaser, $page); - } - else { - $node = node_prepare($node, $teaser); - } - // Allow modules to change $node->body before viewing. - node_invoke_nodeapi($node, 'view', $teaser, $page); + if ($links) { $node->links = module_invoke_all('link', 'node', $node, !$page); @@ -538,11 +524,21 @@ function node_view($node, $teaser = FALS $function($node, $node->links); } } - // unset unused $node part so that a bad theme can not open a security hole + + $node->content = node_build_content($node, $teaser, $page); + + if (isset($content['#readmore'])) { + $node->readmore = TRUE; + } + + // set the proper node part, then unset unused $node part so that a bad + // theme can not open a security hole if ($teaser) { + $node->teaser = form_render($node->content); unset($node->body); } else { + $node->body = form_render($node->content); unset($node->teaser); } @@ -550,17 +546,63 @@ function node_view($node, $teaser = FALS } /** - * Apply filters to a node in preparation for theming. + * Apply filters and build the node's standard elements. */ function node_prepare($node, $teaser = FALSE) { - $node->readmore = (strlen($node->teaser) < strlen($node->body)); - if ($teaser == FALSE) { - $node->body = check_markup($node->body, $node->format, FALSE); + $content['body'] = array( + '#type' => 'markup', + '#value' => check_markup($teaser ? $node->teaser : $node->body, $node->format, FALSE), + '#weight' => 0, + ); + + if ($node->log != '' && !$teaser) { + $content['log_message'] = array( + '#type' => 'markup', + '#value' => theme('node_log_message', filter_xss($node->log)), + '#weight' => 20, + ); + } + + if (strlen($node->teaser) < strlen($node->body)) { + $content['#readmore'] = TRUE; + } + + return $content; +} + +/** + * Builds a structured array representing the node's content. + * + * @param $node + * A node object. + * @param $teaser + * Whether to display the teaser only, as on the main page. + * @param $page + * Whether the node is being displayed by itself as a page. + * + * @return + * An structured array containing the individual elements + * of the node's body. + */ +function node_build_content($node, $teaser = FALSE, $page = FALSE) { + // The 'view' hook can be implemented to overwrite the default function + // to display nodes. + if (node_hook($node, 'view')) { + $content = node_invoke($node, 'view', $teaser, $page); } else { - $node->teaser = check_markup($node->teaser, $node->format, FALSE); + $content = node_prepare($node, $teaser); } - return $node; + + // Allow modules to make their own additions to the content array. + $content = array_merge($content, node_invoke_nodeapi($node, 'view', $teaser, $page)); + + foreach (module_implements('node_content_alter') AS $module) { + $function = $module .'_node_content_alter'; + $function($node, $content); + } + + return $content; } /** @@ -1831,6 +1873,10 @@ function theme_node_preview($node) { return $output; } +function theme_node_log_message($log) { + return '
'. t('Log') .':
'. $log .'
'; +} + function node_form_submit($form_id, $edit) { global $user; Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.113 diff -u -F^f -r1.113 upload.module --- modules/upload/upload.module 19 Jul 2006 07:15:35 -0000 1.113 +++ modules/upload/upload.module 1 Aug 2006 13:54:13 -0000 @@ -425,31 +425,15 @@ function upload_nodeapi(&$node, $op, $te case 'view': if (isset($node->files) && user_access('view uploaded files')) { - // Manipulate so that inline references work in preview - if (!variable_get('clean_url', 0)) { - $previews = array(); - foreach ($node->files as $file) { - if (strpos($file->fid, 'upload') !== FALSE) { - $previews[] = $file; - } - } - - // URLs to files being previewed are actually Drupal paths. When Clean - // URLs are disabled, the two do not match. We perform an automatic - // replacement from temporary to permanent URLs. That way, the author - // can use the final URL in the body before having actually saved (to - // place inline images for example). - foreach ($previews as $file) { - $old = file_create_filename($file->filename, file_create_path()); - $new = url($old); - $node->body = str_replace($old, $new, $node->body); - $node->teaser = str_replace($old, $new, $node->teaser); - } - } - - // Add the attachments list to node body + // Add the attachments list to node body with a heavy + // weight to ensure they're below other elements if (count($node->files) && !$teaser) { - $node->body .= theme('upload_attachments', $node->files); + $content['files'] = array( + '#type' => 'markup', + '#value' => theme('upload_attachments', $node->files), + '#weight' => 50, + ); + return $content; } } break; @@ -499,6 +483,39 @@ function upload_nodeapi(&$node, $op, $te } } +function upload_node_content_alter($node, &$content) { + if (isset($node->files) && user_access('view uploaded files')) { + // Manipulate so that inline references work in preview + if (!variable_get('clean_url', 0)) { + $previews = array(); + foreach ($node->files as $file) { + $file = (object)$file; + if (strpos($file->fid, 'upload') !== FALSE) { + $previews[] = $file; + } + } + // URLs to files being previewed are actually Drupal paths. When Clean + // URLs are disabled, the two do not match. We perform an automatic + // replacement from temporary to permanent URLs. That way, the author + // can use the final URL in the body before having actually saved (to + // place inline images for example). + foreach ($previews as $file) { + $old = file_create_filename($file->filename, file_create_path()); + $content['#upload_urls'][$old] = url($old); + } + $content['#after_render'][] = 'upload_fix_preview_urls'; + } + } +} + +function upload_fix_preview_urls($elements, $content) { + if (is_array($elements['#upload_urls'])) { + foreach ($elements['#upload_urls'] as $old => $new) { + str_replace($old, $new, $content); + } + } +} + /** * Displays file attachments in table */