summaryrefslogtreecommitdiff
path: root/includes
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 /includes
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.
Diffstat (limited to 'includes')
-rw-r--r--includes/theme.inc125
1 files changed, 124 insertions, 1 deletions
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