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 .= '
'. theme('links', $node->links) .'
';
- }
-
- 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 .= '
'. theme('links', $node->links) .'
';
+- }
+-
+- 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 .= '
'. theme('links', $node->links) .'
';
+- }
+-
+- 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();
}
/**