? body-as-field-372743-171.patch ? body-as-field-372743-173.patch ? body-as-field-372743-177.patch ? body-as-field-372743-180.patch ? body-as-field-372743-184.patch ? edit_links_on_everything-473268-24.patch ? edit_links_on_everything-473268-interim.patch ? enforce_goto_action_D7_0.patch ? fields-ui_01.patch ? fields-ui_interim.patch ? installer_settings_text.patch ? installer_settings_text_02.patch ? test_redirect_login.patch ? modules/field/field.admin.inc ? modules/field/field.js ? sites/all/modules/block_class ? sites/all/modules/cck ? sites/all/modules/coder ? sites/all/modules/cvs_deploy ? sites/all/modules/viewsy ? sites/all/themes/extra_stark ? sites/default/files ? sites/default/settings.php Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.922 diff -u -p -r1.922 common.inc --- includes/common.inc 13 Jun 2009 19:28:57 -0000 1.922 +++ includes/common.inc 16 Jun 2009 09:49:28 -0000 @@ -3651,6 +3651,14 @@ function drupal_render(&$elements) { $elements['#theme'] = 'markup'; } + // If there is an edit link associated with this element but the #editable + // property has not been set, use the menu callback to determine whether or + // not it is editable by the current user. + if (isset($elements['#edit']) && !isset($elements['#editable']) && drupal_function_exists('menu_get_item')) { + $item = menu_get_item($elements['#edit']); + $elements['#editable'] = !empty($item['access']); + } + // 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. @@ -3904,6 +3912,9 @@ function drupal_common_theme() { 'links' => array( 'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')), ), + 'edit_link' => array( + 'arguments' => array('link' => NULL, 'element' => NULL), + ), 'image' => array( 'arguments' => array('path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE), ), Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.328 diff -u -p -r1.328 menu.inc --- includes/menu.inc 10 Jun 2009 21:52:36 -0000 1.328 +++ includes/menu.inc 16 Jun 2009 09:49:29 -0000 @@ -766,7 +766,7 @@ function menu_get_object($type = 'node', } /** - * Render a menu tree based on the current path. + * Returns a menu tree based on the current path. * * The tree is expanded based on the current path and dynamic paths are also * changed according to the defined to_arg functions (for example the 'My account' @@ -775,28 +775,30 @@ function menu_get_object($type = 'node', * @param $menu_name * The name of the menu. * @return - * The rendered HTML of that menu on the current page. + * An array representing the menu on the current page, suitable for + * rendering with drupal_render(). */ function menu_tree($menu_name) { - $menu_output = &drupal_static(__FUNCTION__, array()); + $menu_tree = &drupal_static(__FUNCTION__, array()); - if (!isset($menu_output[$menu_name])) { + if (!isset($menu_tree[$menu_name])) { $tree = menu_tree_page_data($menu_name); - $menu_output[$menu_name] = menu_tree_output($tree); + $menu_tree[$menu_name] = menu_tree_unrendered($tree); } - return $menu_output[$menu_name]; + return $menu_tree[$menu_name]; } /** - * Returns a rendered menu tree. + * Returns an array representing a menu, suitable for rendering. * * @param $tree * A data structure representing the tree as returned from menu_tree_data. * @return - * The rendered HTML of that data structure. + * A structured array representing the menu, suitable for rendering with + * drupal_render(). */ -function menu_tree_output($tree) { - $output = ''; +function menu_tree_unrendered($tree) { + $content = ''; $items = array(); // Pull out just the menu items we are going to render so that we @@ -819,13 +821,28 @@ function menu_tree_output($tree) { $extra_class = implode(' ', $extra_class); $link = theme('menu_item_link', $data['link']); if ($data['below']) { - $output .= theme('menu_item', $link, $data['link']['has_children'], menu_tree_output($data['below']), $data['link']['in_active_trail'], $extra_class); + $content .= theme('menu_item', $link, $data['link']['has_children'], menu_tree_output($data['below']), $data['link']['in_active_trail'], $extra_class); } else { - $output .= theme('menu_item', $link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class); + $content .= theme('menu_item', $link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class); } } - return $output ? theme('menu_tree', $output) : ''; + return array( + '#theme' => 'menu_tree', + '#menu' => $content, + ); +} + +/** + * Returns a rendered menu tree. + * + * @param $tree + * A data structure representing the tree as returned from menu_tree_data. + * @return + * The rendered HTML of that data structure. + */ +function menu_tree_output($tree) { + return drupal_render(menu_tree_unrendered($tree)); } /** @@ -1260,7 +1277,7 @@ function theme_menu_item_link($link) { * @ingroup themeable */ function theme_menu_tree($tree) { - return ''; + return !empty($tree['#menu']) ? '' : ''; } /** Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.495 diff -u -p -r1.495 theme.inc --- includes/theme.inc 13 Jun 2009 19:34:57 -0000 1.495 +++ includes/theme.inc 16 Jun 2009 09:49:30 -0000 @@ -729,16 +729,22 @@ function theme() { } else { // The theme call is a template. - $variables = array( - 'template_files' => array() - ); + $variables = array(); if (!empty($info['arguments'])) { + // Populate the variables with arguments passed to the theme function. + // Note that the first argument may be treated specially by template + // preprocess functions, so it must go into the variables array before + // anything else does. $count = 0; foreach ($info['arguments'] as $name => $default) { $variables[$name] = isset($args[$count]) ? $args[$count] : $default; $count++; } } + // Add an empty array of template files as a default; preprocess functions + // will be able to modify this. We include it last, as per the comment + // above. + $variables += array('template_files' => array()); // default render function and extension. $render_function = 'theme_render_template'; @@ -767,7 +773,12 @@ function theme() { foreach (array('preprocess functions', 'process functions') as $template_phase) { foreach ($info[$template_phase] as $template_function) { if (drupal_function_exists($template_function)) { - call_user_func_array($template_function, $args); + $result = call_user_func_array($template_function, $args); + // Allow process functions to abort rendering the item by returning + // FALSE. + if ($result === FALSE) { + return ''; + } } } } @@ -1309,6 +1320,28 @@ function theme_links($links, $attributes } /** + * Return a themed edit link for an element on a page. + * + * @param $link + * An array representing the edit link to be themed, in the format expected + * by theme_links(); e.g., the array can have keys including 'title', 'href', + * 'html', etc. + * @param $element + * An array representing the editable page element. + * @return + * A themed HTML string representing the edit link. + * + * @see theme_links() + */ +function theme_edit_link($link, $element) { + // Construct a CSS class which associates this edit link with the region on + // the page that it edits. + $class = 'edit-link edit-at-' . str_replace('/', '-', $link['href']); + drupal_add_js(!empty($_REQUEST['edit_mode']) ? 'misc/edit.mode.js' : 'misc/editable.js'); + return theme('links', array($class => $link), array('class' => 'links edit-links')); +} + +/** * Return a themed image. * * @param $path @@ -1859,6 +1892,37 @@ function template_preprocess(&$variables // Initialize html class attribute for the current hook. $variables['classes_array'] = array($hook); + // If the first item passed to the theme function is an editable page + // element which the current user has access to, populate useful variables + // for constructing edit links and other editable markup. + $element = reset($variables); + $variables['is_editable'] = is_array($element) && isset($element['#edit']) && !empty($element['#editable']); + // Do not show edit links when the user is already on the page that is being + // linked to. + $show_edit_links = $variables['is_editable'] && isset($_GET['q']) && $element['#edit'] != $_GET['q']; + // Add appropriate CSS classes that define this element as editable and + // associate it with its edit link. + if ($variables['is_editable']) { + $variables['classes_array'][] = 'editable-region editable-at-' . str_replace('/', '-', $element['#edit']); + } + // Define the default edit link. + $variables['edit_url'] = $show_edit_links ? url($element['#edit'], array('query' => drupal_get_destination())) : ''; + if ($show_edit_links) { + $variables['edit_link_text'] = isset($element['#edit_text']) ? $element['#edit_text'] : t('Edit this item'); + $variables['edit_link_info'] = array( + 'title' => $variables['edit_link_text'], + 'href' => $element['#edit'], + // Refer users back to the current page after they have completed their + // edits. + 'query' => drupal_get_destination(), + ); + } + else { + $variables['edit_link_text'] = ''; + $variables['edit_link_info'] = ''; + } + $variables['edit_link'] = $show_edit_links ? theme('edit_link', $variables['edit_link_info'], $element) : ''; + // Set default variables that depend on the database. $variables['is_admin'] = FALSE; $variables['is_front'] = FALSE; @@ -1958,7 +2022,10 @@ function template_preprocess_page(&$vari $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(); $variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_render(drupal_get_form('search_theme_form')) : ''); - $variables['site_name'] = (theme_get_setting('toggle_name') ? filter_xss_admin(variable_get('site_name', 'Drupal')) : ''); + // TODO: Remove. This is just a quick hack to give a rough feel for the + // "edit mode" in the D7UX proposal. + $edit_mode_link = !empty($_REQUEST['edit_mode']) ? l(t('global edit mode: On'), $_GET['q']) : l(t('global edit mode: Off'), $_GET['q'], array('query' => 'edit_mode=1')); + $variables['site_name'] = (theme_get_setting('toggle_name') ? t('!site_name (!edit_mode)', array('!site_name' => filter_xss_admin(variable_get('site_name', 'Drupal')), '!edit_mode' => $edit_mode_link)) : ''); $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? filter_xss_admin(variable_get('site_slogan', '')) : ''); $variables['css'] = drupal_add_css(); $variables['styles'] = drupal_get_css(); Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.345 diff -u -p -r1.345 block.module --- modules/block/block.module 12 Jun 2009 09:02:55 -0000 1.345 +++ modules/block/block.module 16 Jun 2009 09:49:31 -0000 @@ -276,6 +276,8 @@ function block_get_blocks_by_region($reg $build[$key] += array( '#theme_wrapper' => 'block', '#block' => $block, + '#edit' => 'admin/build/block/configure/' . $block->module . '/' . $block->delta, + '#edit_text' => t('Configure this block'), '#weight' => ++$weight, ); } @@ -829,6 +831,22 @@ function block_flush_caches() { function template_preprocess_block(&$variables) { $block_counter = &drupal_static(__FUNCTION__, array()); $variables['block'] = $variables['elements']['#block']; + + // Create the $content variable that templates expect. If the block is + // empty, do not show it. + $variables['content'] = $variables['elements']['#children']; + if (empty($variables['content'])) { + // TODO: This is necessary to match the behavior in _block_render_blocks() + // when $block->content contains HTML output rather than a structured + // array. The inconsistency is ugly, though. It also means that the array + // of blocks per region inserted into the page via block_page_alter() can + // contain a larger number of blocks than actually will display on the + // page. (This part actually might not be bad, though; it means that other + // modules have a chance to insert content into these "empty" blocks and + // therefore make them appear after all, if they want to.) + return FALSE; + } + // All blocks get an independent counter for each region. if (!isset($block_counter[$variables['block']->region])) { $block_counter[$variables['block']->region] = 1; @@ -837,9 +855,6 @@ function template_preprocess_block(&$var $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even'; $variables['block_id'] = $block_counter[$variables['block']->region]++; - // Create the $content variable that templates expect. - $variables['content'] = $variables['elements']['#children']; - $variables['classes_array'][] = 'block-' . $variables['block']->module; $variables['template_files'][] = 'block-' . $variables['block']->region; Index: modules/block/block.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.tpl.php,v retrieving revision 1.3 diff -u -p -r1.3 block.tpl.php --- modules/block/block.tpl.php 12 Jun 2009 09:02:55 -0000 1.3 +++ modules/block/block.tpl.php 16 Jun 2009 09:49:31 -0000 @@ -30,6 +30,15 @@ * - $logged_in: Flags true when the current user is a logged-in member. * - $is_admin: Flags true when the current user is an administrator. * + * Edit variables: + * - $is_editable: TRUE when the block is editable by the current user. + * - $edit_link: An already-themed link to the edit page for the block; may be + * empty. + * - $edit_url: The full URL to edit the block; may be empty. + * - $edit_link_text: A caption for the link to edit the block; may be empty. + * - $edit_link_info: An array of information describing the link to edit the + * block; may be empty. + * * @see template_preprocess() * @see template_preprocess_block() * @see template_process() @@ -43,4 +52,8 @@
+ + + + Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.192 diff -u -p -r1.192 menu.module --- modules/menu/menu.module 27 May 2009 18:33:58 -0000 1.192 +++ modules/menu/menu.module 16 Jun 2009 09:49:31 -0000 @@ -149,6 +149,10 @@ function menu_theme() { 'file' => 'menu.admin.inc', 'arguments' => array('title' => NULL, 'name' => NULL, 'description' => NULL), ), + 'menu_editable' => array( + 'arguments' => array('element' => NULL), + 'template' => 'menu-editable', + ), ); } @@ -293,6 +297,30 @@ function menu_block_view($delta = '') { } /** + * Implement hook_page_alter(). + */ +function menu_page_alter(&$page) { + // Search for every non-empty menu block on the page. + // TODO: This works, but cries out for something like hook_block_alter()... + foreach (element_children($page) as $region) { + $blocks = &$page[$region]; + foreach (element_children($blocks) as $id) { + if (isset($blocks[$id]['content']['#theme'])) { + $block = $blocks[$id]['#block']; + $content = &$blocks[$id]['content']; + if ($content['#theme'] == 'menu_tree' && !empty($content['#menu'])) { + // If we have a non-empty menu tree, wrap it in a theme function + // that will display an edit link. + $content['#theme_wrapper'] = 'menu_editable'; + $content['#edit'] = 'admin/build/menu-customize/' . $block->delta; + $content['#edit_text'] = t('Edit this menu'); + } + } + } + } +} + +/** * Implement hook_node_insert(). */ function menu_node_insert($node) { @@ -488,3 +516,11 @@ function menu_get_menus($all = TRUE) { return $query->execute()->fetchAllKeyed(); } + +/** + * TODO: Comment. + */ +function template_preprocess_menu_editable(&$variables) { + // Create the $content variable that templates expect. + $variables['content'] = $variables['element']['#children']; +} Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1070 diff -u -p -r1.1070 node.module --- modules/node/node.module 12 Jun 2009 08:39:38 -0000 1.1070 +++ modules/node/node.module 16 Jun 2009 09:49:32 -0000 @@ -1122,6 +1122,8 @@ function node_build($node, $teaser = FAL $build += array( '#theme' => 'node', '#node' => $node, + '#edit' => 'node/' . $node->nid . '/edit', + '#edit_text' => t('Edit this @type', array('@type' => drupal_strtolower(node_type_get_name($node)))), '#teaser' => $teaser, ); return $build; Index: modules/node/node.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.tpl.php,v retrieving revision 1.12 diff -u -p -r1.12 node.tpl.php --- modules/node/node.tpl.php 28 May 2009 16:44:06 -0000 1.12 +++ modules/node/node.tpl.php 16 Jun 2009 09:49:32 -0000 @@ -47,6 +47,15 @@ * teaser listings. * - $id: Position of the node. Increments each time it's output. * + * Edit variables: + * - $is_editable: TRUE when the node is editable by the current user. + * - $edit_link: An already-themed link to the edit page for the node; may be + * empty. + * - $edit_url: The full URL to edit the node; may be empty. + * - $edit_link_text: A caption for the link to edit the node; may be empty. + * - $edit_link_info: An array of information describing the link to edit the + * node; may be empty. + * * Node status variables: * - $teaser: Flag for the teaser state. * - $page: Flag for the full page state. @@ -89,6 +98,10 @@ + + + + - \ No newline at end of file + Index: modules/system/system.css =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.css,v retrieving revision 1.54 diff -u -p -r1.54 system.css --- modules/system/system.css 11 Apr 2009 22:19:45 -0000 1.54 +++ modules/system/system.css 16 Jun 2009 09:49:33 -0000 @@ -490,6 +490,17 @@ table.sticky-header { } /* +** Highlighted regions for editable.js +*/ +.active-editable-region { + outline: solid red 2px; +} + +.active-editable-link a:hover { + color: red; +} + +/* ** Installation clean URLs */ #clean-url.install { Index: themes/garland/block.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/block.tpl.php,v retrieving revision 1.7 diff -u -p -r1.7 block.tpl.php --- themes/garland/block.tpl.php 12 Jun 2009 09:02:55 -0000 1.7 +++ themes/garland/block.tpl.php 16 Jun 2009 09:49:33 -0000 @@ -8,4 +8,9 @@
+ + + + + Index: themes/garland/node.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/node.tpl.php,v retrieving revision 1.10 diff -u -p -r1.10 node.tpl.php --- themes/garland/node.tpl.php 28 May 2009 16:44:07 -0000 1.10 +++ themes/garland/node.tpl.php 16 Jun 2009 09:49:33 -0000 @@ -28,6 +28,10 @@ + + + + Index: themes/garland/style.css =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/style.css,v retrieving revision 1.57 diff -u -p -r1.57 style.css --- themes/garland/style.css 31 May 2009 00:51:41 -0000 1.57 +++ themes/garland/style.css 16 Jun 2009 09:49:33 -0000 @@ -290,6 +290,10 @@ table .form-button, table .form-submit { margin-bottom: 2.5em; } +.edit-link { + font-size: 0.8em; +} + /** * Layout */ Index: themes/garland/template.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/template.php,v retrieving revision 1.22 diff -u -p -r1.22 template.php --- themes/garland/template.php 2 Jun 2009 03:57:22 -0000 1.22 +++ themes/garland/template.php 16 Jun 2009 09:49:33 -0000 @@ -47,6 +47,9 @@ function garland_preprocess_page(&$vars) if (!empty($site_fields)) { $site_fields[0] = '' . $site_fields[0] . ''; } + // TODO: Remove. This is just a quick hack to give a rough feel for the + // "edit mode" in the D7UX proposal. + $site_fields[0] = $vars['site_name']; $vars['site_html'] = implode(' ', $site_fields); // Hook into color.module