summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2007-07-03 18:48:41 +0000
committerDries Buytaert <dries@buytaert.net>2007-07-03 18:48:41 +0000
commit435f3154f9c347f35a4685d6456b9aded4171bc2 (patch)
tree2b12de72d697709b9904765313a242e1a71ba162
parentb5cdf535f4a233cd4156e6c091e6aa1f3f28800a (diff)
downloadbrdo-435f3154f9c347f35a4685d6456b9aded4171bc2.tar.gz
brdo-435f3154f9c347f35a4685d6456b9aded4171bc2.tar.bz2
- Patch #141730 by Earl: allow theming system to use wildcards. I promised in the issue that this patch would still go in, so here goes.
-rw-r--r--CHANGELOG.txt1
-rw-r--r--includes/theme.inc125
-rw-r--r--themes/chameleon/chameleon.theme11
-rw-r--r--themes/engines/phptemplate/phptemplate.engine32
4 files changed, 127 insertions, 42 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 6674295e8..f512f69ee 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -62,7 +62,6 @@ Drupal 6.0, xxxx-xx-xx (development version)
- Added support for OpenID.
- Added support for configurable actions.
- Made user profiles easier to theme by using array rendering and supplying template files.
-- Added Deletion API to allow modules to alter and respond to any delete operation.
Drupal 5.0, 2007-01-15
----------------------
diff --git a/includes/theme.inc b/includes/theme.inc
index e8c0a8832..d53f4d840 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -416,24 +416,31 @@ function list_theme_engines($refresh = FALSE) {
* This function should only be implemented by theme engines and 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_preprocess_HOOK(&$variables)
* This is the same as the previous function, but is called only per hook.
+ *
* ENGINE_preprocess_HOOK(&$variables)
+ *
* ENGINE_preprocess(&$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_preprocess_HOOK(&$variables)
+ *
* THEME_preprocess(&$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.
+ *
* template_preprocess(&$variables)
* This function will only be called for theme functions registered by
* the named module. In general it is preferred to use the following
* function if possible, but it may not always be the case.
+ *
* template_preprocess_HOOK(&$variables)
* This is the same as the previous function, but is called only per hook.
*
@@ -445,7 +452,12 @@ function list_theme_engines($refresh = FALSE) {
* files, one at a time, and use the first one
* that exists.
* @param $hook
- * The name of the theme function to call.
+ * The name of the theme function to call. May be an array, in which
+ * case the first hook that actually has an implementation registered
+ * will be used. This can be used to choose 'fallback' theme implementations,
+ * so that if the specific theme hook isn't implemented anywhere, a more
+ * generic one will be used. This can allow themes to create specific theme
+ * implementations for named objects.
* @param ...
* Additional arguments to pass along to the theme function.
* @return
@@ -461,6 +473,15 @@ function theme() {
$hooks = theme_get_registry();
}
+ if (is_array($hook)) {
+ foreach ($hook as $candidate) {
+ if (isset($hooks[$candidate])) {
+ break;
+ }
+ }
+ $hook = $candidate;
+ }
+
if (!isset($hooks[$hook])) {
return;
}
@@ -587,6 +608,100 @@ function path_to_theme() {
}
/**
+ * Find overridden theme functions. Called by themes and/or theme engines to
+ * easily discover theme functions.
+ *
+ * @param $cache
+ * The existing cache of theme hooks to test against.
+ * @param $prefixes
+ * An array of prefixes to test, in reverse order of importance.
+ *
+ * @return $templates
+ * The functions found, suitable for returning from hook_theme;
+ */
+function drupal_find_theme_functions($cache, $prefixes) {
+ $templates = array();
+ $functions = get_defined_functions();
+
+ foreach ($cache as $hook => $info) {
+ foreach ($prefixes as $prefix) {
+ if (!empty($info['pattern'])) {
+ $matches = preg_grep('/^'. $prefix .'_'. $info['pattern'] .'/', $functions['user']);
+ if ($matches) {
+ foreach ($matches as $match) {
+ $new_hook = str_replace($prefix . '_', '', $match);
+ $templates[$new_hook] = array(
+ 'function' => $match,
+ 'arguments' => $info['arguments'],
+ );
+ }
+ }
+ }
+ if (function_exists($prefix .'_'. $hook)) {
+ $templates[$hook] = array(
+ 'function' => $prefix .'_'. $hook,
+ );
+ }
+ }
+ }
+
+ return $templates;
+}
+
+/**
+ * Find overridden theme templates. Called by themes and/or theme engines to
+ * easily discover templates.
+ *
+ * @param $cache
+ * The existing cache of theme hooks to test against.
+ * @param $extension
+ * The extension that these templates will have.
+ * @param $path
+ * The path to search.
+ */
+function drupal_find_theme_templates($cache, $extension, $path) {
+ $templates = array();
+
+ // Escape the dots in the extension.
+ $regex = str_replace('.', '\.', $extension) . '$';
+
+ // Because drupal_system_listing works the way it does, we check for real
+ // templates separately from checking for patterns.
+ $files = drupal_system_listing($regex, $path, 'name', 0);
+ foreach ($files as $template => $file) {
+ // Chop off the extension. We do it this way because $template will
+ // have one extension chopped off, but there might be more than one,
+ // such as with .tpl.php
+ $template = substr($template, 0, strpos($template, '.'));
+ if (isset($cache[$template])) {
+ $templates[$template] = array(
+ 'file' => $template,
+ 'path' => dirname($file->filename),
+ );
+ }
+ }
+
+ $patterns = array_keys($files);
+
+ foreach ($cache as $hook => $info) {
+ if (!empty($info['pattern'])) {
+ $matches = preg_grep('/^'. $info['pattern'] .'/', $patterns);
+ if ($matches) {
+ foreach ($matches as $match) {
+ $file = substr($match, 0, strpos($match, '.'));
+ $templates[$file] = array(
+ 'file' => $file,
+ 'path' => dirname($files[$match]->filename),
+ 'arguments' => $info['arguments'],
+ );
+ }
+ }
+ }
+ }
+ return $templates;
+}
+
+/**
* Retrieve an associative array containing the settings for a theme.
*
* The final settings are arrived at by merging the default settings,
@@ -736,6 +851,14 @@ function theme_render_template($file, $variables) {
* 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);
+ * Additionally, the theme() function can take an array of theme
+ * hooks, which can be used to provide 'fallback' implementations to
+ * allow for more specific control of output. For example, the function:
+ * theme(array('table__foo', 'table), $header, $rows) would look to see if
+ * 'table__foo' is registered anywhere; if it is not, it would 'fall back'
+ * to the generic 'table' implementation. This can be used to attach specific
+ * theme functions to named objects, allowing the themer more control over
+ * specific types of output.
*
* 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
diff --git a/themes/chameleon/chameleon.theme b/themes/chameleon/chameleon.theme
index 7433ed8ef..7ba6d71f8 100644
--- a/themes/chameleon/chameleon.theme
+++ b/themes/chameleon/chameleon.theme
@@ -10,16 +10,7 @@
* Implementation of hook_theme. Auto-discover theme functions.
*/
function chameleon_theme($existing, $type, $theme, $path) {
- $templates = array();
- // Check for function overrides.
- foreach ($existing as $hook => $info) {
- if (function_exists($theme .'_'. $hook)) {
- $templates[$hook] = array(
- 'function' => $theme .'_'. $hook,
- );
- }
- }
- return $templates;
+ return drupal_find_theme_functions($existing, array($theme));
}
function chameleon_page($content, $show_blocks = TRUE, $show_messages = TRUE) {
diff --git a/themes/engines/phptemplate/phptemplate.engine b/themes/engines/phptemplate/phptemplate.engine
index 4e9c065af..48f620838 100644
--- a/themes/engines/phptemplate/phptemplate.engine
+++ b/themes/engines/phptemplate/phptemplate.engine
@@ -20,36 +20,8 @@ function phptemplate_init($template) {
* we need to.
*/
function phptemplate_theme($existing, $type, $theme, $path) {
- $templates = array();
-
- // Check for template overrides.
- $files = drupal_system_listing('\.tpl\.php$', $path, '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.
- 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,
- );
- }
- }
-
+ $templates = drupal_find_theme_functions($existing, array('phptemplate', $theme));
+ $templates += drupal_find_theme_templates($existing, '.tpl.php', $path);
return $templates;
}