Binary files ../drupal-themeswo/.DS_Store and ./.DS_Store differ diff -urNp ../drupal-themeswo/includes/bootstrap.inc ./includes/bootstrap.inc --- ../drupal-themeswo/includes/bootstrap.inc 2007-03-28 07:08:21.000000000 -0700 +++ ./includes/bootstrap.inc 2007-03-31 12:13:22.000000000 -0700 @@ -922,6 +922,9 @@ function drupal_maintenance_theme() { drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module'); drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module'); $theme = ''; + + // Special case registry of theme functions used by the installer + _theme_set_registry(drupal_common_themes()); } /** diff -urNp ../drupal-themeswo/includes/common.inc ./includes/common.inc --- ../drupal-themeswo/includes/common.inc 2007-03-29 16:17:15.000000000 -0700 +++ ./includes/common.inc 2007-03-31 13:24:03.000000000 -0700 @@ -2311,3 +2311,258 @@ function int2vancode($i = 0) { $length = strlen($num); return chr($length + ord('0') - 1) . $num; } + +/** + * Provide theme registration for themes across .inc files. + */ +function drupal_common_themes() { + return array( + // theme.inc + 'placeholder' => array( + 'function' => 'theme_placeholder', + 'arguments' => array('text' => NULL) + ), + 'page' => array( + 'function' => 'theme_page', + 'file' => 'theme.base.inc', + 'path' => 'includes', + 'arguments' => array('content' => NULL, 'show_blocks' => TRUE), + ), + 'maintenance_page' => array( + 'function' => 'theme_maintenance_page', + 'arguments' => array('content' => NULL, 'messages' => TRUE), + ), + 'install_page' => array( + 'function' => 'theme_install_page', + 'arguments' => array('content' => NULL), + ), + 'task_list' => array( + 'function' => 'theme_task_list', + 'arguments' => array('items' => NULL, 'active' => NULL), + ), + 'status_messages' => array( + 'function' => 'theme_status_messages', + 'arguments' => array('display' => NULL), + ), + 'links' => array( + 'function' => 'theme_links', + 'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')), + ), + 'image' => array( + 'function' => 'theme_image', + 'arguments' => array('path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE), + ), + 'breadcrumb' => array( + 'function' => 'theme_breadcrumb', + 'arguments' => array('breadcrumb' => NULL), + ), + 'help' => array( + 'function' => 'theme_help', + 'arguments' => array(), + ), + 'node' => array( + 'function' => 'theme_node', + 'file' => 'theme.base.inc', + 'path' => 'includes', + 'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE), + ), + 'submenu' => array( + 'function' => 'theme_submenu', + 'arguments' => array('links' => NULL), + ), + 'table' => array( + 'function' => 'theme_table', + 'arguments' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL), + ), + 'table_select_header_cell' => array( + 'function' => 'theme_table_select_header_cell', + 'arguments' => array(), + ), + 'tablesort_indicator' => array( + 'function' => 'theme_tablesort_indicator', + 'arguments' => array('style' => NULL), + ), + 'box' => array( + 'function' => 'theme_box', + 'arguments' => array('title' => NULL, 'content' => NULL, 'region' => 'main'), + ), + 'block' => array( + 'function' => 'theme_block', + 'file' => 'theme.base.inc', + 'path' => 'includes', + 'arguments' => array('block' => NULL), + ), + 'mark' => array( + 'function' => 'theme_mark', + 'arguments' => array('type' => MARK_NEW), + ), + 'item_list' => array( + 'function' => 'theme_item_list', + 'arguments' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => NULL), + ), + 'more_help_link' => array( + 'function' => 'theme_more_help_link', + 'arguments' => array('url' => NULL), + ), + 'xml_icon' => array( + 'function' => 'theme_xml_icon', + 'arguments' => array('url' => NULL), + ), + 'feed_icon' => array( + 'function' => 'theme_feed_icon', + 'arguments' => array('url' => NULL), + ), + 'closure' => array( + 'function' => 'theme_closure', + 'arguments' => array('main' => 0), + ), + 'blocks' => array( + 'function' => 'theme_blocks', + 'arguments' => array('region' => NULL), + ), + 'username' => array( + 'function' => 'theme_username', + 'arguments' => array('object' => NULL), + ), + 'progress_bar' => array( + 'function' => 'theme_progress_bar', + 'arguments' => array('percent' => NULL, 'message' => NULL), + ), + // from pager.inc + 'pager' => array( + 'function' => 'theme_pager', + 'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()), + ), + 'pager_first' => array( + 'function' => 'theme_pager_first', + 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), + ), + 'pager_previous' => array( + 'function' => 'theme_pager_previous', + 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), + ), + 'pager_next' => array( + 'function' => 'theme_pager_next', + 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), + ), + 'pager_last' => array( + 'function' => 'theme_pager_last', + 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), + ), + 'pager_list' => array( + 'function' => 'theme_pager_list', + 'arguments' => array('limit' => NULL, 'element' => 0, 'quantity' => 5, 'text' => '', 'parameters' => array()), + ), + 'pager_link' => array( + 'function' => 'theme_pager_link', + 'arguments' => array('text' => NULL, 'page_new' => NULL, 'element' => NULL, 'parameters' => array(), 'attributes' => array()), + ), + // from locale.inc + 'locale_admin_manage_screen' => array( + 'function' => 'theme_locale_admin_manage_screen', + 'arguments' => array('form' => NULL), + ), + // from menu.inc + 'menu_item_link' => array( + 'function' => 'theme_menu_item_link', + 'arguments' => array('item' => NULL), + ), + 'menu_tree' => array( + 'function' => 'theme_menu_tree', + 'arguments' => array('tree' => NULL), + ), + 'menu_item' => array( + 'function' => 'theme_menu_item', + 'arguments' => array('link' => NULL, 'has_children' => NULL, 'menu' => ''), + ), + 'menu_local_task' => array( + 'function' => 'theme_menu_local_task', + 'arguments' => array('link' => NULL, 'active' => FALSE), + ), + 'menu_local_tasks' => array( + 'function' => 'theme_menu_local_tasks', + 'arguments' => array(), + ), + // from form.inc + 'select' => array( + 'function' => 'theme_select', + 'arguments' => array('element' => NULL), + ), + 'fieldset' => array( + 'function' => 'theme_fieldset', + 'arguments' => array('element' => NULL), + ), + 'radio' => array( + 'function' => 'theme_radio', + 'arguments' => array('element' => NULL), + ), + 'radios' => array( + 'function' => 'theme_radios', + 'arguments' => array('element' => NULL), + ), + 'password_confirm' => array( + 'function' => 'theme_password_confirm', + 'arguments' => array('element' => NULL), + ), + 'date' => array( + 'function' => 'theme_date', + 'arguments' => array('element' => NULL), + ), + 'item' => array( + 'function' => 'theme_item', + 'arguments' => array('element' => NULL), + ), + 'checkbox' => array( + 'function' => 'theme_checkbox', + 'arguments' => array('element' => NULL), + ), + 'checkboxes' => array( + 'function' => 'theme_checkboxes', + 'arguments' => array('element' => NULL), + ), + 'submit' => array( + 'function' => 'theme_submit', + 'arguments' => array('element' => NULL), + ), + 'button' => array( + 'function' => 'theme_button', + 'arguments' => array('element' => NULL), + ), + 'hidden' => array( + 'function' => 'theme_hidden', + 'arguments' => array('element' => NULL), + ), + 'token' => array( + 'function' => 'theme_token', + 'arguments' => array('element' => NULL), + ), + 'textfield' => array( + 'function' => 'theme_textfield', + 'arguments' => array('element' => NULL), + ), + 'form' => array( + 'function' => 'theme_form', + 'arguments' => array('element' => NULL), + ), + 'textarea' => array( + 'function' => 'theme_textarea', + 'arguments' => array('element' => NULL), + ), + 'markup' => array( + 'function' => 'theme_markup', + 'arguments' => array('element' => NULL), + ), + 'password' => array( + 'function' => 'theme_password', + 'arguments' => array('element' => NULL), + ), + 'file' => array( + 'function' => 'theme_file', + 'arguments' => array('element' => NULL), + ), + 'form_element' => array( + 'function' => 'theme_form_element', + 'arguments' => array('element' => NULL, 'value' => NULL), + ), + ); +} diff -urNp ../drupal-themeswo/includes/form.inc ./includes/form.inc --- ../drupal-themeswo/includes/form.inc 2007-03-26 22:13:53.000000000 -0700 +++ ./includes/form.inc 2007-03-31 12:13:22.000000000 -0700 @@ -457,7 +457,9 @@ function drupal_render_form($form_id, &$ // Don't override #theme if someone already set it. if (!isset($form['#theme'])) { - if (theme_get_function($form_id)) { + init_theme(); + $registry = theme_get_registry(); + if (isset($registry[$form_id])) { $form['#theme'] = $form_id; } } diff -urNp ../drupal-themeswo/includes/menu.inc ./includes/menu.inc --- ../drupal-themeswo/includes/menu.inc 2007-03-26 22:13:53.000000000 -0700 +++ ./includes/menu.inc 2007-03-31 13:14:01.000000000 -0700 @@ -498,6 +498,23 @@ function theme_menu_item_link($item) { } /** + * Returns the rendered local tasks. The default implementation renders + * them as tabs. + */ +function theme_menu_local_tasks() { + $output = ''; + + if ($primary = menu_primary_local_tasks()) { + $output .= "\n"; + } + if ($secondary = menu_secondary_local_tasks()) { + $output .= "\n"; + } + + return $output; +} + +/** * Generate the HTML output for a menu tree */ function theme_menu_tree($tree) { diff -urNp ../drupal-themeswo/includes/theme.inc ./includes/theme.inc --- ../drupal-themeswo/includes/theme.inc 2007-03-26 22:13:53.000000000 -0700 +++ ./includes/theme.inc 2007-03-31 12:13:22.000000000 -0700 @@ -72,6 +72,7 @@ function init_theme() { if (strpos($themes[$theme]->filename, '.theme')) { // file is a theme; include it include_once './' . $themes[$theme]->filename; + _theme_load_registry($theme); } elseif (strpos($themes[$theme]->description, '.engine')) { // file is a template; include its engine @@ -80,10 +81,104 @@ function init_theme() { if (function_exists($theme_engine .'_init')) { call_user_func($theme_engine .'_init', $themes[$theme]); } + _theme_load_registry($theme, $theme_engine); } } /** + * Retrieve the stored theme registry. If the theme registry is already + * in memory it will be returned; otherwise it will attempt to load the + * registry from cache. If this fails, it will construct the registry and + * cache it. + */ +function theme_get_registry($registry = NULL) { + static $theme_registry = NULL; + if (isset($registry)) { + $theme_registry = $registry; + } + + return $theme_registry; +} + +/** + * Store the theme registry in memory. + */ +function _theme_set_registry($registry) { + // Pass through for setting of static variable. + return theme_get_registry($registry); +} + +/** + * Get the theme_registry cache from the database; if it doesn't exist, build + * it. + */ +function _theme_load_registry($theme, $theme_engine = NULL) { + // TODO: use a separate cache for this. + $cache = cache_get("theme_registry:$theme", 'cache'); + if (isset($cache->data)) { + $registry = unserialize($cache->data); + } + else { + $registry = _theme_build_registry($theme, $theme_engine); + _theme_save_registry($theme, $registry); + } + _theme_set_registry($registry); +} + +/** + * Write the theme_registry cache into the database. + */ +function _theme_save_registry($theme, $registry) { + // TODO: use a separate cache for this. + cache_set("theme_registry:$theme", 'cache', serialize($registry)); +} + +/** + * Process a single invocation of the themes hook. + */ +function _theme_process_registry(&$cache, $name, $type) { + $function = $name .'_themes'; + if (function_exists($function)) { + $result = $function($cache); + + // Automatically find paths + $path = drupal_get_path($type, $name); + foreach ($result as $hook => $info) { + $result[$hook]['type'] = $type; + if (isset($info['file']) && !isset($info['path'])) { + $result[$hook]['file'] = $path .'/'. $info['file']; + } + // If 'arguments' have been defined previously, carry them forward. + // This should happen if a theme overrides a Drupal defined theme + // function, for example. + if (!isset($info['arguments']) && isset($cache[$hook])) { + $result[$hook]['arguments'] = $cache[$hook]['arguments']; + } + } + + $cache = array_merge($cache, $result); + } +} + +/** + * Rebuild the hook theme_registry cache. + */ +function _theme_build_registry($theme, $theme_engine) { + $cache = array(); + foreach (module_implements('themes') as $module) { + _theme_process_registry($cache, $module, 'module'); + } + + if ($theme_engine) { + _theme_process_registry($cache, $theme_engine, 'theme_engine'); + } + + _theme_process_registry($cache, $theme, 'theme'); + + return $cache; +} + +/** * Provides a list of currently available themes. * * @param $refresh @@ -140,18 +235,41 @@ function list_theme_engines($refresh = F } /** - * Generate the themed representation of a Drupal object. - * - * All requests for themed functions must go through this function. It examines - * the request and routes it to the appropriate theme function. If the current - * theme does not implement the requested function, then the current theme - * engine is checked. If neither the engine nor theme implement the requested - * function, then the base theme function is called. + * Generate the themed output. * - * For example, to retrieve the HTML that is output by theme_page($output), a - * module should call theme('page', $output). + * All requests for theme hooks must go through this function. It examines + * the request and routes it to the appropriate theme function. The theme + * registry is checked to determine which implementation to use, which may + * be a function or a template. + * + * If the implementation is a function, it is executed and its return value + * passed along. + * + * If the implementation is a template, the arguments are converted to a + * $variables array. This array is then modified by the theme engine (if + * applicable) and the theme. The following functions may be used to modify + * the $variables array: + * + * ENGINE_engine_variables(&$variables) + * This function should only be implemented by theme engines and is exists + * so that the theme engine can set necessary variables. It is commonly + * used to set global variables such as $directory and $is_front_page. + * ENGINE_engine_variables_HOOK(&$variables) + * This is the same as the previous function, but is called only per hook. + * ENGINE_variables_HOOK(&$variables) + * ENGINE_variables(&$variables) + * This is meant to be used by themes that utilize a theme engine; as it is + * good practice for these themes to use the theme engine's name for + * their functions so that they may share code. In PHPTemplate, these + * functions will appear in template.php + * THEME_variables_HOOK(&$variables) + * THEME_variables(&$variables) + * These functions are based upon the raw theme; they should primarily be + * used by themes that do not use an engine or by themes that need small + * changes to what has already been established in the theme engine version + * of the function. * - * @param $function + * @param $hook * The name of the theme function to call. * @param ... * Additional arguments to pass along to the theme function. @@ -159,48 +277,125 @@ function list_theme_engines($refresh = F * An HTML string that generates the themed output. */ function theme() { - static $functions; $args = func_get_args(); - $function = array_shift($args); + $hook = array_shift($args); - if (!isset($functions[$function])) { - $functions[$function] = theme_get_function($function); + static $hooks = NULL; + if (!isset($hooks)) { + init_theme(); + $hooks = theme_get_registry(); + } + + if (!isset($hooks[$hook])) { + return; } - if ($functions[$function]) { - return call_user_func_array($functions[$function], $args); + + $info = $hooks[$hook]; + + if (isset($info['function'])) { + // The theme call is a function. + // Include a file if this theme function is held elsewhere. + if (!empty($info['file'])) { + include_once($info['file']); + } + return call_user_func_array($info['function'], $args); + } + else { + // The theme call is a template. + $variables = array( + 'template_files' => array() + ); + if (!empty($info['arguments'])) { + $count = 0; + foreach ($info['arguments'] as $name => $default) { + $variables[$name] = isset($args[$count]) ? $args[$count] : $default; + $count++; + } + } + + // default render function and extension. + $render_function = 'theme_render_template'; + $extension = '.tpl.php'; + $variables_list = array(); + + // Run through the theme engine variables, if necessary + global $theme_engine; + if (isset($theme_engine)) { + // Call each of our variable override functions. We allow + // several to create cleaner code. + $variables_list[] = $theme_engine .'_engine_variables'; + $variables_list[] = $theme_engine .'_engine_variables_'. $hook; + $variables_list[] = $theme_engine .'_variables'; + $variables_list[] = $theme_engine .'_variables_'. $hook; + + // If theme or theme engine is implementing this, it may have + // a different extension and a different renderer. + if ($hooks[$hook]['type'] != 'module') { + if (function_exists($theme_engine .'_render_template')) { + $render_function = $theme_engine .'_render_template'; + } + $extension_function = $theme_engine .'_extension'; + if (function_exists($extension_function)) { + $extension = $extension_function(); + } + } + } + + // Add theme specific variable substitution: + global $theme; + $variables_list[] = $theme .'_variables'; + $variables_list[] = $theme .'_variables_'. $hook; + + // This construct ensures that we can keep a reference through + // call_user_func_array. + $args = array(&$variables, $hook); + foreach ($variables_list as $variables_function) { + if (function_exists($variables_function)) { + call_user_func_array($variables_function, $args); + } + } + + // Get suggestions for alternate templates out of the variables + // that were set. This lets us dynamically choose a template + // from a list. The order is FILO, so this array is ordered from + // least appropriate first to most appropriate last. + $suggestions = array(); + + if (isset($variables['template_files'])) { + $suggestions = $variables['template_files']; + } + if (isset($variables['template_file'])) { + $suggestions[] = $variables['template_file']; + } + + if ($suggestions) { + $template_file = drupal_discover_template($suggestions, $extension); + } + + if (empty($template_file)) { + $template_file = $hooks[$hook]['file'] . $extension; + if (isset($hooks[$hook]['path'])) { + $template_file = $hooks[$hook]['path'] .'/'. $template_file; + } + } + return $render_function($template_file, $variables); } } /** - * Determine if a theme function exists, and if so return which one was found. - * - * @param $function - * The name of the theme function to test. - * @return - * The name of the theme function that should be used, or FALSE if no function exists. + * Choose which template file to actually render; these are all + * suggested templates from the theme. */ -function theme_get_function($function) { - global $theme, $theme_engine; +function drupal_discover_template($suggestions, $extension = '.tpl.php') { + global $theme_engine; - // Because theme() is called a lot, calling init_theme() only to have it - // smartly return is a noticeable performance hit. Don't do it. - if (!isset($theme)) { - init_theme(); - } - - if (($theme != '') && function_exists($theme .'_'. $function)) { - // call theme function - return $theme .'_'. $function; - } - elseif (($theme != '') && isset($theme_engine) && function_exists($theme_engine .'_'. $function)) { - // call engine function - return $theme_engine .'_'. $function; - } - elseif (function_exists('theme_'. $function)){ - // call Drupal function - return 'theme_'. $function; + // Loop through any suggestions in FIFO order. + $suggestions = array_reverse($suggestions); + foreach ($suggestions as $suggestion) { + if (!empty($suggestion) && file_exists($file = path_to_theme() .'/'. $suggestion . $extension)) { + return $file; + } } - return FALSE; } /** @@ -348,16 +543,79 @@ function theme_get_setting($setting_name } /** - * @defgroup themeable Themeable functions + * Render a system default template, which is essentially a PHP template. + * + * @param $file + * The filename of the template to render. + * @param $variables + * A keyed array of variables that will appear in the output. + * + * @return + * The output generated by the template. + */ +function theme_render_template($file, $variables) { + extract($variables, EXTR_SKIP); // Extract the variables to a local namespace + ob_start(); // Start output buffering + include "./$file"; // Include the file + $contents = ob_get_contents(); // Get the contents of the buffer + ob_end_clean(); // End buffering and discard + return $contents; // Return the contents +} + +/** + * @defgroup themeable Default theme implementations * @{ - * Functions that display HTML, and which can be customized by themes. + * Functions and templates that present output to the user, and can be + * implemented by themes. * - * All functions that produce HTML for display should be themeable. This means - * that they should be named with the theme_ prefix, and invoked using theme() - * rather than being called directly. This allows themes to override the display - * of any Drupal object. + * Drupal's presentation layer is a pluggable system known as the theme + * layer. Each theme can take control over most of Drupal's output, and + * has complete control over the CSS. + * + * Inside Drupal, the theme layer is utilized by the use of the theme() + * function, which is passed the name of a component (the theme hook) + * and several arguments. For example, theme('table', $header, $rows); + * + * As of Drupal 6, every theme hook is required to be registered by the + * module that owns it, so that Drupal can tell what to do with it and + * to make it simple for themes to identify and override the behavior + * for these calls. + * + * The theme hooks are registered via hook_themes(), which returns an + * array of arrays with information about the hook. It describes the + * arguments the function or template will need, and provides + * defaults for the template in case they are not filled in. If the default + * implementation is a function, by convention it is named theme_HOOK(). + * + * Each module should provide a default implementation for themes that + * it registers. This implementation may be either a function or a template; + * if it is a function it must be specified via hook_themes(). By convention, + * default implementations of theme hooks are named theme_HOOK. Default + * template implementations are stored in the module directory. + * + * Drupal's default template renderer is a simple PHP parsing engine that + * includes the template and stores the output. Drupal's theme engines + * can provide alternate template engines, such as XTemplate, Smarty and + * PHPTal. The most common template engine is PHPTemplate (included with + * Drupal and implemented in phptemplate.engine, which uses Drupal's default + * template renderer. + * + * Themes can implement their own version of theme hooks, either as functions + * or files. If using a pure .theme without an engine, the .theme is required + * to implement its own version of hook_themes() to tell Drupal what it is + * implementing; themes utilizing an engine will have their well-named + * theming functions automatically registered for them. While this can vary + * based upon the theme engine, the standard set by phptemplate is that theme + * functions should be named either phptemplate_HOOK or THEMENAME_HOOK. For + * example, for Drupal's default theme (Garland) to implement the 'table' hook, + * the phptemplate.engine would find phptemplate_table() or garland_table(). + * The ENGINE_HOOK() syntax is preferred, as this can be used by sub-themes + * (which are themes that share code but use different stylesheets). * * The theme system is described and defined in theme.inc. + * + * @see theme() + * @see hook_themes() */ /** @@ -373,55 +631,6 @@ function theme_placeholder($text) { return ''. check_plain($text) .''; } -/** - * Return an entire Drupal page displaying the supplied content. - * - * @param $content - * A string to display in the main content area of the page. - * @return - * A string containing the entire HTML page. - */ -function theme_page($content) { - // Get blocks before so that they can alter the header (JavaScript, Stylesheets etc.) - $blocks = theme('blocks', 'all'); - - $output = "\n"; - $output .= ''; - $output .= ''; - $output .= ' '. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'Drupal')) .''; - $output .= drupal_get_html_head(); - $output .= drupal_get_css(); - $output .= drupal_get_js(); - - $output .= ' '; - $output .= ' '; - $output .= '
'; - - $output .= $blocks; - $output .= ''; - - $output .= theme('breadcrumb', drupal_get_breadcrumb()); - $output .= '

