Newer
Older
Dries Buytaert
committed
// $Id$
* The theme system, which controls the output of Drupal.
*
* The theme system allows for nearly all output of the Drupal system to be
* customized by user themes.
*
Dries Buytaert
committed
/**
* @name Content markers
* @{
* Markers used by theme_mark() and node_mark() to designate content.
* @see theme_mark(), node_mark()
*/
define('MARK_READ', 0);
define('MARK_NEW', 1);
define('MARK_UPDATED', 2);
/**
* @} End of "Content markers".
*/
Dries Buytaert
committed
global $theme, $user, $custom_theme, $theme_engine, $theme_key;
// If $theme is already set, assume the others are set, too, and do nothing
if (isset($theme)) {
return;
}
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
// Only select the user selected theme if it is available in the
// list of enabled themes.
Dries Buytaert
committed
$theme = !empty($user->theme) && $themes[$user->theme]->status ? $user->theme : variable_get('theme_default', 'garland');
// Allow modules to override the present theme... only select custom theme
Steven Wittens
committed
$theme = $custom_theme && $themes[$custom_theme] ? $custom_theme : $theme;
// Store the identifier for retrieving theme settings with.
$theme_key = $theme;
Dries Buytaert
committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Find all our ancestor themes and put them in an array.
$base_theme = array();
$ancestor = $theme;
while ($ancestor && isset($themes[$ancestor]->base_theme)) {
if (isset($themes[$themes[$ancestor]->base_theme])) {
$base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme];
// stop if this is final ancestor.
if (!isset($new_base_theme->base_theme)) {
break;
}
$ancestor = $new_base_theme->base_theme;
}
// stop if ancestor didn't exist.
else {
break;
}
}
_init_theme($themes[$theme], array_reverse($base_theme));
}
/**
* Initialize the theme system given already loaded information. This
* function is useful to initialize a theme when no database is present.
*
* @param $theme
* An object with the following information:
* filename
* The .info file for this theme. The 'path' to
* the theme will be in this file's directory. (Required)
* owner
* The path to the .theme file or the .engine file to load for
* the theme. (Required)
* stylesheet
* The primary stylesheet for the theme. (Optional)
* engine
* The name of theme engine to use. (Optional)
* @param $base_theme
* An optional array of objects that represent the 'base theme' if the
* theme is meant to be derivative of another theme. It requires
* the same information as the $theme object. It should be in
* 'oldest first' order, meaning the top level of the chain will
* be first.
*/
function _init_theme($theme, $base_theme = array()) {
global $theme_info, $base_theme_info, $theme_engine, $theme_path;
$theme_info = $theme;
$base_theme_info = $base_theme;
$theme_path = dirname($theme->filename);
Gábor Hojtsy
committed
// Add stylesheets used by this theme.
if (!empty($theme->stylesheets)) {
foreach ($theme->stylesheets as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet) {
drupal_add_css($stylesheet, 'theme', $media);
Dries Buytaert
committed
}
Gábor Hojtsy
committed
// Add scripts used by this theme.
if (!empty($theme->scripts)) {
foreach ($theme->scripts as $script) {
drupal_add_js($script, 'theme');
Gábor Hojtsy
committed
}
}
Dries Buytaert
committed
$theme_engine = NULL;
// Initialize the theme.
if (isset($theme->engine)) {
// Include the engine.
include_once './'. $theme->owner;
$theme_engine = $theme->engine;
Dries Buytaert
committed
foreach ($base_theme as $base) {
call_user_func($theme_engine .'_init', $base);
}
call_user_func($theme_engine .'_init', $theme);
}
}
else {
// include non-engine theme files
foreach ($base_theme as $base) {
// Include the theme file or the engine.
if (!empty($base->owner)) {
include_once './'. $base->owner;
}
}
// and our theme gets one too.
if (!empty($theme->owner)) {
include_once './'. $theme->owner;
Dries Buytaert
committed
_theme_load_registry($theme, $base_theme, $theme_engine);
Dries Buytaert
committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/**
* 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.
Dries Buytaert
committed
*
* @param $theme
* The loaded $theme object.
* @param $base_theme
* An array of loaded $theme objects representing the ancestor themes in
* oldest first order.
* @param theme_engine
* The name of the theme engine.
Dries Buytaert
committed
*/
Dries Buytaert
committed
function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL) {
// Check the theme registry cache; if it exists, use it.
$cache = cache_get("theme_registry:$theme->name", 'cache');
Dries Buytaert
committed
if (isset($cache->data)) {
Dries Buytaert
committed
$registry = $cache->data;
Dries Buytaert
committed
}
else {
Dries Buytaert
committed
// If not, build one and cache it.
$registry = _theme_build_registry($theme, $base_theme, $theme_engine);
Dries Buytaert
committed
_theme_save_registry($theme, $registry);
}
_theme_set_registry($registry);
}
/**
* Write the theme_registry cache into the database.
*/
function _theme_save_registry($theme, $registry) {
Dries Buytaert
committed
cache_set("theme_registry:$theme->name", $registry);
Dries Buytaert
committed
}
/**
* Force the system to rebuild the theme registry; this should be called
* when modules are added to the system, or when a dynamic system needs
* to add more theme hooks.
*/
function drupal_rebuild_theme_registry() {
cache_clear_all('theme_registry', 'cache', TRUE);
}
/**
Dries Buytaert
committed
* Process a single invocation of the theme hook. $type will be one
* of 'module', 'theme_engine' or 'theme' and it tells us some
* important information.
*
* Because $cache is a reference, the cache will be continually
* expanded upon; new entries will replace old entries in the
* array_merge, but we are careful to ensure some data is carried
* forward, such as the arguments a theme hook needs.
Dries Buytaert
committed
*/
Dries Buytaert
committed
function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
Dries Buytaert
committed
$function = $name .'_theme';
if (function_exists($function)) {
Dries Buytaert
committed
$result = $function($cache, $type, $theme, $path);
Dries Buytaert
committed
foreach ($result as $hook => $info) {
$result[$hook]['type'] = $type;
Dries Buytaert
committed
$result[$hook]['theme path'] = $path;
Dries Buytaert
committed
// if function and file are left out, default to standard naming
// conventions.
if (!isset($info['template']) && !isset($info['function'])) {
Dries Buytaert
committed
$result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name .'_') . $hook;
}
Dries Buytaert
committed
// If a path is set in the info, use what was set. Otherwise use the
// default path. This is mostly so system.module can declare theme
// functions on behalf of core .include files.
// All files are included to be safe. Conditionally included
// files can prevent them from getting registered.
Dries Buytaert
committed
if (isset($info['file']) && !isset($info['path'])) {
$result[$hook]['file'] = $path .'/'. $info['file'];
include_once($result[$hook]['file']);
}
elseif (isset($info['file']) && isset($info['path'])) {
include_once($info['path'] .'/'. $info['file']);
}
if (isset($info['template']) && !isset($info['path'])) {
$result[$hook]['template'] = $path .'/'. $info['template'];
Dries Buytaert
committed
}
// 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'];
}
Dries Buytaert
committed
// Check for default _preprocess_ functions. Ensure arrayness.
if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
$info['preprocess functions'] = array();
$prefix = ($type == 'module' ? 'template' : $name);
Dries Buytaert
committed
// theme engines get an extra set that come before the normally named preprocess.
Dries Buytaert
committed
if ($type == 'theme_engine') {
if (function_exists($prefix .'_engine_preprocess')) {
$info['preprocess functions'][] = $prefix .'_engine_preprocess';
}
if (function_exists($prefix .'_engine_preprocess_'. $hook)) {
$info['preprocess functions'][] = $prefix .'_engine_preprocess_'. $hook;
}
}
Dries Buytaert
committed
// It would be too much of a performance hit to let every module have
// a generic preprocess function; themes and theme engines can do that.
if ($type != 'module' && function_exists($prefix .'_preprocess')) {
$info['preprocess functions'][] = $prefix .'_preprocess';
}
if (function_exists($prefix .'_preprocess_'. $hook)) {
$info['preprocess functions'][] = $prefix .'_preprocess_'. $hook;
}
Dries Buytaert
committed
}
if (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions']) && empty($cache[$hook]['override preprocess functions'])) {
$info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']);
}
$result[$hook]['preprocess functions'] = $info['preprocess functions'];
Dries Buytaert
committed
}
Dries Buytaert
committed
// Merge the newly created theme hooks into the existing cache.
Dries Buytaert
committed
$cache = array_merge($cache, $result);
}
}
/**
* Rebuild the hook theme_registry cache.
Dries Buytaert
committed
*
* @param $theme
* The loaded $theme object.
* @param $base_theme
* An array of loaded $theme objects representing the ancestor themes in
* oldest first order.
* @param theme_engine
* The name of the theme engine.
Dries Buytaert
committed
*/
Dries Buytaert
committed
function _theme_build_registry($theme, $base_theme, $theme_engine) {
Dries Buytaert
committed
$cache = array();
Dries Buytaert
committed
// First, process the theme hooks advertised by modules. This will
// serve as the basic registry.
Dries Buytaert
committed
foreach (module_implements('theme') as $module) {
Dries Buytaert
committed
_theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
}
// Process each base theme.
foreach ($base_theme as $base) {
// If the theme uses a theme engine, process its hooks.
$base_path = dirname($base->filename);
if ($theme_engine) {
_theme_process_registry($cache, $theme_engine, 'base_theme_engine', $base->name, $base_path);
}
_theme_process_registry($cache, $base->name, 'base_theme', $base->name, $base_path);
Dries Buytaert
committed
}
Dries Buytaert
committed
// And then the same thing, but for the theme.
Dries Buytaert
committed
if ($theme_engine) {
Dries Buytaert
committed
_theme_process_registry($cache, $theme_engine, 'theme_engine', $theme->name, dirname($theme->filename));
Dries Buytaert
committed
}
Dries Buytaert
committed
// Finally, hooks provided by the theme itself.
_theme_process_registry($cache, $theme->name, 'theme', $theme->name, dirname($theme->filename));
Dries Buytaert
committed
return $cache;
}
* Provides a list of currently available themes.
*
* @param $refresh
* Whether to reload the list of themes from the database.
* @return
* An array of the currently available themes.
function list_themes($refresh = FALSE) {
static $list = array();
Gábor Hojtsy
committed
$result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme');
while ($theme = db_fetch_object($result)) {
if (file_exists($theme->filename)) {
$theme->info = unserialize($theme->info);
Gábor Hojtsy
committed
foreach ($theme->info['stylesheets'] as $media => $stylesheets) {
foreach ($stylesheets as $stylesheet => $path) {
if (file_exists($path)) {
$theme->stylesheets[$media][$stylesheet] = $path;
}
}
Dries Buytaert
committed
}
Gábor Hojtsy
committed
foreach ($theme->info['scripts'] as $script => $path) {
if (file_exists($path)) {
$theme->scripts[$script] = $path;
}
Gábor Hojtsy
committed
}
Dries Buytaert
committed
if (isset($theme->info['engine'])) {
$theme->engine = $theme->info['engine'];
}
if (isset($theme->info['base theme'])) {
$theme->base_theme = $theme->info['base theme'];
}
$list[$theme->name] = $theme;
}
}
}
return $list;
}
/**
* Provides a list of currently available theme engines
*
* @param $refresh
* Whether to reload the list of themes from the database.
* @return
* An array of the currently available theme engines.
*/
function list_theme_engines($refresh = FALSE) {
static $list;
if ($refresh) {
unset($list);
}
if (!$list) {
$list = array();
Gábor Hojtsy
committed
$result = db_query("SELECT * FROM {system} WHERE type = '%s' AND status = %d ORDER BY name", 'theme_engine', '1');
while ($engine = db_fetch_object($result)) {
if (file_exists($engine->filename)) {
$engine->info = unserialize($engine->info);
$list[$engine->name] = $engine;
}
}
}
return $list;
}
Dries Buytaert
committed
* Generate the themed 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.
Dries Buytaert
committed
* 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:
Dries Buytaert
committed
* ENGINE_engine_preprocess(&$variables)
* This function should only be implemented by theme engines and exists
Dries Buytaert
committed
* so that the theme engine can set necessary variables. It is commonly
* used to set global variables such as $directory and $is_front_page.
Dries Buytaert
committed
*
Dries Buytaert
committed
* ENGINE_engine_preprocess_HOOK(&$variables)
Dries Buytaert
committed
* This is the same as the previous function, but is called only per hook.
Dries Buytaert
committed
*
Dries Buytaert
committed
* ENGINE_preprocess_HOOK(&$variables)
Dries Buytaert
committed
*
Dries Buytaert
committed
* ENGINE_preprocess(&$variables)
Dries Buytaert
committed
* 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
Dries Buytaert
committed
*
Dries Buytaert
committed
* THEME_preprocess_HOOK(&$variables)
Dries Buytaert
committed
*
Dries Buytaert
committed
* THEME_preprocess(&$variables)
Dries Buytaert
committed
* 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.
Dries Buytaert
committed
*
Dries Buytaert
committed
* 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.
Dries Buytaert
committed
*
Dries Buytaert
committed
* template_preprocess_HOOK(&$variables)
* This is the same as the previous function, but is called only per hook.
Dries Buytaert
committed
* There are two special variables that these hooks can set:
* 'template_file' and 'template_files'. These will be merged together
* to form a list of 'suggested' alternate template files to use, in
* reverse order of priority. template_file will always be a higher
* priority than items in template_files. theme() will then look for these
* files, one at a time, and use the first one
* that exists.
* @param $hook
Dries Buytaert
committed
* 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
* An HTML string that generates the themed output.
$args = func_get_args();
Dries Buytaert
committed
$hook = array_shift($args);
Dries Buytaert
committed
static $hooks = NULL;
if (!isset($hooks)) {
init_theme();
$hooks = theme_get_registry();
}
Dries Buytaert
committed
Dries Buytaert
committed
if (is_array($hook)) {
foreach ($hook as $candidate) {
if (isset($hooks[$candidate])) {
break;
}
}
$hook = $candidate;
}
Dries Buytaert
committed
if (!isset($hooks[$hook])) {
return;
}
Dries Buytaert
committed
$info = $hooks[$hook];
Dries Buytaert
committed
global $theme_path;
$temp = $theme_path;
// point path_to_theme() to the currently used theme path:
$theme_path = $hooks[$hook]['theme path'];
// Include a file if the theme function or preprocess function is held elsewhere.
if (!empty($info['file'])) {
$include_file = $info['file'];
if (isset($info['path'])) {
$include_file = $info['path'] .'/'. $include_file;
}
include_once($include_file);
}
Dries Buytaert
committed
if (isset($info['function'])) {
// The theme call is a function.
Dries Buytaert
committed
$output = call_user_func_array($info['function'], $args);
Dries Buytaert
committed
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++;
}
}
Dries Buytaert
committed
// default render function and extension.
$render_function = 'theme_render_template';
$extension = '.tpl.php';
// Run through the theme engine variables, if necessary
global $theme_engine;
if (isset($theme_engine)) {
// 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();
}
}
}
Dries Buytaert
committed
if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) {
// This construct ensures that we can keep a reference through
// call_user_func_array.
$args = array(&$variables, $hook);
foreach ($info['preprocess functions'] as $preprocess_function) {
if (function_exists($preprocess_function)) {
call_user_func_array($preprocess_function, $args);
}
Dries Buytaert
committed
}
}
// 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]['template'] . $extension;
Dries Buytaert
committed
if (isset($hooks[$hook]['path'])) {
$template_file = $hooks[$hook]['path'] .'/'. $template_file;
}
}
Dries Buytaert
committed
$output = $render_function($template_file, $variables);
Dries Buytaert
committed
// restore path_to_theme()
$theme_path = $temp;
return $output;
Dries Buytaert
committed
}
/**
* Choose which template file to actually render; these are all
* suggested templates from the theme.
*/
function drupal_discover_template($suggestions, $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($file = path_to_theme() .'/'. $suggestion . $extension)) {
return $file;
}
* Return the path to the currently selected theme.
Dries Buytaert
committed
global $theme_path;
Dries Buytaert
committed
if (!isset($theme_path)) {
init_theme();
}
Dries Buytaert
committed
return $theme_path;
}
Dries Buytaert
committed
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
/**
* 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, '.'));
// Transform - in filenames to _ to match function naming scheme
// for the purposes of searching.
$hook = strtr($template, '-', '_');
if (isset($cache[$hook])) {
$templates[$hook] = array(
'template' => $template,
Dries Buytaert
committed
'path' => dirname($file->filename),
);
}
}
$patterns = array_keys($files);
foreach ($cache as $hook => $info) {
if (!empty($info['pattern'])) {
// Transform _ in pattern to - to match file naming scheme
// for the purposes of searching.
$pattern = strtr($info['pattern'], '_', '-');
$matches = preg_grep('/^'. $pattern .'/', $patterns);
Dries Buytaert
committed
if ($matches) {
foreach ($matches as $match) {
$file = substr($match, 0, strpos($match, '.'));
// Put the underscores back in for the hook name and register this pattern.
$templates[strtr($file, '-', '_')] = array(
'template' => $file,
Dries Buytaert
committed
'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,
* the site-wide settings, and the settings defined for the specific theme.
* If no $key was specified, only the site-wide theme defaults are retrieved.
*
* The default values for each of settings are also defined in this function.
* To add new settings, add their default values here, and then add form elements
* to system_theme_settings() in system.module.
*
* @param $key
* The template/style value for a given theme.
*
* @return
* An associative array containing theme settings.
*/
Steven Wittens
committed
function theme_get_settings($key = NULL) {
$defaults = array(
'mission' => '',
'default_logo' => 1,
'logo_path' => '',
'default_favicon' => 1,
'favicon_path' => '',
Gábor Hojtsy
committed
'primary_links' => 1,
'secondary_links' => 1,
'toggle_favicon' => 1,
'toggle_name' => 1,
'toggle_search' => 1,
'toggle_slogan' => 0,
'toggle_mission' => 1,
'toggle_node_user_picture' => 0,
'toggle_comment_user_picture' => 0,
Gábor Hojtsy
committed
'toggle_primary_links' => 1,
'toggle_secondary_links' => 1,
Neil Drumm
committed
foreach (node_get_types() as $type => $name) {
Dries Buytaert
committed
$defaults['toggle_node_info_'. $type] = 1;
}
$settings = array_merge($defaults, variable_get('theme_settings', array()));
if ($key) {
$settings = array_merge($settings, variable_get(str_replace('/', '_', 'theme_'. $key .'_settings'), array()));
}
// Only offer search box if search.module is enabled.
if (!module_exists('search') || !user_access('search content')) {
$settings['toggle_search'] = 0;
}
return $settings;
}
/**
* Retrieve a setting for the current theme.
* This function is designed for use from within themes & engines
* to determine theme settings made in the admin interface.
*
* Caches values for speed (use $refresh = TRUE to refresh cache)
*
* @param $setting_name
* The name of the setting to be retrieved.
*
* @param $refresh
* Whether to reload the cache of settings.
*
* @return
* The value of the requested setting, NULL if the setting does not exist.
*/
Steven Wittens
committed
function theme_get_setting($setting_name, $refresh = FALSE) {
Steven Wittens
committed
$settings = theme_get_settings($theme_key);
$themes = list_themes();
$theme_object = $themes[$theme_key];
if ($settings['mission'] == '') {
$settings['mission'] = variable_get('site_mission', '');
}
if (!$settings['toggle_mission']) {
$settings['mission'] = '';
}
if ($settings['toggle_logo']) {
if ($settings['default_logo']) {
$settings['logo'] = base_path() . dirname($theme_object->filename) .'/logo.png';
$settings['logo'] = base_path() . $settings['logo_path'];
if ($settings['toggle_favicon']) {
if ($settings['default_favicon']) {
if (file_exists($favicon = dirname($theme_object->filename) .'/favicon.ico')) {
$settings['favicon'] = base_path() . $favicon;
}
else {
Dries Buytaert
committed
$settings['favicon'] = base_path() .'misc/favicon.ico';
}
}
elseif ($settings['favicon_path']) {
$settings['favicon'] = base_path() . $settings['favicon_path'];
Dries Buytaert
committed
else {
$settings['toggle_favicon'] = FALSE;
}
}
return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL;
}
Dries Buytaert
committed
* 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
Dries Buytaert
committed
* Functions and templates that present output to the user, and can be
* implemented by themes.
*
* 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.
Dries Buytaert
committed
* 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);
Dries Buytaert
committed
* 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.
Dries Buytaert
committed
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
*
* 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_theme(), 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_theme(). 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.
*
* In order to create theme-specific implementations of these hooks,
* themes can implement their own version of theme hooks, either as functions
* or templates. These implementations will be used instead of the default
* implementation. If using a pure .theme without an engine, the .theme is
* required to implement its own version of hook_theme() 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).
Dries Buytaert
committed
*
* @see theme()
* @see hook_theme()
Dries Buytaert
committed
* Formats text for emphasized display in a placeholder inside a sentence.
* Used automatically by t().
*
* @param $text
* The text to format (plain-text).
* @return
* The formatted text (html).
*/
function theme_placeholder($text) {
return '<em>'. check_plain($text) .'</em>';
}
Steven Wittens
committed
/**
* Generate a themed maintenance page.
*
* Note: this function is not themeable.
Steven Wittens
committed
*
* @param $content
* The page content to show.
* @param $show_messages
Steven Wittens
committed
* Whether to output status and error messages.
* FALSE can be useful to postpone the messages to a subsequent page.
Steven Wittens
committed
*/
function theme_maintenance_page($content, $show_messages = TRUE) {
Steven Wittens
committed
// Set required headers.
drupal_set_header('Content-Type: text/html; charset=utf-8');
Dries Buytaert
committed
drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() .'misc/maintenance.css" />');
drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() . drupal_get_path('module', 'system') .'/defaults.css" />');
drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. base_path() . drupal_get_path('module', 'system') .'/system.css" />');
drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
Steven Wittens
committed
// Prepare variables.
$variables = array(
'head_title' => strip_tags(drupal_get_title()),
'head' => drupal_get_html_head(),
'styles' => '',
'scripts' => drupal_get_js(),
'sidebar_left' => drupal_get_content('left'),
'sidebar_right' => drupal_get_content('right'),
'base_path' => base_path(),
'path_to_theme' => base_path() .'themes/garland/minnelli',
'logo' => base_path() .'themes/garland/minnelli/logo.png',
'site_title' => t('Drupal'),
'title' => drupal_get_title(),
'messages' => $show_messages ? theme('status_messages') : '',
Steven Wittens
committed
'content' => $content,
);
Dries Buytaert
committed
$output = theme_render_template('misc/maintenance.tpl.php', $variables);
Steven Wittens
committed
/**
* Generate a themed installation page.
*
* Note: this function is not themeable.
Steven Wittens
committed
*
* @param $content
* The page content to show.
*/
Dries Buytaert
committed
function theme_install_page($content) {
drupal_set_header('Content-Type: text/html; charset=utf-8');
Steven Wittens
committed
drupal_add_css('misc/maintenance.css', 'module', 'all', FALSE);
Dries Buytaert
committed
drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
Steven Wittens
committed
$variables = array(
'head_title' => strip_tags(drupal_get_title()),
'head' => drupal_get_html_head(),
'styles' => drupal_get_css(),
'scripts' => drupal_get_js(),