' . drupal_get_title() . '

'; - - if ($tabs = theme('menu_local_tasks')) { - $output .= $tabs; - } - - $output .= theme('help'); - - $output .= theme('status_messages'); - - $output .= "\n\n"; - $output .= $content; - $output .= drupal_get_feeds(); - $output .= "\n\n"; - - $output .= '
'; - $output .= theme('closure'); - $output .= ''; - - return $output; -} /** * Generate a themed maintenance page. @@ -458,9 +667,7 @@ function theme_maintenance_page($content 'content' => $content, ); - // Render simplified PHPTemplate. - include_once './themes/engines/phptemplate/phptemplate.engine'; - $output = _phptemplate_render('misc/maintenance.tpl.php', $variables); + $output = theme_render_template('misc/maintenance.tpl.php', $variables); return $output; } @@ -509,9 +716,7 @@ function theme_install_page($content) { $variables['messages'] .= theme('status_messages', 'status'); } - // Render simplified PHPTemplate. - include_once './themes/engines/phptemplate/phptemplate.engine'; - return _phptemplate_render('misc/maintenance.tpl.php', $variables); + return theme_render_template('misc/maintenance.tpl.php', $variables); } /** @@ -678,66 +883,6 @@ function theme_help() { } /** - * Return a themed node. - * - * @param $node - * An object providing all relevant information for displaying a node: - * - $node->nid: The ID of the node. - * - $node->type: The content type (story, blog, forum...). - * - $node->title: The title of the node. - * - $node->created: The creation date, as a UNIX timestamp. - * - $node->teaser: A shortened version of the node body. - * - $node->body: The entire node contents. - * - $node->changed: The last modification date, as a UNIX timestamp. - * - $node->uid: The ID of the author. - * - $node->username: The username of the author. - * @param $teaser - * Whether to display the teaser only, as on the main page. - * @param $page - * Whether to display the node as a standalone page. If TRUE, do not display - * the title because it will be provided by the menu system. - * @return - * A string containing the node output. - */ -function theme_node($node, $teaser = FALSE, $page = FALSE) { - if (!$node->status) { - $output = '
'; - } - - if (module_exists('taxonomy')) { - $terms = taxonomy_link('taxonomy terms', $node); - } - - if ($page == 0) { - $output .= t('!title by !name', array('!title' => '

'. check_plain($node->title) .'

', '!name' => theme('username', $node))); - } - else { - $output .= t('by !name', array('!name' => theme('username', $node))); - } - - if (count($terms)) { - $output .= ' ('. theme('links', $terms) .')
'; - } - - if ($teaser && $node->teaser) { - $output .= $node->teaser; - } - else { - $output .= $node->body; - } - - if ($node->links) { - $output .= ''; - } - - if (!$node->status) { - $output .= '
'; - } - - return $output; -} - -/** * Return a themed submenu, typically displayed under the tabs. * * @param $links @@ -904,29 +1049,6 @@ function theme_box($title, $content, $re } /** - * Return a themed block. - * - * You can style your blocks by defining .block (all blocks), - * .block-module (all blocks of module module), and - * \#block-module-delta (specific block of module module - * with delta delta) in your theme's CSS. - * - * @param $block - * An object populated with fields from the "blocks" database table - * ($block->module, $block->delta ...) and fields returned by - * module_block('view') ($block->subject, $block->content, ...). - * @return - * A string containing the block output. - */ -function theme_block($block) { - $output = "
module\" id=\"block-$block->module-$block->delta\">\n"; - $output .= "

$block->subject

\n"; - $output .= "
$block->content
\n"; - $output .= "
\n"; - return $output; -} - -/** * Return a themed marker, useful for marking new or updated * content. * diff -urNp ../drupal-themeswo/index.php ./index.php --- ../drupal-themeswo/index.php 2007-02-11 01:30:50.000000000 -0800 +++ ./index.php 2007-03-31 12:13:22.000000000 -0700 @@ -31,7 +31,6 @@ if (is_int($return)) { elseif (isset($return)) { // Print any value (including an empty string) except NULL or undefined: print theme('page', $return); - } drupal_page_footer(); diff -urNp ../drupal-themeswo/modules/aggregator/aggregator.module ./modules/aggregator/aggregator.module --- ../drupal-themeswo/modules/aggregator/aggregator.module 2007-03-26 22:13:53.000000000 -0700 +++ ./modules/aggregator/aggregator.module 2007-03-31 12:13:22.000000000 -0700 @@ -26,6 +26,34 @@ function aggregator_help($section) { } /** + * Implementation of hook_themes() + */ +function aggregator_themes() { + return array( + 'aggregator_page_list' => array( + 'function' => 'theme_aggregator_page_list', + 'arguments' => array('form' => NULL), + ), + 'aggregator_feed' => array( + 'function' => 'theme_aggregator_feed', + 'arguments' => array('feed' => NULL), + ), + 'aggregator_block_item' => array( + 'function' => 'theme_aggregator_block_item', + 'arguments' => array('item' => NULL, 'feed' => 0), + ), + 'aggregator_summary_item' => array( + 'function' => 'theme_aggregator_summary_item', + 'arguments' => array('item' => NULL), + ), + 'aggregator_page_item' => array( + 'function' => 'theme_aggregator_page_item', + 'arguments' => array('item' => NULL), + ), + + ); + +/** * Implementation of hook_menu(). */ function aggregator_menu() { diff -urNp ../drupal-themeswo/modules/block/block.module ./modules/block/block.module --- ../drupal-themeswo/modules/block/block.module 2007-03-26 22:13:53.000000000 -0700 +++ ./modules/block/block.module 2007-03-31 12:13:22.000000000 -0700 @@ -49,6 +49,18 @@ function block_help($section) { } /** + * Implementation of hook_themes() + */ +function block_themes() { + return array( + 'block_admin_display' => array( + 'function' => 'theme_block_admin_display', + 'arguments' => array('form' => NULL), + ), + ); +} + +/** * Implementation of hook_perm(). */ function block_perm() { diff -urNp ../drupal-themeswo/modules/book/book.module ./modules/book/book.module --- ../drupal-themeswo/modules/book/book.module 2007-03-26 22:13:53.000000000 -0700 +++ ./modules/book/book.module 2007-03-31 12:13:22.000000000 -0700 @@ -20,6 +20,26 @@ function book_node_info() { } /** + * Implementation of hook_themes() + */ +function book_themes() { + return array( + 'book_navigation' => array( + 'function' => 'theme_book_navigation', + 'arguments' => array('node' => NULL), + ), + 'book_export_html' => array( + 'function' => 'theme_book_export_html', + 'arguments' => array('title' => NULL, 'content' => NULL), + ), + 'book_admin_table' => array( + 'function' => 'theme_book_admin_table', + 'arguments' => array('form' => NULL), + ), + ); +} + +/** * Implementation of hook_perm(). */ function book_perm() { diff -urNp ../drupal-themeswo/modules/color/color.module ./modules/color/color.module --- ../drupal-themeswo/modules/color/color.module 2007-03-26 22:13:53.000000000 -0700 +++ ./modules/color/color.module 2007-03-31 12:13:22.000000000 -0700 @@ -2,6 +2,17 @@ // $Id: color.module,v 1.17 2007/03/27 05:13:53 unconed Exp $ /** + * Implementation of hook_themes() + */ +function color_themes() { + return array( + 'color_scheme_form' => array( + 'function' => 'theme_color_scheme_form', + 'arguments' => array('form' => NULL), + ), + ); +} +/** * Implementation of hook_form_alter(). */ function color_form_alter(&$form, $form_id) { diff -urNp ../drupal-themeswo/modules/comment/comment.module ./modules/comment/comment.module --- ../drupal-themeswo/modules/comment/comment.module 2007-03-30 00:45:19.000000000 -0700 +++ ./modules/comment/comment.module 2007-03-31 12:13:22.000000000 -0700 @@ -140,6 +140,66 @@ function comment_help($section) { } } +/** + * Implementation of hook_themes() + */ +function comment_themes() { + return array( + 'comment_block' => array( + 'function' => 'theme_comment_block', + 'arguments' => array(), + ), + 'comment_admin_overview' => array( + 'function' => 'theme_comment_admin_overview', + 'arguments' => array('form' => NULL), + ), + 'comment_preview' => array( + 'function' => 'theme_comment_preview', + 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), + ), + 'comment_view' => array( + 'function' => 'theme_comment_view', + 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), + ), + 'comment_controls' => array( + 'function' => 'theme_comment_controls', + 'arguments' => array('form' => NULL), + ), + 'comment' => array( + 'function' => 'theme_comment', + 'arguments' => array('comment' => NULL, 'links' => array()), + ), + 'comment_folded' => array( + 'function' => 'theme_comment_folded', + 'arguments' => array('comment' => NULL), + ), + 'comment_flat_collapsed' => array( + 'function' => 'theme_comment_flat_collapsed', + 'arguments' => array('comment' => NULL), + ), + 'comment_flat_expanded' => array( + 'function' => 'theme_comment_flat_expanded', + 'arguments' => array('comment' => NULL), + ), + 'comment_thread_collapsed' => array( + 'function' => 'theme_comment_thread_collapsed', + 'arguments' => array('comment' => NULL), + ), + 'comment_thread_expanded' => array( + 'function' => 'theme_comment_thread_expanded', + 'arguments' => array('comment' => NULL), + ), + 'comment_post_forbidden' => array( + 'function' => 'theme_comment_post_forbidden', + 'arguments' => array('nid' => NULL), + ), + 'comment_wrapper' => array( + 'function' => 'theme_comment_wrapper', + 'arguments' => array('content' => NULL), + ), + ); +} + function _comment_view_access($node, $cid) { return $node && $cid; } diff -urNp ../drupal-themeswo/modules/drupal/drupal.module ./modules/drupal/drupal.module --- ../drupal-themeswo/modules/drupal/drupal.module 2007-02-27 04:29:22.000000000 -0800 +++ ./modules/drupal/drupal.module 2007-03-31 12:13:22.000000000 -0700 @@ -46,6 +46,18 @@ print drupal_client_page(); } } +/** + * Implementation of hook_themes() + */ +function drupal_themes() { + return array( + 'client_list' => array( + 'function' => 'theme_client_list', + 'arguments' => array('clients' => NULL), + ), + ); +} + function drupal_sites_registry_settings() { // Check if all required fields are present if ((variable_get('site_name', 'Drupal') == 'Drupal') || (variable_get('site_name', 'Drupal') == '')) { diff -urNp ../drupal-themeswo/modules/filter/filter.module ./modules/filter/filter.module --- ../drupal-themeswo/modules/filter/filter.module 2007-03-12 04:31:02.000000000 -0700 +++ ./modules/filter/filter.module 2007-03-31 12:13:22.000000000 -0700 @@ -48,6 +48,30 @@ function filter_help($section) { } /** + * Implementation of hook_themes() + */ +function filter_themes() { + return array( + 'filter_admin_overview' => array( + 'function' => 'theme_filter_admin_overview', + 'arguments' => array('form' => NULL), + ), + 'filter_admin_order' => array( + 'function' => 'theme_filter_admin_order', + 'arguments' => array('form' => NULL), + ), + 'filter_tips' => array( + 'function' => 'theme_filter_tips', + 'arguments' => array('tips' => NULL, 'long' => FALSE, 'extra' => ''), + ), + 'filter_tips_more_info' => array( + 'function' => 'theme_filter_tips_more_info', + 'arguments' => array(), + ), + ); +} + +/** * Implementation of hook_menu(). */ function filter_menu() { diff -urNp ../drupal-themeswo/modules/forum/forum.module ./modules/forum/forum.module --- ../drupal-themeswo/modules/forum/forum.module 2007-03-28 07:08:22.000000000 -0700 +++ ./modules/forum/forum.module 2007-03-31 12:13:22.000000000 -0700 @@ -29,6 +29,34 @@ function forum_help($section) { } /** + * Implementation of hook_themes() + */ +function forum_themes() { + return array( + 'forum_display' => array( + 'function' => 'theme_forum_display', + 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), + ), + 'forum_list' => array( + 'function' => 'theme_forum_list', + 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), + ), + 'forum_topic_list' => array( + 'function' => 'theme_forum_topic_list', + 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), + ), + 'forum_icon' => array( + 'function' => 'theme_forum_icon', + 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), + ), + 'forum_topic_navigation' => array( + 'function' => 'theme_forum_topic_navigation', + 'arguments' => array('node' => NULL), + ), + ); +} + +/** * Implementation of hook_menu(). */ function forum_menu() { diff -urNp ../drupal-themeswo/modules/node/node.module ./modules/node/node.module --- ../drupal-themeswo/modules/node/node.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/node/node.module 2007-03-31 12:13:22.000000000 -0700 @@ -46,6 +46,46 @@ function node_help($section) { } /** + * Implementation of hook_themes() + */ +function node_themes() { + return array( + 'node_list' => array( + 'function' => 'theme_node_list', + 'arguments' => array('items' => NULL, 'title' => NULL), + ), + 'node_search_admin' => array( + 'function' => 'theme_node_search_admin', + 'arguments' => array('form' => NULL), + ), + 'node_filter_form' => array( + 'function' => 'theme_node_filter_form', + 'arguments' => array('form' => NULL), + ), + 'node_filters' => array( + 'function' => 'theme_node_filters', + 'arguments' => array('form' => NULL), + ), + 'node_admin_nodes' => array( + 'function' => 'theme_node_admin_nodes', + 'arguments' => array('form' => NULL), + ), + 'node_form' => array( + 'function' => 'theme_node_form', + 'arguments' => array('form' => NULL), + ), + 'node_preview' => array( + 'function' => 'theme_node_preview', + 'arguments' => array('node' => NULL), + ), + 'node_log_message' => array( + 'function' => 'theme_node_log_message', + 'arguments' => array('log' => NULL), + ), + ); +} + +/** * Implementation of hook_cron(). */ function node_cron() { @@ -2350,7 +2390,6 @@ function node_revisions() { * Menu callback; Generate a listing of promoted nodes. */ 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)); if (db_num_rows($result)) { diff -urNp ../drupal-themeswo/modules/poll/poll.module ./modules/poll/poll.module --- ../drupal-themeswo/modules/poll/poll.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/poll/poll.module 2007-03-31 12:13:22.000000000 -0700 @@ -21,6 +21,26 @@ function poll_help($section) { } /** + * Implementation of hook_themes() + */ +function poll_themes() { + return array( + 'poll_view_voting' => array( + 'function' => 'theme_poll_view_voting', + 'arguments' => array('form' => NULL), + ), + 'poll_results' => array( + 'function' => 'theme_poll_results', + 'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL, 'links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL), + ), + 'poll_bar' => array( + 'function' => 'theme_poll_bar', + 'arguments' => array('title' => NULL, 'percentage' => NULL, 'votes' => NULL, 'block' => NULL), + ), + ); +} + +/** * Implementation of hook_access(). */ function poll_access($op, $node) { diff -urNp ../drupal-themeswo/modules/profile/profile.module ./modules/profile/profile.module --- ../drupal-themeswo/modules/profile/profile.module 2007-03-30 02:38:13.000000000 -0700 +++ ./modules/profile/profile.module 2007-03-31 12:13:22.000000000 -0700 @@ -52,6 +52,21 @@ function profile_help($section) { } /** + * Implementation of hook_themes() + */ +function profile_themes() { + return array( + 'profile_block' => array( + 'function' => 'theme_profile_block', + 'arguments' => array('account' => NULL, 'fields' => array()), + ), + 'profile_listing' => array( + 'function' => 'theme_profile_listing', + 'arguments' => array('account' => NULL, 'fields' => array()), + ), ); +} + +/** * Implementation of hook_menu(). */ function profile_menu() { diff -urNp ../drupal-themeswo/modules/search/search.module ./modules/search/search.module --- ../drupal-themeswo/modules/search/search.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/search/search.module 2007-03-31 12:13:22.000000000 -0700 @@ -112,6 +112,30 @@ function search_help($section) { } /** + * Implementation of hook_themes() + */ +function search_themes() { + return array( + 'search_theme_form' => array( + 'function' => 'theme_search_theme_form', + 'arguments' => array('form' => NULL), + ), + 'search_block_form' => array( + 'function' => 'theme_search_block_form', + 'arguments' => array('form' => NULL), + ), + 'search_item' => array( + 'function' => 'theme_search_item', + 'arguments' => array('item' => NULL, 'type' => NULL), + ), + 'search_page' => array( + 'function' => 'theme_search_page', + 'arguments' => array('results' => NULL, 'type' => NULL), + ), + ); +} + +/** * Implementation of hook_perm(). */ function search_perm() { diff -urNp ../drupal-themeswo/modules/system/system.module ./modules/system/system.module --- ../drupal-themeswo/modules/system/system.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/system/system.module 2007-03-31 12:13:22.000000000 -0700 @@ -48,6 +48,46 @@ function system_help($section) { } } +function system_themes() { + return array_merge(drupal_common_themes(), array( + 'system_theme_select_form' => array( + 'function' => 'theme_system_theme_select_form', + 'arguments' => array('form' => NULL), + ), + 'system_themes_form' => array( + 'function' => 'theme_system_themes_form', + 'arguments' => array('form' => NULL), + ), + 'system_modules' => array( + 'function' => 'theme_system_modules', + 'arguments' => array('form' => NULL), + ), + 'system_modules_uninstall' => array( + 'function' => 'theme_system_modules_uninstall', + 'arguments' => array('form' => NULL), + ), + 'status_report' => array( + 'function' => 'theme_status_report', + 'arguments' => array('requirements' => NULL), + ), + 'admin_page' => array( + 'function' => 'theme_admin_page', + 'arguments' => array('blocks' => NULL), + ), + 'admin_block' => array( + 'function' => 'theme_admin_block', + 'arguments' => array('block' => NULL), + ), + 'admin_block_content' => array( + 'function' => 'theme_admin_block_content', + 'arguments' => array('content' => NULL), + ), + 'system_admin_by_module' => array( + 'function' => 'theme_system_admin_by_module', + 'arguments' => array('menu_items' => NULL), + ), + )); +} /** * Implementation of hook_perm(). */ @@ -150,7 +190,7 @@ function system_menu() { 'title' => t('Themes'), 'description' => t('Change which theme your site uses or allows users to set.'), 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_themes'), + 'page arguments' => array('system_themes_form'), ); $items['admin/build/themes/select'] = array( 'title' => t('List'), @@ -1143,7 +1183,7 @@ function system_settings_form_submit($fo /** * Menu callback; displays a listing of all themes. */ -function system_themes() { +function system_themes_form() { drupal_clear_css_cache(); $themes = system_theme_data(); @@ -1177,7 +1217,7 @@ function system_themes() { return $form; } -function theme_system_themes($form) { +function theme_system_themes_form($form) { foreach (element_children($form) as $key) { $row = array(); if (isset($form[$key]['description']) && is_array($form[$key]['description'])) { @@ -1199,7 +1239,7 @@ function theme_system_themes($form) { } -function system_themes_submit($form_id, $form_values) { +function system_themes_form_submit($form_id, $form_values) { db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'"); diff -urNp ../drupal-themeswo/modules/taxonomy/taxonomy.module ./modules/taxonomy/taxonomy.module --- ../drupal-themeswo/modules/taxonomy/taxonomy.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/taxonomy/taxonomy.module 2007-03-31 12:13:22.000000000 -0700 @@ -14,6 +14,18 @@ function taxonomy_perm() { } /** + * Implementation of hook_themes() + */ +function taxonomy_themes() { + return array( + 'taxonomy_term_select' => array( + 'function' => 'theme_taxonomy_term_select', + 'arguments' => array('element' => NULL), + ), + ); +} + +/** * Implementation of hook_link(). * * This hook is extended with $type = 'taxonomy terms' to allow themes to diff -urNp ../drupal-themeswo/modules/upload/upload.module ./modules/upload/upload.module --- ../drupal-themeswo/modules/upload/upload.module 2007-03-26 22:13:54.000000000 -0700 +++ ./modules/upload/upload.module 2007-03-31 12:13:22.000000000 -0700 @@ -23,6 +23,26 @@ function upload_help($section) { } /** + * Implementation of hook_themes() + */ +function upload_themes() { + return array( + 'upload_attachments' => array( + 'function' => 'theme_upload_attachments', + 'arguments' => array('files' => NULL), + ), + 'upload_form_current' => array( + 'function' => 'theme_upload_form_current', + 'arguments' => array('form' => NULL), + ), + 'upload_form_new' => array( + 'function' => 'theme_upload_form_new', + 'arguments' => array('form' => NULL), + ), + ); +} + +/** * Implementation of hook_perm(). */ function upload_perm() { diff -urNp ../drupal-themeswo/modules/user/user.module ./modules/user/user.module --- ../drupal-themeswo/modules/user/user.module 2007-03-30 00:45:19.000000000 -0700 +++ ./modules/user/user.module 2007-03-31 12:13:22.000000000 -0700 @@ -24,6 +24,46 @@ function user_module_invoke($type, &$arr } } +/** + * Implementation of hook_themes() + */ +function user_themes() { + return array( + 'user_picture' => array( + 'function' => 'theme_user_picture', + 'arguments' => array('account' => NULL), + ), + 'user_profile' => array( + 'function' => 'theme_user_profile', + 'arguments' => array('account' => NULL, 'fields' => NULL), + ), + 'user_list' => array( + 'function' => 'theme_user_list', + 'arguments' => array('users' => NULL, 'title' => NULL), + ), + 'user_admin_perm' => array( + 'function' => 'theme_user_admin_perm', + 'arguments' => array('form' => NULL), + ), + 'user_admin_new_role' => array( + 'function' => 'theme_user_admin_new_role', + 'arguments' => array('form' => NULL), + ), + 'user_admin_account' => array( + 'function' => 'theme_user_admin_account', + 'arguments' => array('form' => NULL), + ), + 'user_filter_form' => array( + 'function' => 'theme_user_filter_form', + 'arguments' => array('form' => NULL), + ), + 'user_filters' => array( + 'function' => 'theme_user_filters', + 'arguments' => array('form' => NULL), + ), + ); +} + function user_external_load($authname) { $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname); diff -urNp ../drupal-themeswo/modules/watchdog/watchdog.module ./modules/watchdog/watchdog.module --- ../drupal-themeswo/modules/watchdog/watchdog.module 2007-02-27 04:29:22.000000000 -0800 +++ ./modules/watchdog/watchdog.module 2007-03-31 12:13:22.000000000 -0700 @@ -28,6 +28,18 @@ function watchdog_help($section) { } /** + * Implementation of hook_themes() + */ +function watchdog_themes() { + return array( + 'watchdog_form_overview' => array( + 'function' => 'theme_watchdog_form_overview', + 'arguments' => array('form' => NULL), + ), + ); +} + +/** * Implementation of hook_menu(). */ function watchdog_menu() { diff -urNp ../drupal-themeswo/sites/default/settings.php ./sites/default/settings.php --- ../drupal-themeswo/sites/default/settings.php 2007-03-31 12:17:51.000000000 -0700 +++ ./sites/default/settings.php 2007-03-31 12:17:03.000000000 -0700 @@ -91,7 +91,7 @@ * $db_url = 'pgsql://username:password@localhost/databasename'; */ $db_url = 'mysql://root:root@localhost/drupals'; -$db_prefix = 'two'; +$db_prefix = 'tw'; /** * Base URL (optional). diff -urNp ../drupal-themeswo/theme_reg.patch ./theme_reg.patch --- ../drupal-themeswo/theme_reg.patch 1969-12-31 16:00:00.000000000 -0800 +++ ./theme_reg.patch 2007-03-31 13:46:18.000000000 -0700 @@ -0,0 +1,1559 @@ +Binary files ../drupal-themeswo/.DS_Store and ./.DS_Store differ +diff -urNp ../drupal-themeswo/includes/bootstrap.inc ./includes/bootstrap.inc +--- ../drupal-themeswo/includes/bootstrap.inc 2007-03-28 07:08:21.000000000 -0700 ++++ ./includes/bootstrap.inc 2007-03-31 12:13:22.000000000 -0700 +@@ -922,6 +922,9 @@ function drupal_maintenance_theme() { + drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module'); + drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module'); + $theme = ''; ++ ++ // Special case registry of theme functions used by the installer ++ _theme_set_registry(drupal_common_themes()); + } + + /** +diff -urNp ../drupal-themeswo/includes/common.inc ./includes/common.inc +--- ../drupal-themeswo/includes/common.inc 2007-03-29 16:17:15.000000000 -0700 ++++ ./includes/common.inc 2007-03-31 13:24:03.000000000 -0700 +@@ -2311,3 +2311,258 @@ function int2vancode($i = 0) { + $length = strlen($num); + return chr($length + ord('0') - 1) . $num; + } ++ ++/** ++ * Provide theme registration for themes across .inc files. ++ */ ++function drupal_common_themes() { ++ return array( ++ // theme.inc ++ 'placeholder' => array( ++ 'function' => 'theme_placeholder', ++ 'arguments' => array('text' => NULL) ++ ), ++ 'page' => array( ++ 'function' => 'theme_page', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('content' => NULL, 'show_blocks' => TRUE), ++ ), ++ 'maintenance_page' => array( ++ 'function' => 'theme_maintenance_page', ++ 'arguments' => array('content' => NULL, 'messages' => TRUE), ++ ), ++ 'install_page' => array( ++ 'function' => 'theme_install_page', ++ 'arguments' => array('content' => NULL), ++ ), ++ 'task_list' => array( ++ 'function' => 'theme_task_list', ++ 'arguments' => array('items' => NULL, 'active' => NULL), ++ ), ++ 'status_messages' => array( ++ 'function' => 'theme_status_messages', ++ 'arguments' => array('display' => NULL), ++ ), ++ 'links' => array( ++ 'function' => 'theme_links', ++ 'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')), ++ ), ++ 'image' => array( ++ 'function' => 'theme_image', ++ 'arguments' => array('path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE), ++ ), ++ 'breadcrumb' => array( ++ 'function' => 'theme_breadcrumb', ++ 'arguments' => array('breadcrumb' => NULL), ++ ), ++ 'help' => array( ++ 'function' => 'theme_help', ++ 'arguments' => array(), ++ ), ++ 'node' => array( ++ 'function' => 'theme_node', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE), ++ ), ++ 'submenu' => array( ++ 'function' => 'theme_submenu', ++ 'arguments' => array('links' => NULL), ++ ), ++ 'table' => array( ++ 'function' => 'theme_table', ++ 'arguments' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL), ++ ), ++ 'table_select_header_cell' => array( ++ 'function' => 'theme_table_select_header_cell', ++ 'arguments' => array(), ++ ), ++ 'tablesort_indicator' => array( ++ 'function' => 'theme_tablesort_indicator', ++ 'arguments' => array('style' => NULL), ++ ), ++ 'box' => array( ++ 'function' => 'theme_box', ++ 'arguments' => array('title' => NULL, 'content' => NULL, 'region' => 'main'), ++ ), ++ 'block' => array( ++ 'function' => 'theme_block', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('block' => NULL), ++ ), ++ 'mark' => array( ++ 'function' => 'theme_mark', ++ 'arguments' => array('type' => MARK_NEW), ++ ), ++ 'item_list' => array( ++ 'function' => 'theme_item_list', ++ 'arguments' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => NULL), ++ ), ++ 'more_help_link' => array( ++ 'function' => 'theme_more_help_link', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'xml_icon' => array( ++ 'function' => 'theme_xml_icon', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'feed_icon' => array( ++ 'function' => 'theme_feed_icon', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'closure' => array( ++ 'function' => 'theme_closure', ++ 'arguments' => array('main' => 0), ++ ), ++ 'blocks' => array( ++ 'function' => 'theme_blocks', ++ 'arguments' => array('region' => NULL), ++ ), ++ 'username' => array( ++ 'function' => 'theme_username', ++ 'arguments' => array('object' => NULL), ++ ), ++ 'progress_bar' => array( ++ 'function' => 'theme_progress_bar', ++ 'arguments' => array('percent' => NULL, 'message' => NULL), ++ ), ++ // from pager.inc ++ 'pager' => array( ++ 'function' => 'theme_pager', ++ 'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_first' => array( ++ 'function' => 'theme_pager_first', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_previous' => array( ++ 'function' => 'theme_pager_previous', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), ++ ), ++ 'pager_next' => array( ++ 'function' => 'theme_pager_next', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), ++ ), ++ 'pager_last' => array( ++ 'function' => 'theme_pager_last', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_list' => array( ++ 'function' => 'theme_pager_list', ++ 'arguments' => array('limit' => NULL, 'element' => 0, 'quantity' => 5, 'text' => '', 'parameters' => array()), ++ ), ++ 'pager_link' => array( ++ 'function' => 'theme_pager_link', ++ 'arguments' => array('text' => NULL, 'page_new' => NULL, 'element' => NULL, 'parameters' => array(), 'attributes' => array()), ++ ), ++ // from locale.inc ++ 'locale_admin_manage_screen' => array( ++ 'function' => 'theme_locale_admin_manage_screen', ++ 'arguments' => array('form' => NULL), ++ ), ++ // from menu.inc ++ 'menu_item_link' => array( ++ 'function' => 'theme_menu_item_link', ++ 'arguments' => array('item' => NULL), ++ ), ++ 'menu_tree' => array( ++ 'function' => 'theme_menu_tree', ++ 'arguments' => array('tree' => NULL), ++ ), ++ 'menu_item' => array( ++ 'function' => 'theme_menu_item', ++ 'arguments' => array('link' => NULL, 'has_children' => NULL, 'menu' => ''), ++ ), ++ 'menu_local_task' => array( ++ 'function' => 'theme_menu_local_task', ++ 'arguments' => array('link' => NULL, 'active' => FALSE), ++ ), ++ 'menu_local_tasks' => array( ++ 'function' => 'theme_menu_local_tasks', ++ 'arguments' => array(), ++ ), ++ // from form.inc ++ 'select' => array( ++ 'function' => 'theme_select', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'fieldset' => array( ++ 'function' => 'theme_fieldset', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'radio' => array( ++ 'function' => 'theme_radio', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'radios' => array( ++ 'function' => 'theme_radios', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'password_confirm' => array( ++ 'function' => 'theme_password_confirm', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'date' => array( ++ 'function' => 'theme_date', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'item' => array( ++ 'function' => 'theme_item', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'checkbox' => array( ++ 'function' => 'theme_checkbox', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'checkboxes' => array( ++ 'function' => 'theme_checkboxes', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'submit' => array( ++ 'function' => 'theme_submit', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'button' => array( ++ 'function' => 'theme_button', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'hidden' => array( ++ 'function' => 'theme_hidden', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'token' => array( ++ 'function' => 'theme_token', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'textfield' => array( ++ 'function' => 'theme_textfield', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'form' => array( ++ 'function' => 'theme_form', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'textarea' => array( ++ 'function' => 'theme_textarea', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'markup' => array( ++ 'function' => 'theme_markup', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'password' => array( ++ 'function' => 'theme_password', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'file' => array( ++ 'function' => 'theme_file', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'form_element' => array( ++ 'function' => 'theme_form_element', ++ 'arguments' => array('element' => NULL, 'value' => NULL), ++ ), ++ ); ++} +diff -urNp ../drupal-themeswo/includes/form.inc ./includes/form.inc +--- ../drupal-themeswo/includes/form.inc 2007-03-26 22:13:53.000000000 -0700 ++++ ./includes/form.inc 2007-03-31 12:13:22.000000000 -0700 +@@ -457,7 +457,9 @@ function drupal_render_form($form_id, &$ + // Don't override #theme if someone already set it. + + if (!isset($form['#theme'])) { +- if (theme_get_function($form_id)) { ++ init_theme(); ++ $registry = theme_get_registry(); ++ if (isset($registry[$form_id])) { + $form['#theme'] = $form_id; + } + } +diff -urNp ../drupal-themeswo/includes/menu.inc ./includes/menu.inc +--- ../drupal-themeswo/includes/menu.inc 2007-03-26 22:13:53.000000000 -0700 ++++ ./includes/menu.inc 2007-03-31 13:14:01.000000000 -0700 +@@ -498,6 +498,23 @@ function theme_menu_item_link($item) { + } + + /** ++ * Returns the rendered local tasks. The default implementation renders ++ * them as tabs. ++ */ ++function theme_menu_local_tasks() { ++ $output = ''; ++ ++ if ($primary = menu_primary_local_tasks()) { ++ $output .= "\n"; ++ } ++ if ($secondary = menu_secondary_local_tasks()) { ++ $output .= "\n"; ++ } ++ ++ return $output; ++} ++ ++/** + * Generate the HTML output for a menu tree + */ + function theme_menu_tree($tree) { +diff -urNp ../drupal-themeswo/includes/theme.inc ./includes/theme.inc +--- ../drupal-themeswo/includes/theme.inc 2007-03-26 22:13:53.000000000 -0700 ++++ ./includes/theme.inc 2007-03-31 12:13:22.000000000 -0700 +@@ -72,6 +72,7 @@ function init_theme() { + if (strpos($themes[$theme]->filename, '.theme')) { + // file is a theme; include it + include_once './' . $themes[$theme]->filename; ++ _theme_load_registry($theme); + } + elseif (strpos($themes[$theme]->description, '.engine')) { + // file is a template; include its engine +@@ -80,10 +81,104 @@ function init_theme() { + if (function_exists($theme_engine .'_init')) { + call_user_func($theme_engine .'_init', $themes[$theme]); + } ++ _theme_load_registry($theme, $theme_engine); + } + } + + /** ++ * Retrieve the stored theme registry. If the theme registry is already ++ * in memory it will be returned; otherwise it will attempt to load the ++ * registry from cache. If this fails, it will construct the registry and ++ * cache it. ++ */ ++function theme_get_registry($registry = NULL) { ++ static $theme_registry = NULL; ++ if (isset($registry)) { ++ $theme_registry = $registry; ++ } ++ ++ return $theme_registry; ++} ++ ++/** ++ * Store the theme registry in memory. ++ */ ++function _theme_set_registry($registry) { ++ // Pass through for setting of static variable. ++ return theme_get_registry($registry); ++} ++ ++/** ++ * Get the theme_registry cache from the database; if it doesn't exist, build ++ * it. ++ */ ++function _theme_load_registry($theme, $theme_engine = NULL) { ++ // TODO: use a separate cache for this. ++ $cache = cache_get("theme_registry:$theme", 'cache'); ++ if (isset($cache->data)) { ++ $registry = unserialize($cache->data); ++ } ++ else { ++ $registry = _theme_build_registry($theme, $theme_engine); ++ _theme_save_registry($theme, $registry); ++ } ++ _theme_set_registry($registry); ++} ++ ++/** ++ * Write the theme_registry cache into the database. ++ */ ++function _theme_save_registry($theme, $registry) { ++ // TODO: use a separate cache for this. ++ cache_set("theme_registry:$theme", 'cache', serialize($registry)); ++} ++ ++/** ++ * Process a single invocation of the themes hook. ++ */ ++function _theme_process_registry(&$cache, $name, $type) { ++ $function = $name .'_themes'; ++ if (function_exists($function)) { ++ $result = $function($cache); ++ ++ // Automatically find paths ++ $path = drupal_get_path($type, $name); ++ foreach ($result as $hook => $info) { ++ $result[$hook]['type'] = $type; ++ if (isset($info['file']) && !isset($info['path'])) { ++ $result[$hook]['file'] = $path .'/'. $info['file']; ++ } ++ // If 'arguments' have been defined previously, carry them forward. ++ // This should happen if a theme overrides a Drupal defined theme ++ // function, for example. ++ if (!isset($info['arguments']) && isset($cache[$hook])) { ++ $result[$hook]['arguments'] = $cache[$hook]['arguments']; ++ } ++ } ++ ++ $cache = array_merge($cache, $result); ++ } ++} ++ ++/** ++ * Rebuild the hook theme_registry cache. ++ */ ++function _theme_build_registry($theme, $theme_engine) { ++ $cache = array(); ++ foreach (module_implements('themes') as $module) { ++ _theme_process_registry($cache, $module, 'module'); ++ } ++ ++ if ($theme_engine) { ++ _theme_process_registry($cache, $theme_engine, 'theme_engine'); ++ } ++ ++ _theme_process_registry($cache, $theme, 'theme'); ++ ++ return $cache; ++} ++ ++/** + * Provides a list of currently available themes. + * + * @param $refresh +@@ -140,18 +235,41 @@ function list_theme_engines($refresh = F + } + + /** +- * Generate the themed representation of a Drupal object. +- * +- * All requests for themed functions must go through this function. It examines +- * the request and routes it to the appropriate theme function. If the current +- * theme does not implement the requested function, then the current theme +- * engine is checked. If neither the engine nor theme implement the requested +- * function, then the base theme function is called. ++ * Generate the themed output. + * +- * For example, to retrieve the HTML that is output by theme_page($output), a +- * module should call theme('page', $output). ++ * All requests for theme hooks must go through this function. It examines ++ * the request and routes it to the appropriate theme function. The theme ++ * registry is checked to determine which implementation to use, which may ++ * be a function or a template. ++ * ++ * If the implementation is a function, it is executed and its return value ++ * passed along. ++ * ++ * If the implementation is a template, the arguments are converted to a ++ * $variables array. This array is then modified by the theme engine (if ++ * applicable) and the theme. The following functions may be used to modify ++ * the $variables array: ++ * ++ * ENGINE_engine_variables(&$variables) ++ * This function should only be implemented by theme engines and is exists ++ * so that the theme engine can set necessary variables. It is commonly ++ * used to set global variables such as $directory and $is_front_page. ++ * ENGINE_engine_variables_HOOK(&$variables) ++ * This is the same as the previous function, but is called only per hook. ++ * ENGINE_variables_HOOK(&$variables) ++ * ENGINE_variables(&$variables) ++ * This is meant to be used by themes that utilize a theme engine; as it is ++ * good practice for these themes to use the theme engine's name for ++ * their functions so that they may share code. In PHPTemplate, these ++ * functions will appear in template.php ++ * THEME_variables_HOOK(&$variables) ++ * THEME_variables(&$variables) ++ * These functions are based upon the raw theme; they should primarily be ++ * used by themes that do not use an engine or by themes that need small ++ * changes to what has already been established in the theme engine version ++ * of the function. + * +- * @param $function ++ * @param $hook + * The name of the theme function to call. + * @param ... + * Additional arguments to pass along to the theme function. +@@ -159,48 +277,125 @@ function list_theme_engines($refresh = F + * An HTML string that generates the themed output. + */ + function theme() { +- static $functions; + $args = func_get_args(); +- $function = array_shift($args); ++ $hook = array_shift($args); + +- if (!isset($functions[$function])) { +- $functions[$function] = theme_get_function($function); ++ static $hooks = NULL; ++ if (!isset($hooks)) { ++ init_theme(); ++ $hooks = theme_get_registry(); ++ } ++ ++ if (!isset($hooks[$hook])) { ++ return; + } +- if ($functions[$function]) { +- return call_user_func_array($functions[$function], $args); ++ ++ $info = $hooks[$hook]; ++ ++ if (isset($info['function'])) { ++ // The theme call is a function. ++ // Include a file if this theme function is held elsewhere. ++ if (!empty($info['file'])) { ++ include_once($info['file']); ++ } ++ return call_user_func_array($info['function'], $args); ++ } ++ else { ++ // The theme call is a template. ++ $variables = array( ++ 'template_files' => array() ++ ); ++ if (!empty($info['arguments'])) { ++ $count = 0; ++ foreach ($info['arguments'] as $name => $default) { ++ $variables[$name] = isset($args[$count]) ? $args[$count] : $default; ++ $count++; ++ } ++ } ++ ++ // default render function and extension. ++ $render_function = 'theme_render_template'; ++ $extension = '.tpl.php'; ++ $variables_list = array(); ++ ++ // Run through the theme engine variables, if necessary ++ global $theme_engine; ++ if (isset($theme_engine)) { ++ // Call each of our variable override functions. We allow ++ // several to create cleaner code. ++ $variables_list[] = $theme_engine .'_engine_variables'; ++ $variables_list[] = $theme_engine .'_engine_variables_'. $hook; ++ $variables_list[] = $theme_engine .'_variables'; ++ $variables_list[] = $theme_engine .'_variables_'. $hook; ++ ++ // If theme or theme engine is implementing this, it may have ++ // a different extension and a different renderer. ++ if ($hooks[$hook]['type'] != 'module') { ++ if (function_exists($theme_engine .'_render_template')) { ++ $render_function = $theme_engine .'_render_template'; ++ } ++ $extension_function = $theme_engine .'_extension'; ++ if (function_exists($extension_function)) { ++ $extension = $extension_function(); ++ } ++ } ++ } ++ ++ // Add theme specific variable substitution: ++ global $theme; ++ $variables_list[] = $theme .'_variables'; ++ $variables_list[] = $theme .'_variables_'. $hook; ++ ++ // This construct ensures that we can keep a reference through ++ // call_user_func_array. ++ $args = array(&$variables, $hook); ++ foreach ($variables_list as $variables_function) { ++ if (function_exists($variables_function)) { ++ call_user_func_array($variables_function, $args); ++ } ++ } ++ ++ // Get suggestions for alternate templates out of the variables ++ // that were set. This lets us dynamically choose a template ++ // from a list. The order is FILO, so this array is ordered from ++ // least appropriate first to most appropriate last. ++ $suggestions = array(); ++ ++ if (isset($variables['template_files'])) { ++ $suggestions = $variables['template_files']; ++ } ++ if (isset($variables['template_file'])) { ++ $suggestions[] = $variables['template_file']; ++ } ++ ++ if ($suggestions) { ++ $template_file = drupal_discover_template($suggestions, $extension); ++ } ++ ++ if (empty($template_file)) { ++ $template_file = $hooks[$hook]['file'] . $extension; ++ if (isset($hooks[$hook]['path'])) { ++ $template_file = $hooks[$hook]['path'] .'/'. $template_file; ++ } ++ } ++ return $render_function($template_file, $variables); + } + } + + /** +- * Determine if a theme function exists, and if so return which one was found. +- * +- * @param $function +- * The name of the theme function to test. +- * @return +- * The name of the theme function that should be used, or FALSE if no function exists. ++ * Choose which template file to actually render; these are all ++ * suggested templates from the theme. + */ +-function theme_get_function($function) { +- global $theme, $theme_engine; ++function drupal_discover_template($suggestions, $extension = '.tpl.php') { ++ global $theme_engine; + +- // Because theme() is called a lot, calling init_theme() only to have it +- // smartly return is a noticeable performance hit. Don't do it. +- if (!isset($theme)) { +- init_theme(); +- } +- +- if (($theme != '') && function_exists($theme .'_'. $function)) { +- // call theme function +- return $theme .'_'. $function; +- } +- elseif (($theme != '') && isset($theme_engine) && function_exists($theme_engine .'_'. $function)) { +- // call engine function +- return $theme_engine .'_'. $function; +- } +- elseif (function_exists('theme_'. $function)){ +- // call Drupal function +- return 'theme_'. $function; ++ // Loop through any suggestions in FIFO order. ++ $suggestions = array_reverse($suggestions); ++ foreach ($suggestions as $suggestion) { ++ if (!empty($suggestion) && file_exists($file = path_to_theme() .'/'. $suggestion . $extension)) { ++ return $file; ++ } + } +- return FALSE; + } + + /** +@@ -348,16 +543,79 @@ function theme_get_setting($setting_name + } + + /** +- * @defgroup themeable Themeable functions ++ * Render a system default template, which is essentially a PHP template. ++ * ++ * @param $file ++ * The filename of the template to render. ++ * @param $variables ++ * A keyed array of variables that will appear in the output. ++ * ++ * @return ++ * The output generated by the template. ++ */ ++function theme_render_template($file, $variables) { ++ extract($variables, EXTR_SKIP); // Extract the variables to a local namespace ++ ob_start(); // Start output buffering ++ include "./$file"; // Include the file ++ $contents = ob_get_contents(); // Get the contents of the buffer ++ ob_end_clean(); // End buffering and discard ++ return $contents; // Return the contents ++} ++ ++/** ++ * @defgroup themeable Default theme implementations + * @{ +- * Functions that display HTML, and which can be customized by themes. ++ * Functions and templates that present output to the user, and can be ++ * implemented by themes. + * +- * All functions that produce HTML for display should be themeable. This means +- * that they should be named with the theme_ prefix, and invoked using theme() +- * rather than being called directly. This allows themes to override the display +- * of any Drupal object. ++ * Drupal's presentation layer is a pluggable system known as the theme ++ * layer. Each theme can take control over most of Drupal's output, and ++ * has complete control over the CSS. ++ * ++ * Inside Drupal, the theme layer is utilized by the use of the theme() ++ * function, which is passed the name of a component (the theme hook) ++ * and several arguments. For example, theme('table', $header, $rows); ++ * ++ * As of Drupal 6, every theme hook is required to be registered by the ++ * module that owns it, so that Drupal can tell what to do with it and ++ * to make it simple for themes to identify and override the behavior ++ * for these calls. ++ * ++ * The theme hooks are registered via hook_themes(), which returns an ++ * array of arrays with information about the hook. It describes the ++ * arguments the function or template will need, and provides ++ * defaults for the template in case they are not filled in. If the default ++ * implementation is a function, by convention it is named theme_HOOK(). ++ * ++ * Each module should provide a default implementation for themes that ++ * it registers. This implementation may be either a function or a template; ++ * if it is a function it must be specified via hook_themes(). By convention, ++ * default implementations of theme hooks are named theme_HOOK. Default ++ * template implementations are stored in the module directory. ++ * ++ * Drupal's default template renderer is a simple PHP parsing engine that ++ * includes the template and stores the output. Drupal's theme engines ++ * can provide alternate template engines, such as XTemplate, Smarty and ++ * PHPTal. The most common template engine is PHPTemplate (included with ++ * Drupal and implemented in phptemplate.engine, which uses Drupal's default ++ * template renderer. ++ * ++ * Themes can implement their own version of theme hooks, either as functions ++ * or files. If using a pure .theme without an engine, the .theme is required ++ * to implement its own version of hook_themes() to tell Drupal what it is ++ * implementing; themes utilizing an engine will have their well-named ++ * theming functions automatically registered for them. While this can vary ++ * based upon the theme engine, the standard set by phptemplate is that theme ++ * functions should be named either phptemplate_HOOK or THEMENAME_HOOK. For ++ * example, for Drupal's default theme (Garland) to implement the 'table' hook, ++ * the phptemplate.engine would find phptemplate_table() or garland_table(). ++ * The ENGINE_HOOK() syntax is preferred, as this can be used by sub-themes ++ * (which are themes that share code but use different stylesheets). + * + * The theme system is described and defined in theme.inc. ++ * ++ * @see theme() ++ * @see hook_themes() + */ + + /** +@@ -373,55 +631,6 @@ function theme_placeholder($text) { + return ''. check_plain($text) .''; + } + +-/** +- * Return an entire Drupal page displaying the supplied content. +- * +- * @param $content +- * A string to display in the main content area of the page. +- * @return +- * A string containing the entire HTML page. +- */ +-function theme_page($content) { +- // Get blocks before so that they can alter the header (JavaScript, Stylesheets etc.) +- $blocks = theme('blocks', 'all'); +- +- $output = "\n"; +- $output .= ''; +- $output .= ''; +- $output .= ' '. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'Drupal')) .''; +- $output .= drupal_get_html_head(); +- $output .= drupal_get_css(); +- $output .= drupal_get_js(); +- +- $output .= ' '; +- $output .= ' '; +- $output .= '
'; +- +- $output .= $blocks; +- $output .= ''; +- +- $output .= theme('breadcrumb', drupal_get_breadcrumb()); +- $output .= '

' . drupal_get_title() . '

'; +- +- if ($tabs = theme('menu_local_tasks')) { +- $output .= $tabs; +- } +- +- $output .= theme('help'); +- +- $output .= theme('status_messages'); +- +- $output .= "\n\n"; +- $output .= $content; +- $output .= drupal_get_feeds(); +- $output .= "\n\n"; +- +- $output .= '
'; +- $output .= theme('closure'); +- $output .= ''; +- +- return $output; +-} + + /** + * Generate a themed maintenance page. +@@ -458,9 +667,7 @@ function theme_maintenance_page($content + 'content' => $content, + ); + +- // Render simplified PHPTemplate. +- include_once './themes/engines/phptemplate/phptemplate.engine'; +- $output = _phptemplate_render('misc/maintenance.tpl.php', $variables); ++ $output = theme_render_template('misc/maintenance.tpl.php', $variables); + + return $output; + } +@@ -509,9 +716,7 @@ function theme_install_page($content) { + $variables['messages'] .= theme('status_messages', 'status'); + } + +- // Render simplified PHPTemplate. +- include_once './themes/engines/phptemplate/phptemplate.engine'; +- return _phptemplate_render('misc/maintenance.tpl.php', $variables); ++ return theme_render_template('misc/maintenance.tpl.php', $variables); + } + + /** +@@ -678,66 +883,6 @@ function theme_help() { + } + + /** +- * Return a themed node. +- * +- * @param $node +- * An object providing all relevant information for displaying a node: +- * - $node->nid: The ID of the node. +- * - $node->type: The content type (story, blog, forum...). +- * - $node->title: The title of the node. +- * - $node->created: The creation date, as a UNIX timestamp. +- * - $node->teaser: A shortened version of the node body. +- * - $node->body: The entire node contents. +- * - $node->changed: The last modification date, as a UNIX timestamp. +- * - $node->uid: The ID of the author. +- * - $node->username: The username of the author. +- * @param $teaser +- * Whether to display the teaser only, as on the main page. +- * @param $page +- * Whether to display the node as a standalone page. If TRUE, do not display +- * the title because it will be provided by the menu system. +- * @return +- * A string containing the node output. +- */ +-function theme_node($node, $teaser = FALSE, $page = FALSE) { +- if (!$node->status) { +- $output = '
'; +- } +- +- if (module_exists('taxonomy')) { +- $terms = taxonomy_link('taxonomy terms', $node); +- } +- +- if ($page == 0) { +- $output .= t('!title by !name', array('!title' => '

'. check_plain($node->title) .'

', '!name' => theme('username', $node))); +- } +- else { +- $output .= t('by !name', array('!name' => theme('username', $node))); +- } +- +- if (count($terms)) { +- $output .= ' ('. theme('links', $terms) .')
'; +- } +- +- if ($teaser && $node->teaser) { +- $output .= $node->teaser; +- } +- else { +- $output .= $node->body; +- } +- +- if ($node->links) { +- $output .= ''; +- } +- +- if (!$node->status) { +- $output .= '
'; +- } +- +- return $output; +-} +- +-/** + * Return a themed submenu, typically displayed under the tabs. + * + * @param $links +@@ -904,29 +1049,6 @@ function theme_box($title, $content, $re + } + + /** +- * Return a themed block. +- * +- * You can style your blocks by defining .block (all blocks), +- * .block-module (all blocks of module module), and +- * \#block-module-delta (specific block of module module +- * with delta delta) in your theme's CSS. +- * +- * @param $block +- * An object populated with fields from the "blocks" database table +- * ($block->module, $block->delta ...) and fields returned by +- * module_block('view') ($block->subject, $block->content, ...). +- * @return +- * A string containing the block output. +- */ +-function theme_block($block) { +- $output = "
module\" id=\"block-$block->module-$block->delta\">\n"; +- $output .= "

$block->subject

\n"; +- $output .= "
$block->content
\n"; +- $output .= "
\n"; +- return $output; +-} +- +-/** + * Return a themed marker, useful for marking new or updated + * content. + * +diff -urNp ../drupal-themeswo/index.php ./index.php +--- ../drupal-themeswo/index.php 2007-02-11 01:30:50.000000000 -0800 ++++ ./index.php 2007-03-31 12:13:22.000000000 -0700 +@@ -31,7 +31,6 @@ if (is_int($return)) { + elseif (isset($return)) { + // Print any value (including an empty string) except NULL or undefined: + print theme('page', $return); +- + } + + drupal_page_footer(); +diff -urNp ../drupal-themeswo/modules/aggregator/aggregator.module ./modules/aggregator/aggregator.module +--- ../drupal-themeswo/modules/aggregator/aggregator.module 2007-03-26 22:13:53.000000000 -0700 ++++ ./modules/aggregator/aggregator.module 2007-03-31 12:13:22.000000000 -0700 +@@ -26,6 +26,34 @@ function aggregator_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function aggregator_themes() { ++ return array( ++ 'aggregator_page_list' => array( ++ 'function' => 'theme_aggregator_page_list', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'aggregator_feed' => array( ++ 'function' => 'theme_aggregator_feed', ++ 'arguments' => array('feed' => NULL), ++ ), ++ 'aggregator_block_item' => array( ++ 'function' => 'theme_aggregator_block_item', ++ 'arguments' => array('item' => NULL, 'feed' => 0), ++ ), ++ 'aggregator_summary_item' => array( ++ 'function' => 'theme_aggregator_summary_item', ++ 'arguments' => array('item' => NULL), ++ ), ++ 'aggregator_page_item' => array( ++ 'function' => 'theme_aggregator_page_item', ++ 'arguments' => array('item' => NULL), ++ ), ++ ++ ); ++ ++/** + * Implementation of hook_menu(). + */ + function aggregator_menu() { +diff -urNp ../drupal-themeswo/modules/block/block.module ./modules/block/block.module +--- ../drupal-themeswo/modules/block/block.module 2007-03-26 22:13:53.000000000 -0700 ++++ ./modules/block/block.module 2007-03-31 12:13:22.000000000 -0700 +@@ -49,6 +49,18 @@ function block_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function block_themes() { ++ return array( ++ 'block_admin_display' => array( ++ 'function' => 'theme_block_admin_display', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function block_perm() { +diff -urNp ../drupal-themeswo/modules/book/book.module ./modules/book/book.module +--- ../drupal-themeswo/modules/book/book.module 2007-03-26 22:13:53.000000000 -0700 ++++ ./modules/book/book.module 2007-03-31 12:13:22.000000000 -0700 +@@ -20,6 +20,26 @@ function book_node_info() { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function book_themes() { ++ return array( ++ 'book_navigation' => array( ++ 'function' => 'theme_book_navigation', ++ 'arguments' => array('node' => NULL), ++ ), ++ 'book_export_html' => array( ++ 'function' => 'theme_book_export_html', ++ 'arguments' => array('title' => NULL, 'content' => NULL), ++ ), ++ 'book_admin_table' => array( ++ 'function' => 'theme_book_admin_table', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function book_perm() { +diff -urNp ../drupal-themeswo/modules/color/color.module ./modules/color/color.module +--- ../drupal-themeswo/modules/color/color.module 2007-03-26 22:13:53.000000000 -0700 ++++ ./modules/color/color.module 2007-03-31 12:13:22.000000000 -0700 +@@ -2,6 +2,17 @@ + // $Id: color.module,v 1.17 2007/03/27 05:13:53 unconed Exp $ + + /** ++ * Implementation of hook_themes() ++ */ ++function color_themes() { ++ return array( ++ 'color_scheme_form' => array( ++ 'function' => 'theme_color_scheme_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++/** + * Implementation of hook_form_alter(). + */ + function color_form_alter(&$form, $form_id) { +diff -urNp ../drupal-themeswo/modules/comment/comment.module ./modules/comment/comment.module +--- ../drupal-themeswo/modules/comment/comment.module 2007-03-30 00:45:19.000000000 -0700 ++++ ./modules/comment/comment.module 2007-03-31 12:13:22.000000000 -0700 +@@ -140,6 +140,66 @@ function comment_help($section) { + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function comment_themes() { ++ return array( ++ 'comment_block' => array( ++ 'function' => 'theme_comment_block', ++ 'arguments' => array(), ++ ), ++ 'comment_admin_overview' => array( ++ 'function' => 'theme_comment_admin_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'comment_preview' => array( ++ 'function' => 'theme_comment_preview', ++ 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), ++ ), ++ 'comment_view' => array( ++ 'function' => 'theme_comment_view', ++ 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), ++ ), ++ 'comment_controls' => array( ++ 'function' => 'theme_comment_controls', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'comment' => array( ++ 'function' => 'theme_comment', ++ 'arguments' => array('comment' => NULL, 'links' => array()), ++ ), ++ 'comment_folded' => array( ++ 'function' => 'theme_comment_folded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_flat_collapsed' => array( ++ 'function' => 'theme_comment_flat_collapsed', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_flat_expanded' => array( ++ 'function' => 'theme_comment_flat_expanded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_thread_collapsed' => array( ++ 'function' => 'theme_comment_thread_collapsed', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_thread_expanded' => array( ++ 'function' => 'theme_comment_thread_expanded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_post_forbidden' => array( ++ 'function' => 'theme_comment_post_forbidden', ++ 'arguments' => array('nid' => NULL), ++ ), ++ 'comment_wrapper' => array( ++ 'function' => 'theme_comment_wrapper', ++ 'arguments' => array('content' => NULL), ++ ), ++ ); ++} ++ + function _comment_view_access($node, $cid) { + return $node && $cid; + } +diff -urNp ../drupal-themeswo/modules/drupal/drupal.module ./modules/drupal/drupal.module +--- ../drupal-themeswo/modules/drupal/drupal.module 2007-02-27 04:29:22.000000000 -0800 ++++ ./modules/drupal/drupal.module 2007-03-31 12:13:22.000000000 -0700 +@@ -46,6 +46,18 @@ print drupal_client_page(); + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function drupal_themes() { ++ return array( ++ 'client_list' => array( ++ 'function' => 'theme_client_list', ++ 'arguments' => array('clients' => NULL), ++ ), ++ ); ++} ++ + function drupal_sites_registry_settings() { + // Check if all required fields are present + if ((variable_get('site_name', 'Drupal') == 'Drupal') || (variable_get('site_name', 'Drupal') == '')) { +diff -urNp ../drupal-themeswo/modules/filter/filter.module ./modules/filter/filter.module +--- ../drupal-themeswo/modules/filter/filter.module 2007-03-12 04:31:02.000000000 -0700 ++++ ./modules/filter/filter.module 2007-03-31 12:13:22.000000000 -0700 +@@ -48,6 +48,30 @@ function filter_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function filter_themes() { ++ return array( ++ 'filter_admin_overview' => array( ++ 'function' => 'theme_filter_admin_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'filter_admin_order' => array( ++ 'function' => 'theme_filter_admin_order', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'filter_tips' => array( ++ 'function' => 'theme_filter_tips', ++ 'arguments' => array('tips' => NULL, 'long' => FALSE, 'extra' => ''), ++ ), ++ 'filter_tips_more_info' => array( ++ 'function' => 'theme_filter_tips_more_info', ++ 'arguments' => array(), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function filter_menu() { +diff -urNp ../drupal-themeswo/modules/forum/forum.module ./modules/forum/forum.module +--- ../drupal-themeswo/modules/forum/forum.module 2007-03-28 07:08:22.000000000 -0700 ++++ ./modules/forum/forum.module 2007-03-31 12:13:22.000000000 -0700 +@@ -29,6 +29,34 @@ function forum_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function forum_themes() { ++ return array( ++ 'forum_display' => array( ++ 'function' => 'theme_forum_display', ++ 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), ++ ), ++ 'forum_list' => array( ++ 'function' => 'theme_forum_list', ++ 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), ++ ), ++ 'forum_topic_list' => array( ++ 'function' => 'theme_forum_topic_list', ++ 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), ++ ), ++ 'forum_icon' => array( ++ 'function' => 'theme_forum_icon', ++ 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), ++ ), ++ 'forum_topic_navigation' => array( ++ 'function' => 'theme_forum_topic_navigation', ++ 'arguments' => array('node' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function forum_menu() { +diff -urNp ../drupal-themeswo/modules/node/node.module ./modules/node/node.module +--- ../drupal-themeswo/modules/node/node.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/node/node.module 2007-03-31 12:13:22.000000000 -0700 +@@ -46,6 +46,46 @@ function node_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function node_themes() { ++ return array( ++ 'node_list' => array( ++ 'function' => 'theme_node_list', ++ 'arguments' => array('items' => NULL, 'title' => NULL), ++ ), ++ 'node_search_admin' => array( ++ 'function' => 'theme_node_search_admin', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_filter_form' => array( ++ 'function' => 'theme_node_filter_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_filters' => array( ++ 'function' => 'theme_node_filters', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_admin_nodes' => array( ++ 'function' => 'theme_node_admin_nodes', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_form' => array( ++ 'function' => 'theme_node_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_preview' => array( ++ 'function' => 'theme_node_preview', ++ 'arguments' => array('node' => NULL), ++ ), ++ 'node_log_message' => array( ++ 'function' => 'theme_node_log_message', ++ 'arguments' => array('log' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_cron(). + */ + function node_cron() { +@@ -2350,7 +2390,6 @@ function node_revisions() { + * Menu callback; Generate a listing of promoted nodes. + */ + 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)); + + if (db_num_rows($result)) { +diff -urNp ../drupal-themeswo/modules/poll/poll.module ./modules/poll/poll.module +--- ../drupal-themeswo/modules/poll/poll.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/poll/poll.module 2007-03-31 12:13:22.000000000 -0700 +@@ -21,6 +21,26 @@ function poll_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function poll_themes() { ++ return array( ++ 'poll_view_voting' => array( ++ 'function' => 'theme_poll_view_voting', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'poll_results' => array( ++ 'function' => 'theme_poll_results', ++ 'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL, 'links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL), ++ ), ++ 'poll_bar' => array( ++ 'function' => 'theme_poll_bar', ++ 'arguments' => array('title' => NULL, 'percentage' => NULL, 'votes' => NULL, 'block' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_access(). + */ + function poll_access($op, $node) { +diff -urNp ../drupal-themeswo/modules/profile/profile.module ./modules/profile/profile.module +--- ../drupal-themeswo/modules/profile/profile.module 2007-03-30 02:38:13.000000000 -0700 ++++ ./modules/profile/profile.module 2007-03-31 12:13:22.000000000 -0700 +@@ -52,6 +52,21 @@ function profile_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function profile_themes() { ++ return array( ++ 'profile_block' => array( ++ 'function' => 'theme_profile_block', ++ 'arguments' => array('account' => NULL, 'fields' => array()), ++ ), ++ 'profile_listing' => array( ++ 'function' => 'theme_profile_listing', ++ 'arguments' => array('account' => NULL, 'fields' => array()), ++ ), ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function profile_menu() { +diff -urNp ../drupal-themeswo/modules/search/search.module ./modules/search/search.module +--- ../drupal-themeswo/modules/search/search.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/search/search.module 2007-03-31 12:13:22.000000000 -0700 +@@ -112,6 +112,30 @@ function search_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function search_themes() { ++ return array( ++ 'search_theme_form' => array( ++ 'function' => 'theme_search_theme_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'search_block_form' => array( ++ 'function' => 'theme_search_block_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'search_item' => array( ++ 'function' => 'theme_search_item', ++ 'arguments' => array('item' => NULL, 'type' => NULL), ++ ), ++ 'search_page' => array( ++ 'function' => 'theme_search_page', ++ 'arguments' => array('results' => NULL, 'type' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function search_perm() { +diff -urNp ../drupal-themeswo/modules/system/system.module ./modules/system/system.module +--- ../drupal-themeswo/modules/system/system.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/system/system.module 2007-03-31 12:13:22.000000000 -0700 +@@ -48,6 +48,46 @@ function system_help($section) { + } + } + ++function system_themes() { ++ return array_merge(drupal_common_themes(), array( ++ 'system_theme_select_form' => array( ++ 'function' => 'theme_system_theme_select_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_themes_form' => array( ++ 'function' => 'theme_system_themes_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_modules' => array( ++ 'function' => 'theme_system_modules', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_modules_uninstall' => array( ++ 'function' => 'theme_system_modules_uninstall', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'status_report' => array( ++ 'function' => 'theme_status_report', ++ 'arguments' => array('requirements' => NULL), ++ ), ++ 'admin_page' => array( ++ 'function' => 'theme_admin_page', ++ 'arguments' => array('blocks' => NULL), ++ ), ++ 'admin_block' => array( ++ 'function' => 'theme_admin_block', ++ 'arguments' => array('block' => NULL), ++ ), ++ 'admin_block_content' => array( ++ 'function' => 'theme_admin_block_content', ++ 'arguments' => array('content' => NULL), ++ ), ++ 'system_admin_by_module' => array( ++ 'function' => 'theme_system_admin_by_module', ++ 'arguments' => array('menu_items' => NULL), ++ ), ++ )); ++} + /** + * Implementation of hook_perm(). + */ +@@ -150,7 +190,7 @@ function system_menu() { + 'title' => t('Themes'), + 'description' => t('Change which theme your site uses or allows users to set.'), + 'page callback' => 'drupal_get_form', +- 'page arguments' => array('system_themes'), ++ 'page arguments' => array('system_themes_form'), + ); + $items['admin/build/themes/select'] = array( + 'title' => t('List'), +@@ -1143,7 +1183,7 @@ function system_settings_form_submit($fo + /** + * Menu callback; displays a listing of all themes. + */ +-function system_themes() { ++function system_themes_form() { + + drupal_clear_css_cache(); + $themes = system_theme_data(); +@@ -1177,7 +1217,7 @@ function system_themes() { + return $form; + } + +-function theme_system_themes($form) { ++function theme_system_themes_form($form) { + foreach (element_children($form) as $key) { + $row = array(); + if (isset($form[$key]['description']) && is_array($form[$key]['description'])) { +@@ -1199,7 +1239,7 @@ function theme_system_themes($form) { + } + + +-function system_themes_submit($form_id, $form_values) { ++function system_themes_form_submit($form_id, $form_values) { + + db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'"); + +diff -urNp ../drupal-themeswo/modules/taxonomy/taxonomy.module ./modules/taxonomy/taxonomy.module +--- ../drupal-themeswo/modules/taxonomy/taxonomy.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/taxonomy/taxonomy.module 2007-03-31 12:13:22.000000000 -0700 +@@ -14,6 +14,18 @@ function taxonomy_perm() { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function taxonomy_themes() { ++ return array( ++ 'taxonomy_term_select' => array( ++ 'function' => 'theme_taxonomy_term_select', ++ 'arguments' => array('element' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_link(). + * + * This hook is extended with $type = 'taxonomy terms' to allow themes to +diff -urNp ../drupal-themeswo/modules/upload/upload.module ./modules/upload/upload.module +--- ../drupal-themeswo/modules/upload/upload.module 2007-03-26 22:13:54.000000000 -0700 ++++ ./modules/upload/upload.module 2007-03-31 12:13:22.000000000 -0700 +@@ -23,6 +23,26 @@ function upload_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function upload_themes() { ++ return array( ++ 'upload_attachments' => array( ++ 'function' => 'theme_upload_attachments', ++ 'arguments' => array('files' => NULL), ++ ), ++ 'upload_form_current' => array( ++ 'function' => 'theme_upload_form_current', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'upload_form_new' => array( ++ 'function' => 'theme_upload_form_new', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function upload_perm() { +diff -urNp ../drupal-themeswo/modules/user/user.module ./modules/user/user.module +--- ../drupal-themeswo/modules/user/user.module 2007-03-30 00:45:19.000000000 -0700 ++++ ./modules/user/user.module 2007-03-31 12:13:22.000000000 -0700 +@@ -24,6 +24,46 @@ function user_module_invoke($type, &$arr + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function user_themes() { ++ return array( ++ 'user_picture' => array( ++ 'function' => 'theme_user_picture', ++ 'arguments' => array('account' => NULL), ++ ), ++ 'user_profile' => array( ++ 'function' => 'theme_user_profile', ++ 'arguments' => array('account' => NULL, 'fields' => NULL), ++ ), ++ 'user_list' => array( ++ 'function' => 'theme_user_list', ++ 'arguments' => array('users' => NULL, 'title' => NULL), ++ ), ++ 'user_admin_perm' => array( ++ 'function' => 'theme_user_admin_perm', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_admin_new_role' => array( ++ 'function' => 'theme_user_admin_new_role', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_admin_account' => array( ++ 'function' => 'theme_user_admin_account', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_filter_form' => array( ++ 'function' => 'theme_user_filter_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_filters' => array( ++ 'function' => 'theme_user_filters', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ + function user_external_load($authname) { + $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname); + +diff -urNp ../drupal-themeswo/modules/watchdog/watchdog.module ./modules/watchdog/watchdog.module +--- ../drupal-themeswo/modules/watchdog/watchdog.module 2007-02-27 04:29:22.000000000 -0800 ++++ ./modules/watchdog/watchdog.module 2007-03-31 12:13:22.000000000 -0700 +@@ -28,6 +28,18 @@ function watchdog_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function watchdog_themes() { ++ return array( ++ 'watchdog_form_overview' => array( ++ 'function' => 'theme_watchdog_form_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function watchdog_menu() { +diff -urNp ../drupal-themeswo/sites/default/settings.php ./sites/default/settings.php +--- ../drupal-themeswo/sites/default/settings.php 2007-03-31 12:17:51.000000000 -0700 ++++ ./sites/default/settings.php 2007-03-31 12:17:03.000000000 -0700 +@@ -91,7 +91,7 @@ + * $db_url = 'pgsql://username:password@localhost/databasename'; + */ + $db_url = 'mysql://root:root@localhost/drupals'; +-$db_prefix = 'two'; ++$db_prefix = 'tw'; + + /** + * Base URL (optional). diff -urNp ../drupal-themeswo/theme_reg_6.patch ./theme_reg_6.patch --- ../drupal-themeswo/theme_reg_6.patch 1969-12-31 16:00:00.000000000 -0800 +++ ./theme_reg_6.patch 2007-03-31 12:13:04.000000000 -0700 @@ -0,0 +1,2232 @@ +? DrupalHead.kpf +? files +? node_page_default_1.patch +? node_url.patch +? page_context.patch +? reg2.patch +? registry.patch +? registry_0.patch +? test.php +? theme_reg.patch +? themefuncs.txt +? includes/query.inc +? sites/logrus.com +? sites/all/modules +Index: index.php +=================================================================== +RCS file: /cvs/drupal/drupal/index.php,v +retrieving revision 1.92 +diff -u -p -r1.92 index.php +--- index.php 11 Feb 2007 09:30:50 -0000 1.92 ++++ index.php 30 Mar 2007 22:30:35 -0000 +@@ -31,7 +31,6 @@ if (is_int($return)) { + elseif (isset($return)) { + // Print any value (including an empty string) except NULL or undefined: + print theme('page', $return); +- + } + + drupal_page_footer(); +Index: includes/bootstrap.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v +retrieving revision 1.151 +diff -u -p -r1.151 bootstrap.inc +--- includes/bootstrap.inc 28 Mar 2007 14:08:21 -0000 1.151 ++++ includes/bootstrap.inc 30 Mar 2007 22:30:36 -0000 +@@ -922,6 +922,9 @@ function drupal_maintenance_theme() { + drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module'); + drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module'); + $theme = ''; ++ ++ // Special case registry of theme functions used by the installer ++ _theme_set_registry(drupal_common_themes()); + } + + /** +Index: includes/common.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/common.inc,v +retrieving revision 1.625 +diff -u -p -r1.625 common.inc +--- includes/common.inc 29 Mar 2007 23:17:15 -0000 1.625 ++++ includes/common.inc 30 Mar 2007 22:30:38 -0000 +@@ -2311,3 +2311,254 @@ function int2vancode($i = 0) { + $length = strlen($num); + return chr($length + ord('0') - 1) . $num; + } ++ ++/** ++ * Provide theme registration for themes across .inc files. ++ */ ++function drupal_common_themes() { ++ return array( ++ // theme.inc ++ 'placeholder' => array( ++ 'function' => 'theme_placeholder', ++ 'arguments' => array('text' => NULL) ++ ), ++ 'page' => array( ++ 'function' => 'theme_page', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('content' => NULL, 'show_blocks' => TRUE), ++ ), ++ 'maintenance_page' => array( ++ 'function' => 'theme_maintenance_page', ++ 'arguments' => array('content' => NULL, 'messages' => TRUE), ++ ), ++ 'install_page' => array( ++ 'function' => 'theme_install_page', ++ 'arguments' => array('content' => NULL), ++ ), ++ 'task_list' => array( ++ 'function' => 'theme_task_list', ++ 'arguments' => array('items' => NULL, 'active' => NULL), ++ ), ++ 'status_messages' => array( ++ 'function' => 'theme_status_messages', ++ 'arguments' => array('display' => NULL), ++ ), ++ 'links' => array( ++ 'function' => 'theme_links', ++ 'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')), ++ ), ++ 'image' => array( ++ 'function' => 'theme_image', ++ 'arguments' => array('path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE), ++ ), ++ 'breadcrumb' => array( ++ 'function' => 'theme_breadcrumb', ++ 'arguments' => array('breadcrumb' => NULL), ++ ), ++ 'help' => array( ++ 'function' => 'theme_help', ++ 'arguments' => array(), ++ ), ++ 'node' => array( ++ 'function' => 'theme_node', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE), ++ ), ++ 'submenu' => array( ++ 'function' => 'theme_submenu', ++ 'arguments' => array('links' => NULL), ++ ), ++ 'table' => array( ++ 'function' => 'theme_table', ++ 'arguments' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL), ++ ), ++ 'table_select_header_cell' => array( ++ 'function' => 'theme_table_select_header_cell', ++ 'arguments' => array(), ++ ), ++ 'tablesort_indicator' => array( ++ 'function' => 'theme_tablesort_indicator', ++ 'arguments' => array('style' => NULL), ++ ), ++ 'box' => array( ++ 'function' => 'theme_box', ++ 'arguments' => array('title' => NULL, 'content' => NULL, 'region' => 'main'), ++ ), ++ 'block' => array( ++ 'function' => 'theme_block', ++ 'file' => 'theme.base.inc', ++ 'path' => 'includes', ++ 'arguments' => array('block' => NULL), ++ ), ++ 'mark' => array( ++ 'function' => 'theme_mark', ++ 'arguments' => array('type' => MARK_NEW), ++ ), ++ 'item_list' => array( ++ 'function' => 'theme_item_list', ++ 'arguments' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => NULL), ++ ), ++ 'more_help_link' => array( ++ 'function' => 'theme_more_help_link', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'xml_icon' => array( ++ 'function' => 'theme_xml_icon', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'feed_icon' => array( ++ 'function' => 'theme_feed_icon', ++ 'arguments' => array('url' => NULL), ++ ), ++ 'closure' => array( ++ 'function' => 'theme_closure', ++ 'arguments' => array('main' => 0), ++ ), ++ 'blocks' => array( ++ 'function' => 'theme_blocks', ++ 'arguments' => array('region' => NULL), ++ ), ++ 'username' => array( ++ 'function' => 'theme_username', ++ 'arguments' => array('object' => NULL), ++ ), ++ 'progress_bar' => array( ++ 'function' => 'theme_progress_bar', ++ 'arguments' => array('percent' => NULL, 'message' => NULL), ++ ), ++ // from pager.inc ++ 'pager' => array( ++ 'function' => 'theme_pager', ++ 'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_first' => array( ++ 'function' => 'theme_pager_first', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_previous' => array( ++ 'function' => 'theme_pager_previous', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), ++ ), ++ 'pager_next' => array( ++ 'function' => 'theme_pager_next', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()), ++ ), ++ 'pager_last' => array( ++ 'function' => 'theme_pager_last', ++ 'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()), ++ ), ++ 'pager_list' => array( ++ 'function' => 'theme_pager_list', ++ 'arguments' => array('limit' => NULL, 'element' => 0, 'quantity' => 5, 'text' => '', 'parameters' => array()), ++ ), ++ 'pager_link' => array( ++ 'function' => 'theme_pager_link', ++ 'arguments' => array('text' => NULL, 'page_new' => NULL, 'element' => NULL, 'parameters' => array(), 'attributes' => array()), ++ ), ++ // from locale.inc ++ 'locale_admin_manage_screen' => array( ++ 'function' => 'theme_locale_admin_manage_screen', ++ 'arguments' => array('form' => NULL), ++ ), ++ // from menu.inc ++ 'menu_item_link' => array( ++ 'function' => 'theme_menu_item_link', ++ 'arguments' => array('item' => NULL), ++ ), ++ 'menu_tree' => array( ++ 'function' => 'theme_menu_tree', ++ 'arguments' => array('tree' => NULL), ++ ), ++ 'menu_item' => array( ++ 'function' => 'theme_menu_item', ++ 'arguments' => array('link' => NULL, 'has_children' => NULL, 'menu' => ''), ++ ), ++ 'menu_local_task' => array( ++ 'function' => 'theme_menu_local_task', ++ 'arguments' => array('link' => NULL, 'active' => FALSE), ++ ), ++ // from form.inc ++ 'select' => array( ++ 'function' => 'theme_select', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'fieldset' => array( ++ 'function' => 'theme_fieldset', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'radio' => array( ++ 'function' => 'theme_radio', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'radios' => array( ++ 'function' => 'theme_radios', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'password_confirm' => array( ++ 'function' => 'theme_password_confirm', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'date' => array( ++ 'function' => 'theme_date', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'item' => array( ++ 'function' => 'theme_item', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'checkbox' => array( ++ 'function' => 'theme_checkbox', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'checkboxes' => array( ++ 'function' => 'theme_checkboxes', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'submit' => array( ++ 'function' => 'theme_submit', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'button' => array( ++ 'function' => 'theme_button', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'hidden' => array( ++ 'function' => 'theme_hidden', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'token' => array( ++ 'function' => 'theme_token', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'textfield' => array( ++ 'function' => 'theme_textfield', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'form' => array( ++ 'function' => 'theme_form', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'textarea' => array( ++ 'function' => 'theme_textarea', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'markup' => array( ++ 'function' => 'theme_markup', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'password' => array( ++ 'function' => 'theme_password', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'file' => array( ++ 'function' => 'theme_file', ++ 'arguments' => array('element' => NULL), ++ ), ++ 'form_element' => array( ++ 'function' => 'theme_form_element', ++ 'arguments' => array('element' => NULL, 'value' => NULL), ++ ), ++ ); ++} +Index: includes/form.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/form.inc,v +retrieving revision 1.185 +diff -u -p -r1.185 form.inc +--- includes/form.inc 27 Mar 2007 05:13:53 -0000 1.185 ++++ includes/form.inc 30 Mar 2007 22:30:39 -0000 +@@ -457,7 +457,9 @@ function drupal_render_form($form_id, &$ + // Don't override #theme if someone already set it. + + if (!isset($form['#theme'])) { +- if (theme_get_function($form_id)) { ++ init_theme(); ++ $registry = theme_get_registry(); ++ if (isset($registry[$form_id])) { + $form['#theme'] = $form_id; + } + } +Index: includes/theme.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/theme.inc,v +retrieving revision 1.344 +diff -u -p -r1.344 theme.inc +--- includes/theme.inc 27 Mar 2007 05:13:53 -0000 1.344 ++++ includes/theme.inc 30 Mar 2007 22:30:41 -0000 +@@ -72,6 +72,7 @@ function init_theme() { + if (strpos($themes[$theme]->filename, '.theme')) { + // file is a theme; include it + include_once './' . $themes[$theme]->filename; ++ _theme_load_registry($theme); + } + elseif (strpos($themes[$theme]->description, '.engine')) { + // file is a template; include its engine +@@ -80,10 +81,104 @@ function init_theme() { + if (function_exists($theme_engine .'_init')) { + call_user_func($theme_engine .'_init', $themes[$theme]); + } ++ _theme_load_registry($theme, $theme_engine); + } + } + + /** ++ * Retrieve the stored theme registry. If the theme registry is already ++ * in memory it will be returned; otherwise it will attempt to load the ++ * registry from cache. If this fails, it will construct the registry and ++ * cache it. ++ */ ++function theme_get_registry($registry = NULL) { ++ static $theme_registry = NULL; ++ if (isset($registry)) { ++ $theme_registry = $registry; ++ } ++ ++ return $theme_registry; ++} ++ ++/** ++ * Store the theme registry in memory. ++ */ ++function _theme_set_registry($registry) { ++ // Pass through for setting of static variable. ++ return theme_get_registry($registry); ++} ++ ++/** ++ * Get the theme_registry cache from the database; if it doesn't exist, build ++ * it. ++ */ ++function _theme_load_registry($theme, $theme_engine = NULL) { ++ // TODO: use a separate cache for this. ++ $cache = cache_get("theme_registry:$theme", 'cache'); ++ if (isset($cache->data)) { ++ $registry = unserialize($cache->data); ++ } ++ else { ++ $registry = _theme_build_registry($theme, $theme_engine); ++ _theme_save_registry($theme, $registry); ++ } ++ _theme_set_registry($registry); ++} ++ ++/** ++ * Write the theme_registry cache into the database. ++ */ ++function _theme_save_registry($theme, $registry) { ++ // TODO: use a separate cache for this. ++ cache_set("theme_registry:$theme", 'cache', serialize($registry)); ++} ++ ++/** ++ * Process a single invocation of the themes hook. ++ */ ++function _theme_process_registry(&$cache, $name, $type) { ++ $function = $name .'_themes'; ++ if (function_exists($function)) { ++ $result = $function($cache); ++ ++ // Automatically find paths ++ $path = drupal_get_path($type, $name); ++ foreach ($result as $hook => $info) { ++ $result[$hook]['type'] = $type; ++ if (isset($info['file']) && !isset($info['path'])) { ++ $result[$hook]['file'] = $path .'/'. $info['file']; ++ } ++ // If 'arguments' have been defined previously, carry them forward. ++ // This should happen if a theme overrides a Drupal defined theme ++ // function, for example. ++ if (!isset($info['arguments']) && isset($cache[$hook])) { ++ $result[$hook]['arguments'] = $cache[$hook]['arguments']; ++ } ++ } ++ ++ $cache = array_merge($cache, $result); ++ } ++} ++ ++/** ++ * Rebuild the hook theme_registry cache. ++ */ ++function _theme_build_registry($theme, $theme_engine) { ++ $cache = array(); ++ foreach (module_implements('themes') as $module) { ++ _theme_process_registry($cache, $module, 'module'); ++ } ++ ++ if ($theme_engine) { ++ _theme_process_registry($cache, $theme_engine, 'theme_engine'); ++ } ++ ++ _theme_process_registry($cache, $theme, 'theme'); ++ ++ return $cache; ++} ++ ++/** + * Provides a list of currently available themes. + * + * @param $refresh +@@ -140,18 +235,41 @@ function list_theme_engines($refresh = F + } + + /** +- * Generate the themed representation of a Drupal object. +- * +- * All requests for themed functions must go through this function. It examines +- * the request and routes it to the appropriate theme function. If the current +- * theme does not implement the requested function, then the current theme +- * engine is checked. If neither the engine nor theme implement the requested +- * function, then the base theme function is called. ++ * Generate the themed output. + * +- * For example, to retrieve the HTML that is output by theme_page($output), a +- * module should call theme('page', $output). ++ * All requests for theme hooks must go through this function. It examines ++ * the request and routes it to the appropriate theme function. The theme ++ * registry is checked to determine which implementation to use, which may ++ * be a function or a template. ++ * ++ * If the implementation is a function, it is executed and its return value ++ * passed along. ++ * ++ * If the implementation is a template, the arguments are converted to a ++ * $variables array. This array is then modified by the theme engine (if ++ * applicable) and the theme. The following functions may be used to modify ++ * the $variables array: ++ * ++ * ENGINE_engine_variables(&$variables) ++ * This function should only be implemented by theme engines and is exists ++ * so that the theme engine can set necessary variables. It is commonly ++ * used to set global variables such as $directory and $is_front_page. ++ * ENGINE_engine_variables_HOOK(&$variables) ++ * This is the same as the previous function, but is called only per hook. ++ * ENGINE_variables_HOOK(&$variables) ++ * ENGINE_variables(&$variables) ++ * This is meant to be used by themes that utilize a theme engine; as it is ++ * good practice for these themes to use the theme engine's name for ++ * their functions so that they may share code. In PHPTemplate, these ++ * functions will appear in template.php ++ * THEME_variables_HOOK(&$variables) ++ * THEME_variables(&$variables) ++ * These functions are based upon the raw theme; they should primarily be ++ * used by themes that do not use an engine or by themes that need small ++ * changes to what has already been established in the theme engine version ++ * of the function. + * +- * @param $function ++ * @param $hook + * The name of the theme function to call. + * @param ... + * Additional arguments to pass along to the theme function. +@@ -159,48 +277,125 @@ function list_theme_engines($refresh = F + * An HTML string that generates the themed output. + */ + function theme() { +- static $functions; + $args = func_get_args(); +- $function = array_shift($args); ++ $hook = array_shift($args); + +- if (!isset($functions[$function])) { +- $functions[$function] = theme_get_function($function); ++ static $hooks = NULL; ++ if (!isset($hooks)) { ++ init_theme(); ++ $hooks = theme_get_registry(); ++ } ++ ++ if (!isset($hooks[$hook])) { ++ return; + } +- if ($functions[$function]) { +- return call_user_func_array($functions[$function], $args); ++ ++ $info = $hooks[$hook]; ++ ++ if (isset($info['function'])) { ++ // The theme call is a function. ++ // Include a file if this theme function is held elsewhere. ++ if (!empty($info['file'])) { ++ include_once($info['file']); ++ } ++ return call_user_func_array($info['function'], $args); ++ } ++ else { ++ // The theme call is a template. ++ $variables = array( ++ 'template_files' => array() ++ ); ++ if (!empty($info['arguments'])) { ++ $count = 0; ++ foreach ($info['arguments'] as $name => $default) { ++ $variables[$name] = isset($args[$count]) ? $args[$count] : $default; ++ $count++; ++ } ++ } ++ ++ // default render function and extension. ++ $render_function = 'theme_render_template'; ++ $extension = '.tpl.php'; ++ $variables_list = array(); ++ ++ // Run through the theme engine variables, if necessary ++ global $theme_engine; ++ if (isset($theme_engine)) { ++ // Call each of our variable override functions. We allow ++ // several to create cleaner code. ++ $variables_list[] = $theme_engine .'_engine_variables'; ++ $variables_list[] = $theme_engine .'_engine_variables_'. $hook; ++ $variables_list[] = $theme_engine .'_variables'; ++ $variables_list[] = $theme_engine .'_variables_'. $hook; ++ ++ // If theme or theme engine is implementing this, it may have ++ // a different extension and a different renderer. ++ if ($hooks[$hook]['type'] != 'module') { ++ if (function_exists($theme_engine .'_render_template')) { ++ $render_function = $theme_engine .'_render_template'; ++ } ++ $extension_function = $theme_engine .'_extension'; ++ if (function_exists($extension_function)) { ++ $extension = $extension_function(); ++ } ++ } ++ } ++ ++ // Add theme specific variable substitution: ++ global $theme; ++ $variables_list[] = $theme .'_variables'; ++ $variables_list[] = $theme .'_variables_'. $hook; ++ ++ // This construct ensures that we can keep a reference through ++ // call_user_func_array. ++ $args = array(&$variables, $hook); ++ foreach ($variables_list as $variables_function) { ++ if (function_exists($variables_function)) { ++ call_user_func_array($variables_function, $args); ++ } ++ } ++ ++ // Get suggestions for alternate templates out of the variables ++ // that were set. This lets us dynamically choose a template ++ // from a list. The order is FILO, so this array is ordered from ++ // least appropriate first to most appropriate last. ++ $suggestions = array(); ++ ++ if (isset($variables['template_files'])) { ++ $suggestions = $variables['template_files']; ++ } ++ if (isset($variables['template_file'])) { ++ $suggestions[] = $variables['template_file']; ++ } ++ ++ if ($suggestions) { ++ $template_file = drupal_discover_template($suggestions, $extension); ++ } ++ ++ if (empty($template_file)) { ++ $template_file = $hooks[$hook]['file'] . $extension; ++ if (isset($hooks[$hook]['path'])) { ++ $template_file = $hooks[$hook]['path'] .'/'. $template_file; ++ } ++ } ++ return $render_function($template_file, $variables); + } + } + + /** +- * Determine if a theme function exists, and if so return which one was found. +- * +- * @param $function +- * The name of the theme function to test. +- * @return +- * The name of the theme function that should be used, or FALSE if no function exists. ++ * Choose which template file to actually render; these are all ++ * suggested templates from the theme. + */ +-function theme_get_function($function) { +- global $theme, $theme_engine; ++function drupal_discover_template($suggestions, $extension = '.tpl.php') { ++ global $theme_engine; + +- // Because theme() is called a lot, calling init_theme() only to have it +- // smartly return is a noticeable performance hit. Don't do it. +- if (!isset($theme)) { +- init_theme(); +- } +- +- if (($theme != '') && function_exists($theme .'_'. $function)) { +- // call theme function +- return $theme .'_'. $function; +- } +- elseif (($theme != '') && isset($theme_engine) && function_exists($theme_engine .'_'. $function)) { +- // call engine function +- return $theme_engine .'_'. $function; +- } +- elseif (function_exists('theme_'. $function)){ +- // call Drupal function +- return 'theme_'. $function; ++ // Loop through any suggestions in FIFO order. ++ $suggestions = array_reverse($suggestions); ++ foreach ($suggestions as $suggestion) { ++ if (!empty($suggestion) && file_exists($file = path_to_theme() .'/'. $suggestion . $extension)) { ++ return $file; ++ } + } +- return FALSE; + } + + /** +@@ -348,16 +543,79 @@ function theme_get_setting($setting_name + } + + /** +- * @defgroup themeable Themeable functions ++ * Render a system default template, which is essentially a PHP template. ++ * ++ * @param $file ++ * The filename of the template to render. ++ * @param $variables ++ * A keyed array of variables that will appear in the output. ++ * ++ * @return ++ * The output generated by the template. ++ */ ++function theme_render_template($file, $variables) { ++ extract($variables, EXTR_SKIP); // Extract the variables to a local namespace ++ ob_start(); // Start output buffering ++ include "./$file"; // Include the file ++ $contents = ob_get_contents(); // Get the contents of the buffer ++ ob_end_clean(); // End buffering and discard ++ return $contents; // Return the contents ++} ++ ++/** ++ * @defgroup themeable Default theme implementations + * @{ +- * Functions that display HTML, and which can be customized by themes. ++ * Functions and templates that present output to the user, and can be ++ * implemented by themes. + * +- * All functions that produce HTML for display should be themeable. This means +- * that they should be named with the theme_ prefix, and invoked using theme() +- * rather than being called directly. This allows themes to override the display +- * of any Drupal object. ++ * Drupal's presentation layer is a pluggable system known as the theme ++ * layer. Each theme can take control over most of Drupal's output, and ++ * has complete control over the CSS. ++ * ++ * Inside Drupal, the theme layer is utilized by the use of the theme() ++ * function, which is passed the name of a component (the theme hook) ++ * and several arguments. For example, theme('table', $header, $rows); ++ * ++ * As of Drupal 6, every theme hook is required to be registered by the ++ * module that owns it, so that Drupal can tell what to do with it and ++ * to make it simple for themes to identify and override the behavior ++ * for these calls. ++ * ++ * The theme hooks are registered via hook_themes(), which returns an ++ * array of arrays with information about the hook. It describes the ++ * arguments the function or template will need, and provides ++ * defaults for the template in case they are not filled in. If the default ++ * implementation is a function, by convention it is named theme_HOOK(). ++ * ++ * Each module should provide a default implementation for themes that ++ * it registers. This implementation may be either a function or a template; ++ * if it is a function it must be specified via hook_themes(). By convention, ++ * default implementations of theme hooks are named theme_HOOK. Default ++ * template implementations are stored in the module directory. ++ * ++ * Drupal's default template renderer is a simple PHP parsing engine that ++ * includes the template and stores the output. Drupal's theme engines ++ * can provide alternate template engines, such as XTemplate, Smarty and ++ * PHPTal. The most common template engine is PHPTemplate (included with ++ * Drupal and implemented in phptemplate.engine, which uses Drupal's default ++ * template renderer. ++ * ++ * Themes can implement their own version of theme hooks, either as functions ++ * or files. If using a pure .theme without an engine, the .theme is required ++ * to implement its own version of hook_themes() to tell Drupal what it is ++ * implementing; themes utilizing an engine will have their well-named ++ * theming functions automatically registered for them. While this can vary ++ * based upon the theme engine, the standard set by phptemplate is that theme ++ * functions should be named either phptemplate_HOOK or THEMENAME_HOOK. For ++ * example, for Drupal's default theme (Garland) to implement the 'table' hook, ++ * the phptemplate.engine would find phptemplate_table() or garland_table(). ++ * The ENGINE_HOOK() syntax is preferred, as this can be used by sub-themes ++ * (which are themes that share code but use different stylesheets). + * + * The theme system is described and defined in theme.inc. ++ * ++ * @see theme() ++ * @see hook_themes() + */ + + /** +@@ -373,55 +631,6 @@ function theme_placeholder($text) { + return ''. check_plain($text) .''; + } + +-/** +- * Return an entire Drupal page displaying the supplied content. +- * +- * @param $content +- * A string to display in the main content area of the page. +- * @return +- * A string containing the entire HTML page. +- */ +-function theme_page($content) { +- // Get blocks before so that they can alter the header (JavaScript, Stylesheets etc.) +- $blocks = theme('blocks', 'all'); +- +- $output = "\n"; +- $output .= ''; +- $output .= ''; +- $output .= ' '. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'Drupal')) .''; +- $output .= drupal_get_html_head(); +- $output .= drupal_get_css(); +- $output .= drupal_get_js(); +- +- $output .= ' '; +- $output .= ' '; +- $output .= '
'; +- +- $output .= $blocks; +- $output .= ''; +- +- $output .= theme('breadcrumb', drupal_get_breadcrumb()); +- $output .= '

' . drupal_get_title() . '

'; +- +- if ($tabs = theme('menu_local_tasks')) { +- $output .= $tabs; +- } +- +- $output .= theme('help'); +- +- $output .= theme('status_messages'); +- +- $output .= "\n\n"; +- $output .= $content; +- $output .= drupal_get_feeds(); +- $output .= "\n\n"; +- +- $output .= '
'; +- $output .= theme('closure'); +- $output .= ''; +- +- return $output; +-} + + /** + * Generate a themed maintenance page. +@@ -458,9 +667,7 @@ function theme_maintenance_page($content + 'content' => $content, + ); + +- // Render simplified PHPTemplate. +- include_once './themes/engines/phptemplate/phptemplate.engine'; +- $output = _phptemplate_render('misc/maintenance.tpl.php', $variables); ++ $output = theme_render_template('misc/maintenance.tpl.php', $variables); + + return $output; + } +@@ -509,9 +716,7 @@ function theme_install_page($content) { + $variables['messages'] .= theme('status_messages', 'status'); + } + +- // Render simplified PHPTemplate. +- include_once './themes/engines/phptemplate/phptemplate.engine'; +- return _phptemplate_render('misc/maintenance.tpl.php', $variables); ++ return theme_render_template('misc/maintenance.tpl.php', $variables); + } + + /** +@@ -678,66 +883,6 @@ function theme_help() { + } + + /** +- * Return a themed node. +- * +- * @param $node +- * An object providing all relevant information for displaying a node: +- * - $node->nid: The ID of the node. +- * - $node->type: The content type (story, blog, forum...). +- * - $node->title: The title of the node. +- * - $node->created: The creation date, as a UNIX timestamp. +- * - $node->teaser: A shortened version of the node body. +- * - $node->body: The entire node contents. +- * - $node->changed: The last modification date, as a UNIX timestamp. +- * - $node->uid: The ID of the author. +- * - $node->username: The username of the author. +- * @param $teaser +- * Whether to display the teaser only, as on the main page. +- * @param $page +- * Whether to display the node as a standalone page. If TRUE, do not display +- * the title because it will be provided by the menu system. +- * @return +- * A string containing the node output. +- */ +-function theme_node($node, $teaser = FALSE, $page = FALSE) { +- if (!$node->status) { +- $output = '
'; +- } +- +- if (module_exists('taxonomy')) { +- $terms = taxonomy_link('taxonomy terms', $node); +- } +- +- if ($page == 0) { +- $output .= t('!title by !name', array('!title' => '

'. check_plain($node->title) .'

', '!name' => theme('username', $node))); +- } +- else { +- $output .= t('by !name', array('!name' => theme('username', $node))); +- } +- +- if (count($terms)) { +- $output .= ' ('. theme('links', $terms) .')
'; +- } +- +- if ($teaser && $node->teaser) { +- $output .= $node->teaser; +- } +- else { +- $output .= $node->body; +- } +- +- if ($node->links) { +- $output .= ''; +- } +- +- if (!$node->status) { +- $output .= '
'; +- } +- +- return $output; +-} +- +-/** + * Return a themed submenu, typically displayed under the tabs. + * + * @param $links +@@ -904,29 +1049,6 @@ function theme_box($title, $content, $re + } + + /** +- * Return a themed block. +- * +- * You can style your blocks by defining .block (all blocks), +- * .block-module (all blocks of module module), and +- * \#block-module-delta (specific block of module module +- * with delta delta) in your theme's CSS. +- * +- * @param $block +- * An object populated with fields from the "blocks" database table +- * ($block->module, $block->delta ...) and fields returned by +- * module_block('view') ($block->subject, $block->content, ...). +- * @return +- * A string containing the block output. +- */ +-function theme_block($block) { +- $output = "
module\" id=\"block-$block->module-$block->delta\">\n"; +- $output .= "

$block->subject

\n"; +- $output .= "
$block->content
\n"; +- $output .= "
\n"; +- return $output; +-} +- +-/** + * Return a themed marker, useful for marking new or updated + * content. + * +Index: modules/aggregator/aggregator.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v +retrieving revision 1.333 +diff -u -p -r1.333 aggregator.module +--- modules/aggregator/aggregator.module 27 Mar 2007 05:13:53 -0000 1.333 ++++ modules/aggregator/aggregator.module 30 Mar 2007 22:30:43 -0000 +@@ -26,6 +26,34 @@ function aggregator_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function aggregator_themes() { ++ return array( ++ 'aggregator_page_list' => array( ++ 'function' => 'theme_aggregator_page_list', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'aggregator_feed' => array( ++ 'function' => 'theme_aggregator_feed', ++ 'arguments' => array('feed' => NULL), ++ ), ++ 'aggregator_block_item' => array( ++ 'function' => 'theme_aggregator_block_item', ++ 'arguments' => array('item' => NULL, 'feed' => 0), ++ ), ++ 'aggregator_summary_item' => array( ++ 'function' => 'theme_aggregator_summary_item', ++ 'arguments' => array('item' => NULL), ++ ), ++ 'aggregator_page_item' => array( ++ 'function' => 'theme_aggregator_page_item', ++ 'arguments' => array('item' => NULL), ++ ), ++ ++ ); ++ ++/** + * Implementation of hook_menu(). + */ + function aggregator_menu() { +Index: modules/block/block.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/block/block.module,v +retrieving revision 1.254 +diff -u -p -r1.254 block.module +--- modules/block/block.module 27 Mar 2007 05:13:53 -0000 1.254 ++++ modules/block/block.module 30 Mar 2007 22:30:44 -0000 +@@ -49,6 +49,18 @@ function block_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function block_themes() { ++ return array( ++ 'block_admin_display' => array( ++ 'function' => 'theme_block_admin_display', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function block_perm() { +Index: modules/book/book.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/book/book.module,v +retrieving revision 1.414 +diff -u -p -r1.414 book.module +--- modules/book/book.module 27 Mar 2007 05:13:53 -0000 1.414 ++++ modules/book/book.module 30 Mar 2007 22:30:45 -0000 +@@ -20,6 +20,26 @@ function book_node_info() { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function book_themes() { ++ return array( ++ 'book_navigation' => array( ++ 'function' => 'theme_book_navigation', ++ 'arguments' => array('node' => NULL), ++ ), ++ 'book_export_html' => array( ++ 'function' => 'theme_book_export_html', ++ 'arguments' => array('title' => NULL, 'content' => NULL), ++ ), ++ 'book_admin_table' => array( ++ 'function' => 'theme_book_admin_table', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function book_perm() { +Index: modules/color/color.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/color/color.module,v +retrieving revision 1.17 +diff -u -p -r1.17 color.module +--- modules/color/color.module 27 Mar 2007 05:13:53 -0000 1.17 ++++ modules/color/color.module 30 Mar 2007 22:30:45 -0000 +@@ -2,6 +2,17 @@ + // $Id: color.module,v 1.17 2007/03/27 05:13:53 unconed Exp $ + + /** ++ * Implementation of hook_themes() ++ */ ++function color_themes() { ++ return array( ++ 'color_scheme_form' => array( ++ 'function' => 'theme_color_scheme_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++/** + * Implementation of hook_form_alter(). + */ + function color_form_alter(&$form, $form_id) { +Index: modules/comment/comment.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v +retrieving revision 1.533 +diff -u -p -r1.533 comment.module +--- modules/comment/comment.module 30 Mar 2007 07:45:19 -0000 1.533 ++++ modules/comment/comment.module 30 Mar 2007 22:30:48 -0000 +@@ -140,6 +140,66 @@ function comment_help($section) { + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function comment_themes() { ++ return array( ++ 'comment_block' => array( ++ 'function' => 'theme_comment_block', ++ 'arguments' => array(), ++ ), ++ 'comment_admin_overview' => array( ++ 'function' => 'theme_comment_admin_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'comment_preview' => array( ++ 'function' => 'theme_comment_preview', ++ 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), ++ ), ++ 'comment_view' => array( ++ 'function' => 'theme_comment_view', ++ 'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1), ++ ), ++ 'comment_controls' => array( ++ 'function' => 'theme_comment_controls', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'comment' => array( ++ 'function' => 'theme_comment', ++ 'arguments' => array('comment' => NULL, 'links' => array()), ++ ), ++ 'comment_folded' => array( ++ 'function' => 'theme_comment_folded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_flat_collapsed' => array( ++ 'function' => 'theme_comment_flat_collapsed', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_flat_expanded' => array( ++ 'function' => 'theme_comment_flat_expanded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_thread_collapsed' => array( ++ 'function' => 'theme_comment_thread_collapsed', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_thread_expanded' => array( ++ 'function' => 'theme_comment_thread_expanded', ++ 'arguments' => array('comment' => NULL), ++ ), ++ 'comment_post_forbidden' => array( ++ 'function' => 'theme_comment_post_forbidden', ++ 'arguments' => array('nid' => NULL), ++ ), ++ 'comment_wrapper' => array( ++ 'function' => 'theme_comment_wrapper', ++ 'arguments' => array('content' => NULL), ++ ), ++ ); ++} ++ + function _comment_view_access($node, $cid) { + return $node && $cid; + } +Index: modules/drupal/drupal.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/drupal/drupal.module,v +retrieving revision 1.140 +diff -u -p -r1.140 drupal.module +--- modules/drupal/drupal.module 27 Feb 2007 12:29:22 -0000 1.140 ++++ modules/drupal/drupal.module 30 Mar 2007 22:30:48 -0000 +@@ -46,6 +46,18 @@ print drupal_client_page(); + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function drupal_themes() { ++ return array( ++ 'client_list' => array( ++ 'function' => 'theme_client_list', ++ 'arguments' => array('clients' => NULL), ++ ), ++ ); ++} ++ + function drupal_sites_registry_settings() { + // Check if all required fields are present + if ((variable_get('site_name', 'Drupal') == 'Drupal') || (variable_get('site_name', 'Drupal') == '')) { +Index: modules/filter/filter.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v +retrieving revision 1.166 +diff -u -p -r1.166 filter.module +--- modules/filter/filter.module 12 Mar 2007 11:31:02 -0000 1.166 ++++ modules/filter/filter.module 30 Mar 2007 22:30:50 -0000 +@@ -48,6 +48,30 @@ function filter_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function filter_themes() { ++ return array( ++ 'filter_admin_overview' => array( ++ 'function' => 'theme_filter_admin_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'filter_admin_order' => array( ++ 'function' => 'theme_filter_admin_order', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'filter_tips' => array( ++ 'function' => 'theme_filter_tips', ++ 'arguments' => array('tips' => NULL, 'long' => FALSE, 'extra' => ''), ++ ), ++ 'filter_tips_more_info' => array( ++ 'function' => 'theme_filter_tips_more_info', ++ 'arguments' => array(), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function filter_menu() { +Index: modules/forum/forum.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v +retrieving revision 1.390 +diff -u -p -r1.390 forum.module +--- modules/forum/forum.module 28 Mar 2007 14:08:22 -0000 1.390 ++++ modules/forum/forum.module 30 Mar 2007 22:30:51 -0000 +@@ -29,6 +29,34 @@ function forum_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function forum_themes() { ++ return array( ++ 'forum_display' => array( ++ 'function' => 'theme_forum_display', ++ 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), ++ ), ++ 'forum_list' => array( ++ 'function' => 'theme_forum_list', ++ 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), ++ ), ++ 'forum_topic_list' => array( ++ 'function' => 'theme_forum_topic_list', ++ 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), ++ ), ++ 'forum_icon' => array( ++ 'function' => 'theme_forum_icon', ++ 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), ++ ), ++ 'forum_topic_navigation' => array( ++ 'function' => 'theme_forum_topic_navigation', ++ 'arguments' => array('node' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function forum_menu() { +Index: modules/node/node.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/node/node.module,v +retrieving revision 1.794 +diff -u -p -r1.794 node.module +--- modules/node/node.module 27 Mar 2007 05:13:54 -0000 1.794 ++++ modules/node/node.module 30 Mar 2007 22:30:54 -0000 +@@ -46,6 +46,46 @@ function node_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function node_themes() { ++ return array( ++ 'node_list' => array( ++ 'function' => 'theme_node_list', ++ 'arguments' => array('items' => NULL, 'title' => NULL), ++ ), ++ 'node_search_admin' => array( ++ 'function' => 'theme_node_search_admin', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_filter_form' => array( ++ 'function' => 'theme_node_filter_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_filters' => array( ++ 'function' => 'theme_node_filters', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_admin_nodes' => array( ++ 'function' => 'theme_node_admin_nodes', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_form' => array( ++ 'function' => 'theme_node_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'node_preview' => array( ++ 'function' => 'theme_node_preview', ++ 'arguments' => array('node' => NULL), ++ ), ++ 'node_log_message' => array( ++ 'function' => 'theme_node_log_message', ++ 'arguments' => array('log' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_cron(). + */ + function node_cron() { +@@ -2350,7 +2390,6 @@ function node_revisions() { + * Menu callback; Generate a listing of promoted nodes. + */ + 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)); + + if (db_num_rows($result)) { +Index: modules/poll/poll.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v +retrieving revision 1.225 +diff -u -p -r1.225 poll.module +--- modules/poll/poll.module 27 Mar 2007 05:13:54 -0000 1.225 ++++ modules/poll/poll.module 30 Mar 2007 22:30:54 -0000 +@@ -21,6 +21,26 @@ function poll_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function poll_themes() { ++ return array( ++ 'poll_view_voting' => array( ++ 'function' => 'theme_poll_view_voting', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'poll_results' => array( ++ 'function' => 'theme_poll_results', ++ 'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL, 'links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL), ++ ), ++ 'poll_bar' => array( ++ 'function' => 'theme_poll_bar', ++ 'arguments' => array('title' => NULL, 'percentage' => NULL, 'votes' => NULL, 'block' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_access(). + */ + function poll_access($op, $node) { +Index: modules/profile/profile.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v +retrieving revision 1.196 +diff -u -p -r1.196 profile.module +--- modules/profile/profile.module 30 Mar 2007 09:38:13 -0000 1.196 ++++ modules/profile/profile.module 30 Mar 2007 22:30:55 -0000 +@@ -52,6 +52,21 @@ function profile_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function profile_themes() { ++ return array( ++ 'profile_block' => array( ++ 'function' => 'theme_profile_block', ++ 'arguments' => array('account' => NULL, 'fields' => array()), ++ ), ++ 'profile_listing' => array( ++ 'function' => 'theme_profile_listing', ++ 'arguments' => array('account' => NULL, 'fields' => array()), ++ ), ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function profile_menu() { +Index: modules/search/search.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/search/search.module,v +retrieving revision 1.216 +diff -u -p -r1.216 search.module +--- modules/search/search.module 27 Mar 2007 05:13:54 -0000 1.216 ++++ modules/search/search.module 30 Mar 2007 22:30:56 -0000 +@@ -112,6 +112,30 @@ function search_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function search_themes() { ++ return array( ++ 'search_theme_form' => array( ++ 'function' => 'theme_search_theme_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'search_block_form' => array( ++ 'function' => 'theme_search_block_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'search_item' => array( ++ 'function' => 'theme_search_item', ++ 'arguments' => array('item' => NULL, 'type' => NULL), ++ ), ++ 'search_page' => array( ++ 'function' => 'theme_search_page', ++ 'arguments' => array('results' => NULL, 'type' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function search_perm() { +Index: modules/system/system.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/system/system.module,v +retrieving revision 1.460 +diff -u -p -r1.460 system.module +--- modules/system/system.module 27 Mar 2007 05:13:54 -0000 1.460 ++++ modules/system/system.module 30 Mar 2007 22:30:59 -0000 +@@ -48,6 +48,46 @@ function system_help($section) { + } + } + ++function system_themes() { ++ return array_merge(drupal_common_themes(), array( ++ 'system_theme_select_form' => array( ++ 'function' => 'theme_system_theme_select_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_themes_form' => array( ++ 'function' => 'theme_system_themes_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_modules' => array( ++ 'function' => 'theme_system_modules', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'system_modules_uninstall' => array( ++ 'function' => 'theme_system_modules_uninstall', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'status_report' => array( ++ 'function' => 'theme_status_report', ++ 'arguments' => array('requirements' => NULL), ++ ), ++ 'admin_page' => array( ++ 'function' => 'theme_admin_page', ++ 'arguments' => array('blocks' => NULL), ++ ), ++ 'admin_block' => array( ++ 'function' => 'theme_admin_block', ++ 'arguments' => array('block' => NULL), ++ ), ++ 'admin_block_content' => array( ++ 'function' => 'theme_admin_block_content', ++ 'arguments' => array('content' => NULL), ++ ), ++ 'system_admin_by_module' => array( ++ 'function' => 'theme_system_admin_by_module', ++ 'arguments' => array('menu_items' => NULL), ++ ), ++ )); ++} + /** + * Implementation of hook_perm(). + */ +@@ -150,7 +190,7 @@ function system_menu() { + 'title' => t('Themes'), + 'description' => t('Change which theme your site uses or allows users to set.'), + 'page callback' => 'drupal_get_form', +- 'page arguments' => array('system_themes'), ++ 'page arguments' => array('system_themes_form'), + ); + $items['admin/build/themes/select'] = array( + 'title' => t('List'), +@@ -1143,7 +1183,7 @@ function system_settings_form_submit($fo + /** + * Menu callback; displays a listing of all themes. + */ +-function system_themes() { ++function system_themes_form() { + + drupal_clear_css_cache(); + $themes = system_theme_data(); +@@ -1177,7 +1217,7 @@ function system_themes() { + return $form; + } + +-function theme_system_themes($form) { ++function theme_system_themes_form($form) { + foreach (element_children($form) as $key) { + $row = array(); + if (isset($form[$key]['description']) && is_array($form[$key]['description'])) { +@@ -1199,7 +1239,7 @@ function theme_system_themes($form) { + } + + +-function system_themes_submit($form_id, $form_values) { ++function system_themes_form_submit($form_id, $form_values) { + + db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'"); + +Index: modules/taxonomy/taxonomy.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v +retrieving revision 1.344 +diff -u -p -r1.344 taxonomy.module +--- modules/taxonomy/taxonomy.module 27 Mar 2007 05:13:54 -0000 1.344 ++++ modules/taxonomy/taxonomy.module 30 Mar 2007 22:31:00 -0000 +@@ -14,6 +14,18 @@ function taxonomy_perm() { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function taxonomy_themes() { ++ return array( ++ 'taxonomy_term_select' => array( ++ 'function' => 'theme_taxonomy_term_select', ++ 'arguments' => array('element' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_link(). + * + * This hook is extended with $type = 'taxonomy terms' to allow themes to +Index: modules/upload/upload.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v +retrieving revision 1.156 +diff -u -p -r1.156 upload.module +--- modules/upload/upload.module 27 Mar 2007 05:13:54 -0000 1.156 ++++ modules/upload/upload.module 30 Mar 2007 22:31:01 -0000 +@@ -23,6 +23,26 @@ function upload_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function upload_themes() { ++ return array( ++ 'upload_attachments' => array( ++ 'function' => 'theme_upload_attachments', ++ 'arguments' => array('files' => NULL), ++ ), ++ 'upload_form_current' => array( ++ 'function' => 'theme_upload_form_current', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'upload_form_new' => array( ++ 'function' => 'theme_upload_form_new', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_perm(). + */ + function upload_perm() { +Index: modules/user/user.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/user/user.module,v +retrieving revision 1.763 +diff -u -p -r1.763 user.module +--- modules/user/user.module 30 Mar 2007 07:45:19 -0000 1.763 ++++ modules/user/user.module 30 Mar 2007 22:31:05 -0000 +@@ -24,6 +24,46 @@ function user_module_invoke($type, &$arr + } + } + ++/** ++ * Implementation of hook_themes() ++ */ ++function user_themes() { ++ return array( ++ 'user_picture' => array( ++ 'function' => 'theme_user_picture', ++ 'arguments' => array('account' => NULL), ++ ), ++ 'user_profile' => array( ++ 'function' => 'theme_user_profile', ++ 'arguments' => array('account' => NULL, 'fields' => NULL), ++ ), ++ 'user_list' => array( ++ 'function' => 'theme_user_list', ++ 'arguments' => array('users' => NULL, 'title' => NULL), ++ ), ++ 'user_admin_perm' => array( ++ 'function' => 'theme_user_admin_perm', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_admin_new_role' => array( ++ 'function' => 'theme_user_admin_new_role', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_admin_account' => array( ++ 'function' => 'theme_user_admin_account', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_filter_form' => array( ++ 'function' => 'theme_user_filter_form', ++ 'arguments' => array('form' => NULL), ++ ), ++ 'user_filters' => array( ++ 'function' => 'theme_user_filters', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ + function user_external_load($authname) { + $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname); + +Index: modules/watchdog/watchdog.module +=================================================================== +RCS file: /cvs/drupal/drupal/modules/watchdog/watchdog.module,v +retrieving revision 1.171 +diff -u -p -r1.171 watchdog.module +--- modules/watchdog/watchdog.module 27 Feb 2007 12:29:22 -0000 1.171 ++++ modules/watchdog/watchdog.module 30 Mar 2007 22:31:05 -0000 +@@ -28,6 +28,18 @@ function watchdog_help($section) { + } + + /** ++ * Implementation of hook_themes() ++ */ ++function watchdog_themes() { ++ return array( ++ 'watchdog_form_overview' => array( ++ 'function' => 'theme_watchdog_form_overview', ++ 'arguments' => array('form' => NULL), ++ ), ++ ); ++} ++ ++/** + * Implementation of hook_menu(). + */ + function watchdog_menu() { +Index: themes/chameleon/chameleon.theme +=================================================================== +RCS file: /cvs/drupal/drupal/themes/chameleon/chameleon.theme,v +retrieving revision 1.57 +diff -u -p -r1.57 chameleon.theme +--- themes/chameleon/chameleon.theme 30 Mar 2007 07:45:19 -0000 1.57 ++++ themes/chameleon/chameleon.theme 30 Mar 2007 22:31:05 -0000 +@@ -6,6 +6,23 @@ + * A slim, CSS-driven theme which does not depend on a template engine like phptemplate + */ + ++/** ++ * Implementation of hook_themes. Auto-discover theme functions. ++ */ ++function chameleon_themes($existing) { ++ $templates = array(); ++ // Check for function overrides. ++ global $theme; ++ foreach ($existing as $hook => $info) { ++ if (function_exists($theme .'_'. $hook)) { ++ $templates[$hook] = array( ++ 'function' => $theme .'_'. $hook, ++ ); ++ } ++ } ++ return $templates; ++} ++ + function chameleon_features() { + return array( + 'toggle_logo', +@@ -22,7 +39,7 @@ function chameleon_regions() { + } + + function chameleon_page($content, $show_blocks = TRUE) { +- $language = $GLOBALS['locale']; ++ $language = isset($GLOBALS['locale']) ? $GLOBALS['locale'] : NULL; + + if (theme_get_setting('toggle_favicon')) { + drupal_set_html_head(''); +Index: themes/engines/phptemplate/phptemplate.engine +=================================================================== +RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v +retrieving revision 1.61 +diff -u -p -r1.61 phptemplate.engine +--- themes/engines/phptemplate/phptemplate.engine 30 Mar 2007 07:45:19 -0000 1.61 ++++ themes/engines/phptemplate/phptemplate.engine 30 Mar 2007 22:31:05 -0000 +@@ -9,10 +9,71 @@ + function phptemplate_init($template) { + $file = dirname($template->filename) . '/template.php'; + if (file_exists($file)) { +- include_once "./$file"; ++ include_once "./$file"; + } + } + ++/** ++ * @return ++ * Array of template features ++ */ ++function phptemplate_features() { ++ return array( ++ 'toggle_logo', ++ 'toggle_comment_user_picture', ++ 'toggle_favicon', ++ 'toggle_mission', ++ 'toggle_name', ++ 'toggle_node_user_picture', ++ 'toggle_search', ++ 'toggle_slogan' ++ ); ++} ++ ++/** ++ * Implementation of hook_themes to tell Drupal what templates the engine ++ * and the current theme use. ++ */ ++function phptemplate_themes($existing) { ++ $templates = array( ++ 'regions' => array('function' => 'phptemplate_regions'), ++ 'box' => array('file' => 'box'), ++ 'node' => array('file' => 'node'), ++ 'comment' => array('file' => 'comment'), ++ 'block' => array('file' => 'block'), ++ ); ++ ++ // Check for template overrides. ++ $files = drupal_system_listing('\.tpl\.php$', path_to_theme(), 'name', 0); ++ ++ foreach ($files as $template => $file) { ++ // chop off the .tpl ++ $template = substr($template, 0, -4); ++ if (isset($existing[$template])) { ++ $templates[$template] = array( ++ 'file' => $template, ++ 'path' => dirname($file->filename), ++ ); ++ } ++ } ++ ++ // Check for function overrides. ++ global $theme; ++ foreach ($existing as $hook => $info) { ++ if (function_exists($theme .'_'. $hook)) { ++ $templates[$hook] = array( ++ 'function' => $theme .'_'. $hook, ++ ); ++ } ++ else if (function_exists('phptemplate_'. $hook)) { ++ $templates[$hook] = array( ++ 'function' => 'phptemplate_'. $hook, ++ ); ++ } ++ } ++ return $templates; ++} ++ + function phptemplate_templates($directory = 'themes') { + return drupal_system_listing('^page\.tpl\.php$', $directory, 'filename'); + } +@@ -34,55 +95,6 @@ function phptemplate_regions() { + } + + /** +- * Execute a template engine call. +- * +- * Each call to the template engine has two parts. Namely preparing +- * the variables, and then doing something with them. +- * +- * The first step is done by all template engines / themes, the second +- * step is dependent on the engine used. +- * +- * @param $hook +- * The name of the theme function being executed. +- * @param $variables +- * A sequential array of variables passed to the theme function. +- * @param $suggestions +- * An array of suggested template files to use. If none of the files are found, the +- * default $hook.tpl.php will be used. +- * @return +- * The HTML generated by the template system. +- */ +-function _phptemplate_callback($hook, $variables = array(), $suggestions = array()) { +- global $theme_engine; +- +- $variables = array_merge($variables, _phptemplate_default_variables($hook, $variables)); +- +- // Allow specified variables to be overridden +- $variables_function = '_'. $theme_engine .'_variables'; +- if (function_exists($variables_function)) { +- $variables = array_merge($variables, call_user_func($variables_function, $hook, $variables)); +- } +- +- if (isset($variables['template_files'])) { +- $suggestions = array_merge($suggestions, $variables['template_files']); +- } +- +- if (isset($variables['template_file'])) { +- $suggestions[] = $variables['template_file']; +- } +- +- $hook_function = '_'. $theme_engine .'_'. $hook; +- $default_function = '_'. $theme_engine .'_default'; +- if (function_exists($hook_function)) { +- return call_user_func($hook_function, $variables, $suggestions); +- } +- elseif (function_exists($default_function)) { +- return call_user_func($default_function, $hook, $variables, $suggestions); +- } +- +-} +- +-/** + * Adds additional helper variables to all templates. + * + * Counts how many times certain hooks have been called. Sidebar left / right are special cases. +@@ -92,66 +104,29 @@ function _phptemplate_callback($hook, $v + * @param $variables + * A sequential array of variables passed to the theme function. + */ +-function _phptemplate_default_variables($hook, $variables) { ++function phptemplate_engine_variables(&$variables, $hook) { + global $theme, $sidebar_indicator; + static $count = array(); + ++ // Create variables so anything which is themed can be zebra striped automatically. + $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1; + $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even'; + $variables['id'] = $count[$hook]++; + +- if ($hook == 'block') { +- $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1; +- $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even'; +- $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++; +- } +- elseif ($hook == 'page') { +- $regions = system_region_list($theme); +- // Load all region content assigned via blocks. +- foreach (array_keys($regions) as $region) { +- // Skip blocks in this region that have already been loaded. +- // This pre-loading is necessary because phptemplate uses variable names different from +- // the region names, e.g., 'sidebar_left' instead of 'left'. +- if (!in_array($region, array('left', 'right', 'footer'))) { +- isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region); +- } +- } +- } + // Tell all templates where they are located. + $variables['directory'] = path_to_theme(); + $variables['is_front'] = drupal_is_front_page(); +- +- return $variables; + } + + /** +- * @return +- * Array of template features +- */ +-function phptemplate_features() { +- return array( +- 'toggle_logo', +- 'toggle_comment_user_picture', +- 'toggle_favicon', +- 'toggle_mission', +- 'toggle_name', +- 'toggle_node_user_picture', +- 'toggle_search', +- 'toggle_slogan' +- ); +-} +- +-/** +- * Prepare the values passed to the theme_page function to be passed +- * into a pluggable template engine. Uses the arg() function to +- * generate a series of page template files suggestions based on the +- * current path. If none are found, the default page.tpl.php is used. ++ * Prepare the variables passed to the page.tpl.php template Uses the arg() ++ * function to generate a series of page template files suggestions based on ++ * the current path. + */ +-function phptemplate_page($content, $show_blocks = TRUE) { +- ++function phptemplate_engine_variables_page(&$variables) { + /* Set title and breadcrumb to declared values */ + if (drupal_is_front_page()) { +- $mission = filter_xss_admin(theme_get_setting('mission')); ++ $variables['mission'] = filter_xss_admin(theme_get_setting('mission')); + } + + /* Add favicon */ +@@ -159,26 +134,44 @@ function phptemplate_page($content, $sho + drupal_set_html_head(''); + } + +- // Populate sidebars ++ /** ++ * Populate sidebars. ++ */ ++ $variables['sidebar_left'] = NULL; ++ $variables['sidebar_right'] = NULL; + $layout = 'none'; +- if ($show_blocks) { ++ if ($variables['show_blocks']) { + global $sidebar_indicator; + /** + * Sidebar_indicator tells the block counting code to count sidebars separately. + */ + $sidebar_indicator = 'left'; +- $sidebar_left = theme('blocks', 'left'); +- if ($sidebar_left != '') { ++ $variables['sidebar_left'] = theme('blocks', 'left'); ++ if ($variables['sidebar_left'] != '') { + $layout = 'left'; + } + + $sidebar_indicator = 'right'; +- $sidebar_right = theme('blocks', 'right'); +- if ($sidebar_right != '') { +- $layout = ($layout == 'left') ? 'both' : 'right'; ++ $variables['sidebar_right'] = theme('blocks', 'right'); ++ if ($variables['sidebar_right'] != '') { ++ $variables['layout'] = ($layout == 'left') ? 'both' : 'right'; + } + $sidebar_indicator = NULL; + } ++ $variables['layout'] = $layout; ++ ++ global $theme; ++ // Populate the rest of the regions. ++ $regions = system_region_list($theme); ++ // Load all region content assigned via blocks. ++ foreach (array_keys($regions) as $region) { ++ // Skip blocks in this region that have already been loaded. ++ // This pre-loading is necessary because phptemplate uses variable names different from ++ // the region names, e.g., 'sidebar_left' instead of 'left'. ++ if (!in_array($region, array('left', 'right', 'footer'))) { ++ isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region); ++ } ++ } + + // Construct page title + if (drupal_get_title()) { +@@ -190,35 +183,28 @@ function phptemplate_page($content, $sho + $head_title[] = variable_get('site_slogan', ''); + } + } +- +- $variables = array( +- 'base_path' => base_path(), +- 'breadcrumb' => theme('breadcrumb', drupal_get_breadcrumb()), +- 'closure' => theme('closure'), +- 'content' => $content, +- 'feed_icons' => drupal_get_feeds(), +- 'footer_message' => filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'), +- 'head' => drupal_get_html_head(), +- 'head_title' => implode(' | ', $head_title), +- 'help' => theme('help'), +- 'language' => $GLOBALS['language'], +- 'layout' => isset($layout) ? $layout : NULL, +- 'logo' => theme_get_setting('logo'), +- 'messages' => theme('status_messages'), +- 'mission' => isset($mission) ? $mission : '', +- 'primary_links' => menu_primary_links(), +- 'search_box' => (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''), +- 'secondary_links' => menu_secondary_links(), +- 'sidebar_left' => !empty($sidebar_left) ? $sidebar_left : '', +- 'sidebar_right' => !empty($sidebar_right) ? $sidebar_right : '', +- 'site_name' => (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''), +- 'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''), +- 'css' => drupal_add_css(), +- 'styles' => drupal_get_css(), +- 'scripts' => drupal_get_js(), +- 'tabs' => theme('menu_local_tasks'), +- 'title' => drupal_get_title() +- ); ++ $variables['head_title'] = implode(' | ', $head_title); ++ $variables['base_path'] = base_path(); ++ $variables['breadcrumb'] = theme('breadcrumb', drupal_get_breadcrumb()); ++ $variables['closure'] = theme('closure'); ++ $variables['feed_icons'] = drupal_get_feeds(); ++ $variables['footer_message'] = filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'); ++ $variables['head'] = drupal_get_html_head(); ++ $variables['help'] = theme('help'); ++ $variables['language'] = $GLOBALS['language']; ++ $variables['logo'] = theme_get_setting('logo'); ++ $variables['messages'] = theme('status_messages'); ++ $variables['mission'] = isset($mission) ? $mission : ''; ++ $variables['primary_links'] = menu_primary_links(); ++ $variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''); ++ $variables['secondary_links'] = menu_secondary_links(); ++ $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''); ++ $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''); ++ $variables['css'] = drupal_add_css(); ++ $variables['styles'] = drupal_get_css(); ++ $variables['scripts'] = drupal_get_js(); ++ $variables['tabs'] = theme('menu_local_tasks'); ++ $variables['title'] = drupal_get_title(); + + if ((arg(0) == 'node') && is_numeric(arg(1))) { + $variables['node'] = node_load(arg(1)); +@@ -236,7 +222,7 @@ function phptemplate_page($content, $sho + // page.tpl.php + $i = 0; + $suggestion = 'page'; +- $suggestions = array($suggestion); ++ $suggestions = array(); + while ($arg = arg($i++)) { + $suggestions[] = $suggestion . '-' . $arg; + if (!is_numeric($arg)) { +@@ -247,43 +233,40 @@ function phptemplate_page($content, $sho + $suggestions[] = 'page-front'; + } + +- return _phptemplate_callback('page', $variables, $suggestions); ++ if ($suggestions) { ++ $variables['template_files'] = $suggestions; ++ } + } + + /* + * Prepare the values passed to the theme_node function to be passed +- * into a pluggable template engine. ++ * into standard template files. + */ +-function phptemplate_node($node, $teaser = 0, $page = 0) { ++function phptemplate_engine_variables_node(&$variables) { ++ $node = $variables['node']; + if (module_exists('taxonomy')) { +- $taxonomy = taxonomy_link('taxonomy terms', $node); ++ $variables['taxonomy'] = taxonomy_link('taxonomy terms', $node); + } + else { +- $taxonomy = array(); ++ $variables['taxonomy'] = array(); + } +- if ($teaser && $node->teaser) { +- $content = $node->teaser; ++ ++ if ($variables['teaser'] && $node->teaser) { ++ $variables['content'] = $node->teaser; + } + elseif (isset($node->body)) { +- $content = $node->body; ++ $variables['content'] = $node->body; + } + else { +- $content = ''; ++ $variables['content'] = ''; + } + +- $variables = array( +- 'content' => $content, +- 'date' => format_date($node->created), +- 'links' => !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : '', +- 'name' => theme('username', $node), +- 'node' => $node, // we pass the actual node to allow more customization +- 'node_url' => url('node/'. $node->nid), +- 'page' => $page, +- 'taxonomy' => $taxonomy, +- 'teaser' => $teaser, +- 'terms' => theme('links', $taxonomy, array('class' => 'links inline')), +- 'title' => check_plain($node->title) +- ); ++ $variables['date'] = format_date($node->created); ++ $variables['links'] = !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : ''; ++ $variables['name'] = theme('username', $node); ++ $variables['node_url'] = url('node/'. $node->nid); ++ $variables['terms'] = theme('links', $variables['taxonomy'], array('class' => 'links inline')); ++ $variables['title'] = check_plain($node->title); + + // Flatten the node object's member fields. + $variables = array_merge((array)$node, $variables); +@@ -298,28 +281,28 @@ function phptemplate_node($node, $teaser + $variables['picture'] = ''; + } + +- return _phptemplate_callback('node', $variables, array('node-' . $node->type)); ++ $variables['template_files'][] = 'node-'. $node->type; + } + + /** + * Prepare the values passed to the theme_comment function to be passed + * into a pluggable template engine. + */ +-function phptemplate_comment($comment, $links = 0) { +- return _phptemplate_callback('comment', array( +- 'author' => theme('username', $comment), +- 'comment' => $comment, +- 'content' => $comment->comment, +- 'date' => format_date($comment->timestamp), +- 'links' => isset($links) ? theme('links', $links) : '', +- 'new' => $comment->new ? t('new') : '', +- 'signature' => $comment->signature, +- 'picture' => theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '', +- 'submitted' => t('Submitted by !a on @b.', ++// function phptemplate_comment($comment, $links = 0) { ++function phptemplate_engine_variables_comment(&$variables) { ++ $comment = $variables['comment']; ++ $variables['author'] = theme('username', $comment); ++ $variables['comment'] = $comment; ++ $variables['content'] = $comment->comment; ++ $variables['date'] = format_date($comment->timestamp); ++ $variables['links'] = isset($variables['links']) ? theme('links', $variables['links']) : ''; ++ $variables['new'] = $comment->new ? t('new') : ''; ++ $variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : ''; ++ $variables['signature'] = $comment->signature; ++ $variables['submitted'] = t('Submitted by !a on @b.', + array('!a' => theme('username', $comment), +- '@b' => format_date($comment->timestamp))), +- 'title' => l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid")) +- )); ++ '@b' => format_date($comment->timestamp))); ++ $variables['title'] = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid")); + } + + /** +@@ -328,82 +311,14 @@ function phptemplate_comment($comment, $ + * series of template file suggestions. If none are found, the default + * block.tpl.php is used. + */ +-function phptemplate_block($block) { +- $suggestions[] = 'block'; +- $suggestions[] = 'block-' . $block->region; +- $suggestions[] = 'block-' . $block->module; +- $suggestions[] = 'block-' . $block->module . '-' . $block->delta; +- +- return _phptemplate_callback('block', array('block' => $block), $suggestions); ++function phptemplate_engine_variables_block(&$variables) { ++ global $sidebar_indicator; ++ $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1; ++ ++ $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even'; ++ ++ $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++; ++ $variables['template_files'][] = 'block-' . $variables['block']->region; ++ $variables['template_files'][] = 'block-' . $variables['block']->module; ++ $variables['template_files'][] = 'block-' . $variables['block']->module .'-'. $variables['block']->delta; + } +- +-/** +- * Prepare the values passed to the theme_box function to be passed +- * into a pluggable template engine. +- */ +-function phptemplate_box($title, $content, $region = 'main') { +- return _phptemplate_callback('box', array( +- 'content' => $content, +- 'region' => $region, +- 'title' => $title +- )); +-} +- +-/** +- * Default callback for PHPTemplate. +- * +- * Load a template file, and pass the variable array to it. +- * If the suggested file is not found, PHPTemplate will attempt to use +- * a $hook.tpl.php file in the template directory, and failing that a +- * $hook.tpl.php in the PHPTemplate directory. +- * +- * @param $hook +- * The name of the theme function being executed. +- * @param $variables +- * A sequential array of variables passed to the theme function. +- * @param $suggestions +- * An array of suggested template files to use. +- */ +-function _phptemplate_default($hook, $variables, $suggestions = array(), $extension = '.tpl.php') { +- global $theme_engine; +- +- // Loop through any suggestions in FIFO order. +- $suggestions = array_reverse($suggestions); +- foreach ($suggestions as $suggestion) { +- if (!empty($suggestion) && file_exists(path_to_theme() .'/'. $suggestion . $extension)) { +- $file = path_to_theme() .'/'. $suggestion . $extension; +- break; +- } +- } +- +- if (!isset($file)) { +- if (file_exists(path_to_theme() ."/$hook$extension")) { +- $file = path_to_theme() ."/$hook$extension"; +- } +- else { +- if (in_array($hook, array('node', 'block', 'box', 'comment'))) { +- $file = path_to_engine() .'/'. $hook . $extension; +- } +- else { +- $variables['hook'] = $hook; +- watchdog('error', t('%engine.engine was instructed to override the %name theme function, but no valid template file was found.', array('%engine' => $theme_engine, '%name' => $hook))); +- $file = path_to_engine() .'/default'. $extension; +- } +- } +- } +- +- if (isset($file)) { +- return call_user_func('_'. $theme_engine .'_render', $file, $variables); +- } +-} +- +-function _phptemplate_render($file, $variables) { +- extract($variables, EXTR_SKIP); // Extract the variables to a local namespace +- ob_start(); // Start output buffering +- include "./$file"; // Include the file +- $contents = ob_get_contents(); // Get the contents of the buffer +- ob_end_clean(); // End buffering and discard +- return $contents; // Return the contents +-} +- +-?> +Index: themes/garland/template.php +=================================================================== +RCS file: /cvs/drupal/drupal/themes/garland/template.php,v +retrieving revision 1.6 +diff -u -p -r1.6 template.php +--- themes/garland/template.php 20 Mar 2007 19:07:55 -0000 1.6 ++++ themes/garland/template.php 30 Mar 2007 22:31:06 -0000 +@@ -1,4 +1,6 @@ + '; +- $output .= "\n"; +- $vars['tabs2'] = $output; +- } ++function phptemplate_variables_page(&$vars) { ++ if ($secondary = menu_secondary_local_tasks()) { ++ $output = ''; ++ $output .= "\n"; ++ $vars['tabs2'] = $output; ++ } + +- // Hook into color.module +- if (module_exists('color')) { +- _color_page_alter($vars); +- } +- return $vars; ++ // Hook into color.module ++ if (module_exists('color')) { ++ _color_page_alter($vars); + } +- return array(); + } + + /** Binary files ../drupal-themeswo/themes/.DS_Store and ./themes/.DS_Store differ Binary files ../drupal-themeswo/themes/bluemarine/.DS_Store and ./themes/bluemarine/.DS_Store differ diff -urNp ../drupal-themeswo/themes/chameleon/chameleon.theme ./themes/chameleon/chameleon.theme --- ../drupal-themeswo/themes/chameleon/chameleon.theme 2007-03-30 00:45:19.000000000 -0700 +++ ./themes/chameleon/chameleon.theme 2007-03-31 12:13:22.000000000 -0700 @@ -6,6 +6,23 @@ * A slim, CSS-driven theme which does not depend on a template engine like phptemplate */ +/** + * Implementation of hook_themes. Auto-discover theme functions. + */ +function chameleon_themes($existing) { + $templates = array(); + // Check for function overrides. + global $theme; + foreach ($existing as $hook => $info) { + if (function_exists($theme .'_'. $hook)) { + $templates[$hook] = array( + 'function' => $theme .'_'. $hook, + ); + } + } + return $templates; +} + function chameleon_features() { return array( 'toggle_logo', @@ -22,7 +39,7 @@ function chameleon_regions() { } function chameleon_page($content, $show_blocks = TRUE) { - $language = $GLOBALS['locale']; + $language = isset($GLOBALS['locale']) ? $GLOBALS['locale'] : NULL; if (theme_get_setting('toggle_favicon')) { drupal_set_html_head(''); diff -urNp ../drupal-themeswo/themes/engines/phptemplate/phptemplate.engine ./themes/engines/phptemplate/phptemplate.engine --- ../drupal-themeswo/themes/engines/phptemplate/phptemplate.engine 2007-03-30 00:45:19.000000000 -0700 +++ ./themes/engines/phptemplate/phptemplate.engine 2007-03-31 12:13:22.000000000 -0700 @@ -9,10 +9,71 @@ function phptemplate_init($template) { $file = dirname($template->filename) . '/template.php'; if (file_exists($file)) { - include_once "./$file"; + include_once "./$file"; } } +/** + * @return + * Array of template features + */ +function phptemplate_features() { + return array( + 'toggle_logo', + 'toggle_comment_user_picture', + 'toggle_favicon', + 'toggle_mission', + 'toggle_name', + 'toggle_node_user_picture', + 'toggle_search', + 'toggle_slogan' + ); +} + +/** + * Implementation of hook_themes to tell Drupal what templates the engine + * and the current theme use. + */ +function phptemplate_themes($existing) { + $templates = array( + 'regions' => array('function' => 'phptemplate_regions'), + 'box' => array('file' => 'box'), + 'node' => array('file' => 'node'), + 'comment' => array('file' => 'comment'), + 'block' => array('file' => 'block'), + ); + + // Check for template overrides. + $files = drupal_system_listing('\.tpl\.php$', path_to_theme(), 'name', 0); + + foreach ($files as $template => $file) { + // chop off the .tpl + $template = substr($template, 0, -4); + if (isset($existing[$template])) { + $templates[$template] = array( + 'file' => $template, + 'path' => dirname($file->filename), + ); + } + } + + // Check for function overrides. + global $theme; + foreach ($existing as $hook => $info) { + if (function_exists($theme .'_'. $hook)) { + $templates[$hook] = array( + 'function' => $theme .'_'. $hook, + ); + } + else if (function_exists('phptemplate_'. $hook)) { + $templates[$hook] = array( + 'function' => 'phptemplate_'. $hook, + ); + } + } + return $templates; +} + function phptemplate_templates($directory = 'themes') { return drupal_system_listing('^page\.tpl\.php$', $directory, 'filename'); } @@ -34,55 +95,6 @@ function phptemplate_regions() { } /** - * Execute a template engine call. - * - * Each call to the template engine has two parts. Namely preparing - * the variables, and then doing something with them. - * - * The first step is done by all template engines / themes, the second - * step is dependent on the engine used. - * - * @param $hook - * The name of the theme function being executed. - * @param $variables - * A sequential array of variables passed to the theme function. - * @param $suggestions - * An array of suggested template files to use. If none of the files are found, the - * default $hook.tpl.php will be used. - * @return - * The HTML generated by the template system. - */ -function _phptemplate_callback($hook, $variables = array(), $suggestions = array()) { - global $theme_engine; - - $variables = array_merge($variables, _phptemplate_default_variables($hook, $variables)); - - // Allow specified variables to be overridden - $variables_function = '_'. $theme_engine .'_variables'; - if (function_exists($variables_function)) { - $variables = array_merge($variables, call_user_func($variables_function, $hook, $variables)); - } - - if (isset($variables['template_files'])) { - $suggestions = array_merge($suggestions, $variables['template_files']); - } - - if (isset($variables['template_file'])) { - $suggestions[] = $variables['template_file']; - } - - $hook_function = '_'. $theme_engine .'_'. $hook; - $default_function = '_'. $theme_engine .'_default'; - if (function_exists($hook_function)) { - return call_user_func($hook_function, $variables, $suggestions); - } - elseif (function_exists($default_function)) { - return call_user_func($default_function, $hook, $variables, $suggestions); - } - -} - -/** * Adds additional helper variables to all templates. * * Counts how many times certain hooks have been called. Sidebar left / right are special cases. @@ -92,66 +104,29 @@ function _phptemplate_callback($hook, $v * @param $variables * A sequential array of variables passed to the theme function. */ -function _phptemplate_default_variables($hook, $variables) { +function phptemplate_engine_variables(&$variables, $hook) { global $theme, $sidebar_indicator; static $count = array(); + // Create variables so anything which is themed can be zebra striped automatically. $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1; $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even'; $variables['id'] = $count[$hook]++; - if ($hook == 'block') { - $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1; - $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even'; - $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++; - } - elseif ($hook == 'page') { - $regions = system_region_list($theme); - // Load all region content assigned via blocks. - foreach (array_keys($regions) as $region) { - // Skip blocks in this region that have already been loaded. - // This pre-loading is necessary because phptemplate uses variable names different from - // the region names, e.g., 'sidebar_left' instead of 'left'. - if (!in_array($region, array('left', 'right', 'footer'))) { - isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region); - } - } - } // Tell all templates where they are located. $variables['directory'] = path_to_theme(); $variables['is_front'] = drupal_is_front_page(); - - return $variables; } /** - * @return - * Array of template features - */ -function phptemplate_features() { - return array( - 'toggle_logo', - 'toggle_comment_user_picture', - 'toggle_favicon', - 'toggle_mission', - 'toggle_name', - 'toggle_node_user_picture', - 'toggle_search', - 'toggle_slogan' - ); -} - -/** - * Prepare the values passed to the theme_page function to be passed - * into a pluggable template engine. Uses the arg() function to - * generate a series of page template files suggestions based on the - * current path. If none are found, the default page.tpl.php is used. + * Prepare the variables passed to the page.tpl.php template Uses the arg() + * function to generate a series of page template files suggestions based on + * the current path. */ -function phptemplate_page($content, $show_blocks = TRUE) { - +function phptemplate_engine_variables_page(&$variables) { /* Set title and breadcrumb to declared values */ if (drupal_is_front_page()) { - $mission = filter_xss_admin(theme_get_setting('mission')); + $variables['mission'] = filter_xss_admin(theme_get_setting('mission')); } /* Add favicon */ @@ -159,26 +134,44 @@ function phptemplate_page($content, $sho drupal_set_html_head(''); } - // Populate sidebars + /** + * Populate sidebars. + */ + $variables['sidebar_left'] = NULL; + $variables['sidebar_right'] = NULL; $layout = 'none'; - if ($show_blocks) { + if ($variables['show_blocks']) { global $sidebar_indicator; /** * Sidebar_indicator tells the block counting code to count sidebars separately. */ $sidebar_indicator = 'left'; - $sidebar_left = theme('blocks', 'left'); - if ($sidebar_left != '') { + $variables['sidebar_left'] = theme('blocks', 'left'); + if ($variables['sidebar_left'] != '') { $layout = 'left'; } $sidebar_indicator = 'right'; - $sidebar_right = theme('blocks', 'right'); - if ($sidebar_right != '') { - $layout = ($layout == 'left') ? 'both' : 'right'; + $variables['sidebar_right'] = theme('blocks', 'right'); + if ($variables['sidebar_right'] != '') { + $variables['layout'] = ($layout == 'left') ? 'both' : 'right'; } $sidebar_indicator = NULL; } + $variables['layout'] = $layout; + + global $theme; + // Populate the rest of the regions. + $regions = system_region_list($theme); + // Load all region content assigned via blocks. + foreach (array_keys($regions) as $region) { + // Skip blocks in this region that have already been loaded. + // This pre-loading is necessary because phptemplate uses variable names different from + // the region names, e.g., 'sidebar_left' instead of 'left'. + if (!in_array($region, array('left', 'right', 'footer'))) { + isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region); + } + } // Construct page title if (drupal_get_title()) { @@ -190,35 +183,28 @@ function phptemplate_page($content, $sho $head_title[] = variable_get('site_slogan', ''); } } - - $variables = array( - 'base_path' => base_path(), - 'breadcrumb' => theme('breadcrumb', drupal_get_breadcrumb()), - 'closure' => theme('closure'), - 'content' => $content, - 'feed_icons' => drupal_get_feeds(), - 'footer_message' => filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'), - 'head' => drupal_get_html_head(), - 'head_title' => implode(' | ', $head_title), - 'help' => theme('help'), - 'language' => $GLOBALS['language'], - 'layout' => isset($layout) ? $layout : NULL, - 'logo' => theme_get_setting('logo'), - 'messages' => theme('status_messages'), - 'mission' => isset($mission) ? $mission : '', - 'primary_links' => menu_primary_links(), - 'search_box' => (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''), - 'secondary_links' => menu_secondary_links(), - 'sidebar_left' => !empty($sidebar_left) ? $sidebar_left : '', - 'sidebar_right' => !empty($sidebar_right) ? $sidebar_right : '', - 'site_name' => (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''), - 'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''), - 'css' => drupal_add_css(), - 'styles' => drupal_get_css(), - 'scripts' => drupal_get_js(), - 'tabs' => theme('menu_local_tasks'), - 'title' => drupal_get_title() - ); + $variables['head_title'] = implode(' | ', $head_title); + $variables['base_path'] = base_path(); + $variables['breadcrumb'] = theme('breadcrumb', drupal_get_breadcrumb()); + $variables['closure'] = theme('closure'); + $variables['feed_icons'] = drupal_get_feeds(); + $variables['footer_message'] = filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'); + $variables['head'] = drupal_get_html_head(); + $variables['help'] = theme('help'); + $variables['language'] = $GLOBALS['language']; + $variables['logo'] = theme_get_setting('logo'); + $variables['messages'] = theme('status_messages'); + $variables['mission'] = isset($mission) ? $mission : ''; + $variables['primary_links'] = menu_primary_links(); + $variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''); + $variables['secondary_links'] = menu_secondary_links(); + $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''); + $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''); + $variables['css'] = drupal_add_css(); + $variables['styles'] = drupal_get_css(); + $variables['scripts'] = drupal_get_js(); + $variables['tabs'] = theme('menu_local_tasks'); + $variables['title'] = drupal_get_title(); if ((arg(0) == 'node') && is_numeric(arg(1))) { $variables['node'] = node_load(arg(1)); @@ -236,7 +222,7 @@ function phptemplate_page($content, $sho // page.tpl.php $i = 0; $suggestion = 'page'; - $suggestions = array($suggestion); + $suggestions = array(); while ($arg = arg($i++)) { $suggestions[] = $suggestion . '-' . $arg; if (!is_numeric($arg)) { @@ -247,43 +233,40 @@ function phptemplate_page($content, $sho $suggestions[] = 'page-front'; } - return _phptemplate_callback('page', $variables, $suggestions); + if ($suggestions) { + $variables['template_files'] = $suggestions; + } } /* * Prepare the values passed to the theme_node function to be passed - * into a pluggable template engine. + * into standard template files. */ -function phptemplate_node($node, $teaser = 0, $page = 0) { +function phptemplate_engine_variables_node(&$variables) { + $node = $variables['node']; if (module_exists('taxonomy')) { - $taxonomy = taxonomy_link('taxonomy terms', $node); + $variables['taxonomy'] = taxonomy_link('taxonomy terms', $node); } else { - $taxonomy = array(); + $variables['taxonomy'] = array(); } - if ($teaser && $node->teaser) { - $content = $node->teaser; + + if ($variables['teaser'] && $node->teaser) { + $variables['content'] = $node->teaser; } elseif (isset($node->body)) { - $content = $node->body; + $variables['content'] = $node->body; } else { - $content = ''; + $variables['content'] = ''; } - $variables = array( - 'content' => $content, - 'date' => format_date($node->created), - 'links' => !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : '', - 'name' => theme('username', $node), - 'node' => $node, // we pass the actual node to allow more customization - 'node_url' => url('node/'. $node->nid), - 'page' => $page, - 'taxonomy' => $taxonomy, - 'teaser' => $teaser, - 'terms' => theme('links', $taxonomy, array('class' => 'links inline')), - 'title' => check_plain($node->title) - ); + $variables['date'] = format_date($node->created); + $variables['links'] = !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : ''; + $variables['name'] = theme('username', $node); + $variables['node_url'] = url('node/'. $node->nid); + $variables['terms'] = theme('links', $variables['taxonomy'], array('class' => 'links inline')); + $variables['title'] = check_plain($node->title); // Flatten the node object's member fields. $variables = array_merge((array)$node, $variables); @@ -298,28 +281,28 @@ function phptemplate_node($node, $teaser $variables['picture'] = ''; } - return _phptemplate_callback('node', $variables, array('node-' . $node->type)); + $variables['template_files'][] = 'node-'. $node->type; } /** * Prepare the values passed to the theme_comment function to be passed * into a pluggable template engine. */ -function phptemplate_comment($comment, $links = 0) { - return _phptemplate_callback('comment', array( - 'author' => theme('username', $comment), - 'comment' => $comment, - 'content' => $comment->comment, - 'date' => format_date($comment->timestamp), - 'links' => isset($links) ? theme('links', $links) : '', - 'new' => $comment->new ? t('new') : '', - 'signature' => $comment->signature, - 'picture' => theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '', - 'submitted' => t('Submitted by !a on @b.', +// function phptemplate_comment($comment, $links = 0) { +function phptemplate_engine_variables_comment(&$variables) { + $comment = $variables['comment']; + $variables['author'] = theme('username', $comment); + $variables['comment'] = $comment; + $variables['content'] = $comment->comment; + $variables['date'] = format_date($comment->timestamp); + $variables['links'] = isset($variables['links']) ? theme('links', $variables['links']) : ''; + $variables['new'] = $comment->new ? t('new') : ''; + $variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : ''; + $variables['signature'] = $comment->signature; + $variables['submitted'] = t('Submitted by !a on @b.', array('!a' => theme('username', $comment), - '@b' => format_date($comment->timestamp))), - 'title' => l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid")) - )); + '@b' => format_date($comment->timestamp))); + $variables['title'] = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid")); } /** @@ -328,82 +311,14 @@ function phptemplate_comment($comment, $ * series of template file suggestions. If none are found, the default * block.tpl.php is used. */ -function phptemplate_block($block) { - $suggestions[] = 'block'; - $suggestions[] = 'block-' . $block->region; - $suggestions[] = 'block-' . $block->module; - $suggestions[] = 'block-' . $block->module . '-' . $block->delta; - - return _phptemplate_callback('block', array('block' => $block), $suggestions); +function phptemplate_engine_variables_block(&$variables) { + global $sidebar_indicator; + $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1; + + $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even'; + + $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++; + $variables['template_files'][] = 'block-' . $variables['block']->region; + $variables['template_files'][] = 'block-' . $variables['block']->module; + $variables['template_files'][] = 'block-' . $variables['block']->module .'-'. $variables['block']->delta; } - -/** - * Prepare the values passed to the theme_box function to be passed - * into a pluggable template engine. - */ -function phptemplate_box($title, $content, $region = 'main') { - return _phptemplate_callback('box', array( - 'content' => $content, - 'region' => $region, - 'title' => $title - )); -} - -/** - * Default callback for PHPTemplate. - * - * Load a template file, and pass the variable array to it. - * If the suggested file is not found, PHPTemplate will attempt to use - * a $hook.tpl.php file in the template directory, and failing that a - * $hook.tpl.php in the PHPTemplate directory. - * - * @param $hook - * The name of the theme function being executed. - * @param $variables - * A sequential array of variables passed to the theme function. - * @param $suggestions - * An array of suggested template files to use. - */ -function _phptemplate_default($hook, $variables, $suggestions = array(), $extension = '.tpl.php') { - global $theme_engine; - - // Loop through any suggestions in FIFO order. - $suggestions = array_reverse($suggestions); - foreach ($suggestions as $suggestion) { - if (!empty($suggestion) && file_exists(path_to_theme() .'/'. $suggestion . $extension)) { - $file = path_to_theme() .'/'. $suggestion . $extension; - break; - } - } - - if (!isset($file)) { - if (file_exists(path_to_theme() ."/$hook$extension")) { - $file = path_to_theme() ."/$hook$extension"; - } - else { - if (in_array($hook, array('node', 'block', 'box', 'comment'))) { - $file = path_to_engine() .'/'. $hook . $extension; - } - else { - $variables['hook'] = $hook; - watchdog('error', t('%engine.engine was instructed to override the %name theme function, but no valid template file was found.', array('%engine' => $theme_engine, '%name' => $hook))); - $file = path_to_engine() .'/default'. $extension; - } - } - } - - if (isset($file)) { - return call_user_func('_'. $theme_engine .'_render', $file, $variables); - } -} - -function _phptemplate_render($file, $variables) { - extract($variables, EXTR_SKIP); // Extract the variables to a local namespace - ob_start(); // Start output buffering - include "./$file"; // Include the file - $contents = ob_get_contents(); // Get the contents of the buffer - ob_end_clean(); // End buffering and discard - return $contents; // Return the contents -} - -?> diff -urNp ../drupal-themeswo/themes/garland/template.php ./themes/garland/template.php --- ../drupal-themeswo/themes/garland/template.php 2007-03-20 12:07:55.000000000 -0700 +++ ./themes/garland/template.php 2007-03-31 12:13:22.000000000 -0700 @@ -1,4 +1,6 @@ '; - $output .= "\n"; - $vars['tabs2'] = $output; - } +function phptemplate_variables_page(&$vars) { + if ($secondary = menu_secondary_local_tasks()) { + $output = ''; + $output .= "\n"; + $vars['tabs2'] = $output; + } - // Hook into color.module - if (module_exists('color')) { - _color_page_alter($vars); - } - return $vars; + // Hook into color.module + if (module_exists('color')) { + _color_page_alter($vars); } - return array(); } /**