2001-03-10 11:07:52 +00:00
< ? php
2005-08-11 12:57:41 +00:00
// $Id$
2003-11-26 16:17:13 +00:00
2002-04-14 19:34:04 +00:00
/**
2003-12-08 06:32:19 +00:00
* @ file
2004-07-22 16:06:54 +00:00
* The theme system , which controls the output of Drupal .
2003-12-08 06:32:19 +00:00
*
* The theme system allows for nearly all output of the Drupal system to be
* customized by user themes .
*
2004-06-18 15:04:37 +00:00
* @ see < a href = " http://drupal.org/node/253 " > Theme system </ a >
2003-12-08 06:32:19 +00:00
* @ see themeable
*/
2001-10-20 13:35:12 +00:00
2005-01-30 09:53:19 +00:00
/**
* @ 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 " .
*/
2003-11-26 16:17:13 +00:00
/**
2004-01-02 16:24:28 +00:00
* Initialize the theme system by loading the theme .
2003-12-08 06:32:19 +00:00
*/
2003-11-26 16:17:13 +00:00
function init_theme () {
2006-01-06 07:25:44 +00:00
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 ;
}
2003-11-26 16:17:13 +00:00
2005-07-23 05:57:27 +00:00
drupal_bootstrap ( DRUPAL_BOOTSTRAP_DATABASE );
2003-11-26 16:17:13 +00:00
$themes = list_themes ();
2004-07-22 16:06:54 +00:00
// Only select the user selected theme if it is available in the
// list of enabled themes.
2007-01-31 15:49:26 +00:00
$theme = ! empty ( $user -> theme ) && $themes [ $user -> theme ] -> status ? $user -> theme : variable_get ( 'theme_default' , 'garland' );
2004-08-20 07:51:27 +00:00
// Allow modules to override the present theme... only select custom theme
2005-03-16 19:41:12 +00:00
// if it is available in the list of installed themes.
2004-08-22 14:43:49 +00:00
$theme = $custom_theme && $themes [ $custom_theme ] ? $custom_theme : $theme ;
2004-08-20 07:51:27 +00:00
// Store the identifier for retrieving theme settings with.
$theme_key = $theme ;
2007-05-06 05:47:52 +00:00
// 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 );
2007-07-01 23:27:32 +00:00
// 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 );
2007-05-06 05:47:52 +00:00
}
2004-08-20 07:51:27 +00:00
}
}
2007-07-01 23:27:32 +00:00
// Add scripts used by this theme.
if ( ! empty ( $theme -> scripts )) {
foreach ( $theme -> scripts as $script ) {
drupal_add_js ( $script , 'theme' );
2007-06-08 12:51:59 +00:00
}
}
2007-05-06 05:47:52 +00:00
$theme_engine = NULL ;
// Initialize the theme.
if ( isset ( $theme -> engine )) {
// Include the engine.
include_once './' . $theme -> owner ;
$theme_engine = $theme -> engine ;
2004-08-20 07:51:27 +00:00
if ( function_exists ( $theme_engine . '_init' )) {
2007-05-06 05:47:52 +00:00
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 ;
2004-08-20 07:51:27 +00:00
}
}
2007-05-06 05:47:52 +00:00
_theme_load_registry ( $theme , $base_theme , $theme_engine );
2003-11-26 16:17:13 +00:00
}
2007-04-06 13:27:23 +00:00
/**
* 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 .
2007-05-06 05:47:52 +00:00
*
* @ 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 .
2007-04-06 13:27:23 +00:00
*/
2007-05-06 05:47:52 +00:00
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' );
2007-04-06 13:27:23 +00:00
if ( isset ( $cache -> data )) {
2007-04-25 21:34:32 +00:00
$registry = $cache -> data ;
2007-04-06 13:27:23 +00:00
}
else {
2007-05-06 05:47:52 +00:00
// If not, build one and cache it.
$registry = _theme_build_registry ( $theme , $base_theme , $theme_engine );
2007-04-06 13:27:23 +00:00
_theme_save_registry ( $theme , $registry );
}
_theme_set_registry ( $registry );
}
/**
* Write the theme_registry cache into the database .
*/
function _theme_save_registry ( $theme , $registry ) {
2007-05-06 05:47:52 +00:00
cache_set ( " theme_registry: $theme->name " , $registry );
2007-04-06 13:27:23 +00:00
}
/**
* 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 );
}
/**
2007-05-06 05:47:52 +00:00
* 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 .
2007-04-06 13:27:23 +00:00
*/
2007-05-06 05:47:52 +00:00
function _theme_process_registry ( & $cache , $name , $type , $theme , $path ) {
2007-04-06 13:27:23 +00:00
$function = $name . '_theme' ;
if ( function_exists ( $function )) {
2007-05-06 05:47:52 +00:00
$result = $function ( $cache , $type , $theme , $path );
2007-04-06 13:27:23 +00:00
foreach ( $result as $hook => $info ) {
$result [ $hook ][ 'type' ] = $type ;
2007-05-06 05:47:52 +00:00
$result [ $hook ][ 'theme path' ] = $path ;
2007-04-06 13:27:23 +00:00
// if function and file are left out, default to standard naming
// conventions.
2007-08-26 07:46:11 +00:00
if ( ! isset ( $info [ 'template' ]) && ! isset ( $info [ 'function' ])) {
2007-04-06 13:27:23 +00:00
$result [ $hook ][ 'function' ] = ( $type == 'module' ? 'theme_' : $name . '_' ) . $hook ;
}
2007-05-06 05:47:52 +00:00
// 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.
2007-08-26 07:46:11 +00:00
// All files are included to be safe. Conditionally included
// files can prevent them from getting registered.
2007-04-06 13:27:23 +00:00
if ( isset ( $info [ 'file' ]) && ! isset ( $info [ 'path' ])) {
$result [ $hook ][ 'file' ] = $path . '/' . $info [ 'file' ];
2007-08-26 07:46:11 +00:00
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' ];
2007-04-06 13:27:23 +00:00
}
// 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' ];
}
2007-08-29 16:56:13 +00:00
// Likewise with theme paths. These are used for template naming suggestions.
// Theme implementations can occur in multiple paths. Suggestions should follow.
if ( ! isset ( $info [ 'theme paths' ]) && isset ( $cache [ $hook ])) {
$result [ $hook ][ 'theme paths' ] = $cache [ $hook ][ 'theme paths' ];
}
// Check for sub-directories.
$result [ $hook ][ 'theme paths' ][] = isset ( $info [ 'path' ]) ? $info [ 'path' ] : $path ;
2007-04-27 07:42:54 +00:00
// 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 );
2007-05-06 05:47:52 +00:00
// theme engines get an extra set that come before the normally named preprocess.
2007-04-27 07:42:54 +00:00
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 ;
}
}
2007-05-06 05:47:52 +00:00
2007-09-01 05:35:15 +00:00
// Let the theme engine register theme specific variable functions.
$prefixes [] = $prefix ;
if ( $type == 'theme_engine' ) {
$prefixes [] = $theme ;
2007-05-06 05:47:52 +00:00
}
2007-09-01 05:35:15 +00:00
foreach ( $prefixes as $prefix ) {
if ( function_exists ( $prefix . '_preprocess' )) {
$info [ 'preprocess functions' ][] = $prefix . '_preprocess' ;
}
if ( function_exists ( $prefix . '_preprocess_' . $hook )) {
$info [ 'preprocess functions' ][] = $prefix . '_preprocess_' . $hook ;
}
2007-05-06 05:47:52 +00:00
}
2007-04-27 07:42:54 +00:00
}
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' ];
2007-04-06 13:27:23 +00:00
}
2007-05-06 05:47:52 +00:00
// Merge the newly created theme hooks into the existing cache.
2007-04-06 13:27:23 +00:00
$cache = array_merge ( $cache , $result );
}
}
/**
* Rebuild the hook theme_registry cache .
2007-05-06 05:47:52 +00:00
*
* @ 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 .
2007-04-06 13:27:23 +00:00
*/
2007-05-06 05:47:52 +00:00
function _theme_build_registry ( $theme , $base_theme , $theme_engine ) {
2007-04-06 13:27:23 +00:00
$cache = array ();
2007-05-06 05:47:52 +00:00
// First, process the theme hooks advertised by modules. This will
// serve as the basic registry.
2007-04-06 13:27:23 +00:00
foreach ( module_implements ( 'theme' ) as $module ) {
2007-05-06 05:47:52 +00:00
_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 );
2007-04-06 13:27:23 +00:00
}
2007-05-06 05:47:52 +00:00
// And then the same thing, but for the theme.
2007-04-06 13:27:23 +00:00
if ( $theme_engine ) {
2007-05-06 05:47:52 +00:00
_theme_process_registry ( $cache , $theme_engine , 'theme_engine' , $theme -> name , dirname ( $theme -> filename ));
2007-04-06 13:27:23 +00:00
}
2007-05-06 05:47:52 +00:00
// Finally, hooks provided by the theme itself.
_theme_process_registry ( $cache , $theme -> name , 'theme' , $theme -> name , dirname ( $theme -> filename ));
2007-04-06 13:27:23 +00:00
return $cache ;
}
2003-11-26 16:17:13 +00:00
/**
2003-12-08 06:32:19 +00:00
* Provides a list of currently available themes .
*
* @ param $refresh
2004-07-22 16:06:54 +00:00
* Whether to reload the list of themes from the database .
* @ return
* An array of the currently available themes .
2003-12-08 06:32:19 +00:00
*/
2004-07-22 16:06:54 +00:00
function list_themes ( $refresh = FALSE ) {
2007-04-06 14:31:51 +00:00
static $list = array ();
2003-11-26 16:17:13 +00:00
if ( $refresh ) {
2007-04-06 14:31:51 +00:00
$list = array ();
2003-11-26 16:17:13 +00:00
}
2007-04-06 14:31:51 +00:00
if ( empty ( $list )) {
2003-11-26 16:17:13 +00:00
$list = array ();
2007-08-22 08:36:34 +00:00
$result = db_query ( " SELECT * FROM { system} WHERE type = '%s' " , 'theme' );
2003-11-26 16:17:13 +00:00
while ( $theme = db_fetch_object ( $result )) {
if ( file_exists ( $theme -> filename )) {
2007-04-17 07:19:39 +00:00
$theme -> info = unserialize ( $theme -> info );
2007-07-01 23:27:32 +00:00
foreach ( $theme -> info [ 'stylesheets' ] as $media => $stylesheets ) {
foreach ( $stylesheets as $stylesheet => $path ) {
if ( file_exists ( $path )) {
$theme -> stylesheets [ $media ][ $stylesheet ] = $path ;
}
}
2007-05-06 05:47:52 +00:00
}
2007-07-01 23:27:32 +00:00
foreach ( $theme -> info [ 'scripts' ] as $script => $path ) {
if ( file_exists ( $path )) {
$theme -> scripts [ $script ] = $path ;
}
2007-06-08 12:51:59 +00:00
}
2007-05-06 05:47:52 +00:00
if ( isset ( $theme -> info [ 'engine' ])) {
$theme -> engine = $theme -> info [ 'engine' ];
}
if ( isset ( $theme -> info [ 'base theme' ])) {
$theme -> base_theme = $theme -> info [ 'base theme' ];
}
2003-11-26 16:17:13 +00:00
$list [ $theme -> name ] = $theme ;
}
}
}
return $list ;
}
2004-08-20 07:51:27 +00:00
/**
* 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 ();
2007-08-22 08:36:34 +00:00
$result = db_query ( " SELECT * FROM { system} WHERE type = '%s' AND status = %d ORDER BY name " , 'theme_engine' , '1' );
2004-08-20 07:51:27 +00:00
while ( $engine = db_fetch_object ( $result )) {
if ( file_exists ( $engine -> filename )) {
2007-04-17 07:19:39 +00:00
$engine -> info = unserialize ( $engine -> info );
2004-08-20 07:51:27 +00:00
$list [ $engine -> name ] = $engine ;
}
}
}
return $list ;
}
2003-11-26 16:17:13 +00:00
/**
2007-04-06 13:27:23 +00:00
* 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 .
2003-12-08 06:32:19 +00:00
*
2007-04-06 13:27:23 +00:00
* 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 :
2004-07-22 16:06:54 +00:00
*
2007-04-27 07:42:54 +00:00
* ENGINE_engine_preprocess ( & $variables )
2007-04-29 16:13:12 +00:00
* This function should only be implemented by theme engines and exists
2007-04-06 13:27:23 +00:00
* so that the theme engine can set necessary variables . It is commonly
* used to set global variables such as $directory and $is_front_page .
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* ENGINE_engine_preprocess_HOOK ( & $variables )
2007-04-06 13:27:23 +00:00
* This is the same as the previous function , but is called only per hook .
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* ENGINE_preprocess_HOOK ( & $variables )
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* ENGINE_preprocess ( & $variables )
2007-04-06 13:27:23 +00:00
* 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
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* THEME_preprocess_HOOK ( & $variables )
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* THEME_preprocess ( & $variables )
2007-04-06 13:27:23 +00:00
* 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 .
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* 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 .
2007-07-03 18:48:41 +00:00
*
2007-04-27 07:42:54 +00:00
* template_preprocess_HOOK ( & $variables )
* This is the same as the previous function , but is called only per hook .
2003-12-08 06:32:19 +00:00
*
2007-04-06 13:27:23 +00:00
* 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
2007-07-03 18:48:41 +00:00
* 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 .
2004-07-22 16:06:54 +00:00
* @ param ...
* Additional arguments to pass along to the theme function .
* @ return
* An HTML string that generates the themed output .
2003-12-08 06:32:19 +00:00
*/
2003-11-26 16:17:13 +00:00
function theme () {
2006-01-10 19:37:27 +00:00
$args = func_get_args ();
2007-04-06 13:27:23 +00:00
$hook = array_shift ( $args );
2006-01-10 19:37:27 +00:00
2007-04-06 13:27:23 +00:00
static $hooks = NULL ;
if ( ! isset ( $hooks )) {
init_theme ();
$hooks = theme_get_registry ();
2007-01-11 03:36:06 +00:00
}
2007-04-06 13:27:23 +00:00
2007-07-03 18:48:41 +00:00
if ( is_array ( $hook )) {
foreach ( $hook as $candidate ) {
if ( isset ( $hooks [ $candidate ])) {
break ;
}
}
$hook = $candidate ;
}
2007-04-06 13:27:23 +00:00
if ( ! isset ( $hooks [ $hook ])) {
return ;
2006-01-10 19:37:27 +00:00
}
2007-04-06 13:27:23 +00:00
$info = $hooks [ $hook ];
2007-05-06 05:47:52 +00:00
global $theme_path ;
$temp = $theme_path ;
// point path_to_theme() to the currently used theme path:
$theme_path = $hooks [ $hook ][ 'theme path' ];
2005-03-29 21:01:47 +00:00
2007-08-26 07:46:11 +00:00
// 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 );
}
2007-04-06 13:27:23 +00:00
if ( isset ( $info [ 'function' ])) {
// The theme call is a function.
2007-05-06 05:47:52 +00:00
$output = call_user_func_array ( $info [ 'function' ], $args );
2005-03-29 21:01:47 +00:00
}
2007-04-06 13:27:23 +00:00
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 ++ ;
}
}
2003-11-26 16:17:13 +00:00
2007-04-06 13:27:23 +00:00
// 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 ();
}
}
}
2007-04-27 07:42:54 +00:00
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 );
}
2007-04-06 13:27:23 +00:00
}
}
// 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 ) {
2007-08-29 16:56:13 +00:00
$template_file = drupal_discover_template ( $info [ 'theme paths' ], $suggestions , $extension );
2007-04-06 13:27:23 +00:00
}
if ( empty ( $template_file )) {
2007-08-26 07:46:11 +00:00
$template_file = $hooks [ $hook ][ 'template' ] . $extension ;
2007-04-06 13:27:23 +00:00
if ( isset ( $hooks [ $hook ][ 'path' ])) {
$template_file = $hooks [ $hook ][ 'path' ] . '/' . $template_file ;
}
}
2007-05-06 05:47:52 +00:00
$output = $render_function ( $template_file , $variables );
2004-08-20 07:51:27 +00:00
}
2007-05-06 05:47:52 +00:00
// restore path_to_theme()
$theme_path = $temp ;
return $output ;
2007-04-06 13:27:23 +00:00
}
/**
2007-08-29 16:56:13 +00:00
* Choose which template file to actually render . These are all suggested
* templates from themes and modules . Theming implementations can occur on
* multiple levels . All paths are checked to account for this .
2007-04-06 13:27:23 +00:00
*/
2007-08-29 16:56:13 +00:00
function drupal_discover_template ( $paths , $suggestions , $extension = '.tpl.php' ) {
2007-04-06 13:27:23 +00:00
global $theme_engine ;
2007-08-29 16:56:13 +00:00
// Loop through all paths and suggestions in FIFO order.
2007-04-06 13:27:23 +00:00
$suggestions = array_reverse ( $suggestions );
2007-08-29 16:56:13 +00:00
$paths = array_reverse ( $paths );
2007-04-06 13:27:23 +00:00
foreach ( $suggestions as $suggestion ) {
2007-08-29 16:56:13 +00:00
if ( ! empty ( $suggestion )) {
foreach ( $paths as $path ) {
if ( file_exists ( $file = $path . '/' . $suggestion . $extension )) {
return $file ;
}
}
2007-04-06 13:27:23 +00:00
}
2003-11-26 16:17:13 +00:00
}
}
/**
2004-07-22 16:06:54 +00:00
* Return the path to the currently selected theme .
2003-12-08 06:32:19 +00:00
*/
2003-11-26 16:17:13 +00:00
function path_to_theme () {
2007-05-06 05:47:52 +00:00
global $theme_path ;
2003-11-26 16:17:13 +00:00
2007-05-06 05:47:52 +00:00
if ( ! isset ( $theme_path )) {
2006-12-30 20:59:11 +00:00
init_theme ();
}
2007-05-06 05:47:52 +00:00
return $theme_path ;
2006-12-30 20:59:11 +00:00
}
2007-07-03 18:48:41 +00:00
/**
* 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 , '.' ));
2007-08-16 13:59:41 +00:00
// Transform - in filenames to _ to match function naming scheme
// for the purposes of searching.
$hook = strtr ( $template , '-' , '_' );
if ( isset ( $cache [ $hook ])) {
$templates [ $hook ] = array (
2007-08-26 07:46:11 +00:00
'template' => $template ,
2007-07-03 18:48:41 +00:00
'path' => dirname ( $file -> filename ),
);
}
}
$patterns = array_keys ( $files );
foreach ( $cache as $hook => $info ) {
if ( ! empty ( $info [ 'pattern' ])) {
2007-08-16 13:59:41 +00:00
// Transform _ in pattern to - to match file naming scheme
// for the purposes of searching.
$pattern = strtr ( $info [ 'pattern' ], '_' , '-' );
$matches = preg_grep ( '/^' . $pattern . '/' , $patterns );
2007-07-03 18:48:41 +00:00
if ( $matches ) {
foreach ( $matches as $match ) {
$file = substr ( $match , 0 , strpos ( $match , '.' ));
2007-08-16 13:59:41 +00:00
// Put the underscores back in for the hook name and register this pattern.
$templates [ strtr ( $file , '-' , '_' )] = array (
2007-08-26 07:46:11 +00:00
'template' => $file ,
2007-07-03 18:48:41 +00:00
'path' => dirname ( $files [ $match ] -> filename ),
'arguments' => $info [ 'arguments' ],
);
}
}
}
}
return $templates ;
}
2004-08-20 07:51:27 +00:00
/**
* Retrieve an associative array containing the settings for a theme .
*
2004-08-20 09:34:53 +00:00
* The final settings are arrived at by merging the default settings ,
2004-08-20 07:51:27 +00:00
* 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 .
*/
2004-08-20 17:21:37 +00:00
function theme_get_settings ( $key = NULL ) {
2004-08-20 07:51:27 +00:00
$defaults = array (
'mission' => '' ,
'default_logo' => 1 ,
'logo_path' => '' ,
2005-05-25 06:03:18 +00:00
'default_favicon' => 1 ,
'favicon_path' => '' ,
2007-08-20 18:26:41 +00:00
'primary_links' => 1 ,
'secondary_links' => 1 ,
2004-08-20 07:51:27 +00:00
'toggle_logo' => 1 ,
2005-05-25 06:03:18 +00:00
'toggle_favicon' => 1 ,
2004-08-20 07:51:27 +00:00
'toggle_name' => 1 ,
'toggle_search' => 1 ,
'toggle_slogan' => 0 ,
'toggle_mission' => 1 ,
'toggle_node_user_picture' => 0 ,
'toggle_comment_user_picture' => 0 ,
2007-08-20 18:26:41 +00:00
'toggle_primary_links' => 1 ,
'toggle_secondary_links' => 1 ,
2004-08-20 07:51:27 +00:00
);
2006-08-20 05:57:41 +00:00
if ( module_exists ( 'node' )) {
2006-06-23 07:54:00 +00:00
foreach ( node_get_types () as $type => $name ) {
2007-04-13 08:56:59 +00:00
$defaults [ 'toggle_node_info_' . $type ] = 1 ;
2005-04-13 17:59:39 +00:00
}
2004-08-20 07:51:27 +00:00
}
$settings = array_merge ( $defaults , variable_get ( 'theme_settings' , array ()));
if ( $key ) {
$settings = array_merge ( $settings , variable_get ( str_replace ( '/' , '_' , 'theme_' . $key . '_settings' ), array ()));
}
2004-10-14 02:38:33 +00:00
// Only offer search box if search.module is enabled.
2006-08-20 05:57:41 +00:00
if ( ! module_exists ( 'search' ) || ! user_access ( 'search content' )) {
2004-10-14 02:38:33 +00:00
$settings [ 'toggle_search' ] = 0 ;
}
2004-08-20 07:51:27 +00:00
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 .
*/
2004-08-20 17:21:37 +00:00
function theme_get_setting ( $setting_name , $refresh = FALSE ) {
2006-02-02 12:44:57 +00:00
global $theme_key ;
2004-08-20 07:51:27 +00:00
static $settings ;
if ( empty ( $settings ) || $refresh ) {
2004-08-20 17:21:37 +00:00
$settings = theme_get_settings ( $theme_key );
2004-08-20 07:51:27 +00:00
$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' ]) {
2006-04-04 23:31:04 +00:00
$settings [ 'logo' ] = base_path () . dirname ( $theme_object -> filename ) . '/logo.png' ;
2004-08-20 07:51:27 +00:00
}
elseif ( $settings [ 'logo_path' ]) {
2006-04-04 23:31:04 +00:00
$settings [ 'logo' ] = base_path () . $settings [ 'logo_path' ];
2004-08-20 07:51:27 +00:00
}
}
2005-05-25 06:03:18 +00:00
if ( $settings [ 'toggle_favicon' ]) {
if ( $settings [ 'default_favicon' ]) {
if ( file_exists ( $favicon = dirname ( $theme_object -> filename ) . '/favicon.ico' )) {
2006-04-06 02:35:57 +00:00
$settings [ 'favicon' ] = base_path () . $favicon ;
2005-05-25 06:03:18 +00:00
}
else {
2007-04-13 08:56:59 +00:00
$settings [ 'favicon' ] = base_path () . 'misc/favicon.ico' ;
2005-05-25 06:03:18 +00:00
}
}
elseif ( $settings [ 'favicon_path' ]) {
2006-04-06 02:35:57 +00:00
$settings [ 'favicon' ] = base_path () . $settings [ 'favicon_path' ];
2005-05-25 06:03:18 +00:00
}
2007-05-22 19:56:00 +00:00
else {
$settings [ 'toggle_favicon' ] = FALSE ;
}
2005-05-25 06:03:18 +00:00
}
2004-08-20 07:51:27 +00:00
}
return isset ( $settings [ $setting_name ]) ? $settings [ $setting_name ] : NULL ;
}
2004-01-28 11:36:29 +00:00
/**
2007-04-06 13:27:23 +00:00
* 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
2004-01-28 11:36:29 +00:00
* @ {
2007-04-06 13:27:23 +00:00
* 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 .
2004-01-28 11:36:29 +00:00
*
2007-04-06 13:27:23 +00:00
* 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 );
2007-07-03 18:48:41 +00:00
* 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 .
2007-04-06 13:27:23 +00:00
*
* 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 ) .
2004-01-28 11:36:29 +00:00
*
2004-09-09 05:51:08 +00:00
* The theme system is described and defined in theme . inc .
2007-04-06 13:27:23 +00:00
*
* @ see theme ()
* @ see hook_theme ()
2004-01-28 11:36:29 +00:00
*/
2005-03-31 21:18:08 +00:00
2005-03-31 09:25:33 +00:00
/**
2006-08-18 12:17:00 +00:00
* Formats text for emphasized display in a placeholder inside a sentence .
* Used automatically by t () .
2005-03-31 09:25:33 +00:00
*
* @ param $text
* The text to format ( plain - text ) .
* @ return
* The formatted text ( html ) .
*/
function theme_placeholder ( $text ) {
return '<em>' . check_plain ( $text ) . '</em>' ;
}
2004-01-26 19:05:21 +00:00
2007-03-02 09:40:27 +00:00
/**
* Generate a themed maintenance page .
*
2007-07-02 14:41:37 +00:00
* Note : this function is not themeable .
2007-03-02 09:40:27 +00:00
*
* @ param $content
* The page content to show .
2007-05-04 09:41:37 +00:00
* @ param $show_messages
2007-03-02 09:40:27 +00:00
* Whether to output status and error messages .
2007-05-04 09:41:37 +00:00
* FALSE can be useful to postpone the messages to a subsequent page .
2007-03-02 09:40:27 +00:00
*/
2007-05-04 09:41:37 +00:00
function theme_maintenance_page ( $content , $show_messages = TRUE ) {
2007-03-02 09:40:27 +00:00
// Set required headers.
2005-07-27 01:58:43 +00:00
drupal_set_header ( 'Content-Type: text/html; charset=utf-8' );
2007-08-23 16:41:19 +00:00
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" />' );
2006-02-02 12:44:57 +00:00
drupal_set_html_head ( '<link rel="shortcut icon" href="' . base_path () . 'misc/favicon.ico" type="image/x-icon" />' );
2006-03-28 09:29:23 +00:00
2007-03-02 09:40:27 +00:00
// Prepare variables.
$variables = array (
'head_title' => strip_tags ( drupal_get_title ()),
'head' => drupal_get_html_head (),
'styles' => '' ,
'scripts' => drupal_get_js (),
2007-09-01 05:42:49 +00:00
'left' => drupal_get_content ( 'left' ),
'right' => drupal_get_content ( 'right' ),
2007-03-02 09:40:27 +00:00
'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 (),
2007-05-04 09:41:37 +00:00
'messages' => $show_messages ? theme ( 'status_messages' ) : '' ,
2007-03-02 09:40:27 +00:00
'content' => $content ,
);
2005-07-27 01:58:43 +00:00
2007-04-06 13:27:23 +00:00
$output = theme_render_template ( 'misc/maintenance.tpl.php' , $variables );
2005-07-27 01:58:43 +00:00
return $output ;
}
2007-03-02 09:40:27 +00:00
/**
* Generate a themed installation page .
*
2007-07-02 14:41:37 +00:00
* Note : this function is not themeable .
2007-03-02 09:40:27 +00:00
*
* @ param $content
* The page content to show .
*/
2006-07-13 13:14:25 +00:00
function theme_install_page ( $content ) {
drupal_set_header ( 'Content-Type: text/html; charset=utf-8' );
2006-12-10 09:54:35 +00:00
drupal_add_css ( 'misc/maintenance.css' , 'module' , 'all' , FALSE );
2006-07-13 13:14:25 +00:00
drupal_set_html_head ( '<link rel="shortcut icon" href="' . base_path () . 'misc/favicon.ico" type="image/x-icon" />' );
2007-03-02 09:40:27 +00:00
$variables = array (
'head_title' => strip_tags ( drupal_get_title ()),
'head' => drupal_get_html_head (),
'styles' => drupal_get_css (),
'scripts' => drupal_get_js (),
2007-09-01 05:42:49 +00:00
'left' => drupal_get_content ( 'left' ),
'right' => drupal_get_content ( 'right' ),
2007-03-02 09:40:27 +00:00
'base_path' => base_path (),
'path_to_theme' => base_path () . 'themes/garland/minnelli' ,
'logo' => base_path () . 'themes/garland/minnelli/logo.png' ,
'site_title' => st ( 'Drupal Installation' ),
'title' => drupal_get_title (),
'messages' => '' ,
'content' => $content ,
);
// Special handling of error messages
2006-07-13 13:14:25 +00:00
$messages = drupal_set_message ();
if ( isset ( $messages [ 'error' ])) {
2006-12-27 13:02:34 +00:00
$title = count ( $messages [ 'error' ]) > 1 ? st ( 'The following errors must be resolved before you can continue the installation process' ) : st ( 'The following error must be resolved before you can continue the installation process' );
2007-03-02 09:40:27 +00:00
$variables [ 'messages' ] .= '<h3>' . $title . ':</h3>' ;
$variables [ 'messages' ] .= theme ( 'status_messages' , 'error' );
2006-07-13 13:14:25 +00:00
}
2007-03-02 09:40:27 +00:00
// Special handling of status messages
2006-07-13 13:14:25 +00:00
if ( isset ( $messages [ 'status' ])) {
2006-12-27 13:02:34 +00:00
$warnings = count ( $messages [ 'status' ]) > 1 ? st ( 'The following installation warnings should be carefully reviewed, but in most cases may be safely ignored' ) : st ( 'The following installation warning should be carefully reviewed, but in most cases may be safely ignored' );
2007-03-02 09:40:27 +00:00
$variables [ 'messages' ] .= '<h4>' . $title . ':</h4>' ;
$variables [ 'messages' ] .= theme ( 'status_messages' , 'status' );
2006-07-13 13:14:25 +00:00
}
2007-04-06 13:27:23 +00:00
return theme_render_template ( 'misc/maintenance.tpl.php' , $variables );
2007-03-02 09:40:27 +00:00
}
2006-07-13 13:14:25 +00:00
2007-03-02 09:40:27 +00:00
/**
* Return a themed list of maintenance tasks to perform .
*
2007-07-02 14:41:37 +00:00
* Note : this function is not themeable .
2007-03-02 09:40:27 +00:00
*/
function theme_task_list ( $items , $active = NULL ) {
$done = isset ( $items [ $active ]) || $active == NULL ;
$output = '<ol class="task-list">' ;
foreach ( $items as $k => $item ) {
if ( $active == $k ) {
$class = 'active' ;
$done = false ;
}
else {
$class = $done ? 'done' : '' ;
}
$output .= '<li class="' . $class . '">' . $item . '</li>' ;
}
$output .= '</ol>' ;
2006-07-13 13:14:25 +00:00
return $output ;
}
2004-07-08 16:04:07 +00:00
/**
2006-07-13 13:14:25 +00:00
* Return a themed set of status and / or error messages . The messages are grouped
2004-07-08 16:04:07 +00:00
* by type .
*
2006-07-13 13:14:25 +00:00
* @ param $display
* ( optional ) Set to 'status' or 'error' to display only messages of that type .
*
2004-07-22 16:06:54 +00:00
* @ return
* A string containing the messages .
2004-07-08 16:04:07 +00:00
*/
2006-07-13 13:14:25 +00:00
function theme_status_messages ( $display = NULL ) {
$output = '' ;
foreach ( drupal_get_messages ( $display ) as $type => $messages ) {
$output .= " <div class= \" messages $type\ " > \n " ;
if ( count ( $messages ) > 1 ) {
$output .= " <ul> \n " ;
2007-01-02 05:05:38 +00:00
foreach ( $messages as $message ) {
2006-07-13 13:14:25 +00:00
$output .= ' <li>' . $message . " </li> \n " ;
2004-07-08 16:04:07 +00:00
}
2006-07-13 13:14:25 +00:00
$output .= " </ul> \n " ;
2004-07-08 16:04:07 +00:00
}
2006-07-13 13:14:25 +00:00
else {
$output .= $messages [ 0 ];
}
$output .= " </div> \n " ;
2004-07-08 16:04:07 +00:00
}
2006-07-13 13:14:25 +00:00
return $output ;
2004-07-08 16:04:07 +00:00
}
2003-11-09 23:27:22 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed set of links .
*
* @ param $links
2006-05-18 14:58:57 +00:00
* A keyed array of links to be themed .
2006-08-30 07:37:14 +00:00
* @ param $attributes
* A keyed array of attributes
2004-07-22 16:06:54 +00:00
* @ return
2006-08-30 07:37:14 +00:00
* A string containing an unordered list of links .
2003-12-08 06:32:19 +00:00
*/
2006-08-30 07:37:14 +00:00
function theme_links ( $links , $attributes = array ( 'class' => 'links' )) {
$output = '' ;
2006-05-18 14:58:57 +00:00
2006-11-21 19:41:57 +00:00
if ( count ( $links ) > 0 ) {
2006-08-30 07:37:14 +00:00
$output = '<ul' . drupal_attributes ( $attributes ) . '>' ;
$num_links = count ( $links );
$i = 1 ;
2006-05-18 14:58:57 +00:00
foreach ( $links as $key => $link ) {
2007-08-29 16:16:50 +00:00
$class = $key ;
2006-08-30 07:37:14 +00:00
2007-08-29 16:16:50 +00:00
// Add first, last and active classes to the list of links to help out themers.
2006-12-29 08:18:28 +00:00
if ( $i == 1 ) {
2007-08-29 16:16:50 +00:00
$class .= ' first' ;
2006-12-29 08:18:28 +00:00
}
if ( $i == $num_links ) {
2007-08-29 16:16:50 +00:00
$class .= ' last' ;
}
2007-08-30 15:50:58 +00:00
if ( isset ( $link [ 'href' ]) && $link [ 'href' ] == $_GET [ 'q' ]) {
2007-08-29 16:16:50 +00:00
$class .= ' active' ;
2006-12-29 08:18:28 +00:00
}
2007-08-29 16:16:50 +00:00
$output .= '<li class="' . $class . '">' ;
2006-08-30 07:37:14 +00:00
2006-11-29 20:39:37 +00:00
if ( isset ( $link [ 'href' ])) {
2007-02-15 11:40:19 +00:00
// Pass in $link as $options, they share the same keys.
$output .= l ( $link [ 'title' ], $link [ 'href' ], $link );
2006-05-18 14:58:57 +00:00
}
2007-03-27 05:13:55 +00:00
else if ( ! empty ( $link [ 'title' ])) {
2007-02-15 11:40:19 +00:00
// Some links are actually not links, but we wrap these in <span> for adding title and class attributes
if ( empty ( $link [ 'html' ])) {
2006-10-18 18:00:40 +00:00
$link [ 'title' ] = check_plain ( $link [ 'title' ]);
}
2007-08-29 16:16:50 +00:00
$span_attributes = '' ;
if ( isset ( $link [ 'attributes' ])) {
$span_attributes = drupal_attributes ( $link [ 'attributes' ]);
}
$output .= '<span' . $span_attributes . '>' . $link [ 'title' ] . '</span>' ;
2006-05-18 14:58:57 +00:00
}
2006-08-30 07:37:14 +00:00
$i ++ ;
2006-10-17 08:38:16 +00:00
$output .= " </li> \n " ;
2006-05-18 14:58:57 +00:00
}
2006-08-30 07:37:14 +00:00
$output .= '</ul>' ;
2005-11-03 19:33:37 +00:00
}
2006-05-18 14:58:57 +00:00
2006-08-30 07:37:14 +00:00
return $output ;
2003-11-08 11:56:33 +00:00
}
2003-02-09 17:39:40 +00:00
2003-11-09 23:27:22 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed image .
2003-12-08 06:32:19 +00:00
*
2004-08-04 20:40:01 +00:00
* @ param $path
2006-08-24 00:04:44 +00:00
* Either the path of the image file ( relative to base_path ()) or a full URL .
2004-08-04 20:40:01 +00:00
* @ param $alt
* The alternative text for text - based browsers .
* @ param $title
* The title text is displayed when the image is hovered in some popular browsers .
2005-05-06 09:01:46 +00:00
* @ param $attributes
* Associative array of attributes to be placed in the img tag .
2004-08-20 04:35:33 +00:00
* @ param $getsize
2006-07-05 11:45:51 +00:00
* If set to TRUE , the image ' s dimension are fetched and added as width / height attributes .
2004-07-22 16:06:54 +00:00
* @ return
2004-08-04 20:40:01 +00:00
* A string containing the image tag .
2003-12-08 06:32:19 +00:00
*/
2005-05-06 09:01:46 +00:00
function theme_image ( $path , $alt = '' , $title = '' , $attributes = NULL , $getsize = TRUE ) {
2005-06-19 08:59:06 +00:00
if ( ! $getsize || ( is_file ( $path ) && ( list ( $width , $height , $type , $image_attributes ) = @ getimagesize ( $path )))) {
2005-05-06 09:01:46 +00:00
$attributes = drupal_attributes ( $attributes );
2006-08-24 00:04:44 +00:00
$url = ( url ( $path ) == $path ) ? $path : ( base_path () . $path );
2007-01-31 15:49:26 +00:00
return '<img src="' . check_url ( $url ) . '" alt="' . check_plain ( $alt ) . '" title="' . check_plain ( $title ) . '" ' . ( isset ( $image_attributes ) ? $image_attributes : '' ) . $attributes . ' />' ;
2004-08-04 20:40:01 +00:00
}
2003-11-08 11:56:33 +00:00
}
2003-02-09 17:39:40 +00:00
2003-11-09 23:27:22 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed breadcrumb trail .
2003-12-08 06:32:19 +00:00
*
2004-07-22 16:06:54 +00:00
* @ param $breadcrumb
* An array containing the breadcrumb links .
* @ return a string containing the breadcrumb output .
2003-12-08 06:32:19 +00:00
*/
2003-11-08 11:56:33 +00:00
function theme_breadcrumb ( $breadcrumb ) {
2006-01-18 19:02:34 +00:00
if ( ! empty ( $breadcrumb )) {
return '<div class="breadcrumb">' . implode ( ' » ' , $breadcrumb ) . '</div>' ;
}
2003-11-08 11:56:33 +00:00
}
2001-10-20 13:35:12 +00:00
2005-04-30 17:47:57 +00:00
/**
* Return a themed help message .
*
* @ return a string containing the helptext for the current page .
*/
function theme_help () {
if ( $help = menu_get_active_help ()) {
return '<div class="help">' . $help . '</div>' ;
}
}
2004-06-18 15:04:37 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed submenu , typically displayed under the tabs .
2004-06-18 15:04:37 +00:00
*
2004-07-22 16:06:54 +00:00
* @ param $links
* An array of links .
2004-06-18 15:04:37 +00:00
*/
function theme_submenu ( $links ) {
2004-07-22 16:06:54 +00:00
return '<div class="submenu">' . implode ( ' | ' , $links ) . '</div>' ;
2004-06-18 15:04:37 +00:00
}
2003-11-13 19:52:54 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed table .
*
* @ param $header
* An array containing the table headers . Each element of the array can be
* either a localized string or an associative array with the following keys :
* - " data " : The localized title of the table column .
* - " field " : The database field represented in the table column ( required if
* user is to be able to sort on this column ) .
* - " sort " : A default sort order for this column ( " asc " or " desc " ) .
* - Any HTML attributes , such as " colspan " , to apply to the column header cell .
* @ param $rows
2004-09-14 20:01:00 +00:00
* An array of table rows . Every row is an array of cells , or an associative
* array with the following keys :
* - " data " : an array of cells
* - Any HTML attributes , such as " class " , to apply to the table row .
*
* Each cell can be either a string or an associative array with the following keys :
2004-07-22 16:06:54 +00:00
* - " data " : The string to display in the table cell .
2006-08-03 20:37:52 +00:00
* - " header " : Indicates this cell is a header .
2004-07-22 16:06:54 +00:00
* - Any HTML attributes , such as " colspan " , to apply to the table cell .
2004-09-14 20:01:00 +00:00
*
* Here ' s an example for $rows :
* @ verbatim
* $rows = array (
* // Simple row
* array (
* 'Cell 1' , 'Cell 2' , 'Cell 3'
* ),
* // Row with attributes on the row and some of its cells.
* array (
* 'data' => array ( 'Cell 1' , array ( 'data' => 'Cell 2' , 'colspan' => 2 )), 'class' => 'funky'
* )
* );
* @ endverbatim
*
2004-07-22 16:06:54 +00:00
* @ param $attributes
* An array of HTML attributes to apply to the table tag .
2005-09-06 20:32:53 +00:00
* @ param $caption
* A localized string to use for the < caption > tag .
2004-07-22 16:06:54 +00:00
* @ return
* An HTML string representing the table .
2003-12-08 06:32:19 +00:00
*/
2006-11-17 06:53:31 +00:00
function theme_table ( $header , $rows , $attributes = array (), $caption = NULL ) {
2004-08-21 16:21:56 +00:00
$output = '<table' . drupal_attributes ( $attributes ) . " > \n " ;
2003-11-13 19:52:54 +00:00
2005-09-06 20:32:53 +00:00
if ( isset ( $caption )) {
$output .= '<caption>' . $caption . " </caption> \n " ;
}
2004-07-22 16:06:54 +00:00
// Format the table header:
2005-06-19 08:13:14 +00:00
if ( count ( $header )) {
2007-02-06 08:35:13 +00:00
// Include JS for sticky headers.
drupal_add_js ( 'misc/tableheader.js' );
2006-11-17 06:53:31 +00:00
$ts = tablesort_init ( $header );
2005-09-15 20:58:17 +00:00
$output .= ' <thead><tr>' ;
2003-11-13 19:52:54 +00:00
foreach ( $header as $cell ) {
2004-06-02 05:35:51 +00:00
$cell = tablesort_header ( $cell , $header , $ts );
2006-08-03 20:37:52 +00:00
$output .= _theme_table_cell ( $cell , TRUE );
2003-11-13 19:52:54 +00:00
}
2005-09-15 20:58:17 +00:00
$output .= " </tr></thead> \n " ;
2003-11-13 19:52:54 +00:00
}
2007-03-27 05:13:55 +00:00
else {
$ts = array ();
}
2003-11-13 19:52:54 +00:00
2004-07-22 16:06:54 +00:00
// Format the table rows:
2005-09-15 20:58:17 +00:00
$output .= " <tbody> \n " ;
2005-06-19 08:13:14 +00:00
if ( count ( $rows )) {
2007-04-09 13:43:57 +00:00
$flip = array ( 'even' => 'odd' , 'odd' => 'even' );
$class = 'even' ;
2003-11-13 19:52:54 +00:00
foreach ( $rows as $number => $row ) {
2004-09-14 20:01:00 +00:00
$attributes = array ();
// Check if we're dealing with a simple or complex row
if ( isset ( $row [ 'data' ])) {
foreach ( $row as $key => $value ) {
if ( $key == 'data' ) {
$cells = $value ;
}
else {
$attributes [ $key ] = $value ;
}
}
}
else {
$cells = $row ;
}
2007-06-28 09:11:06 +00:00
if ( count ( $cells )) {
// Add odd/even class
$class = $flip [ $class ];
if ( isset ( $attributes [ 'class' ])) {
$attributes [ 'class' ] .= ' ' . $class ;
}
else {
$attributes [ 'class' ] = $class ;
}
2004-09-14 20:01:00 +00:00
2007-06-28 09:11:06 +00:00
// Build row
$output .= ' <tr' . drupal_attributes ( $attributes ) . '>' ;
$i = 0 ;
foreach ( $cells as $cell ) {
$cell = tablesort_cell ( $cell , $header , $ts , $i ++ );
$output .= _theme_table_cell ( $cell );
}
$output .= " </tr> \n " ;
2003-11-13 19:52:54 +00:00
}
}
}
2005-09-15 20:58:17 +00:00
$output .= " </tbody></table> \n " ;
2003-11-13 19:52:54 +00:00
return $output ;
}
2006-11-21 08:16:39 +00:00
/**
* Returns a header cell for tables that have a select all functionality .
*/
function theme_table_select_header_cell () {
drupal_add_js ( 'misc/tableselect.js' );
return array ( 'class' => 'select-all' );
}
2005-07-02 12:32:09 +00:00
/**
* Return a themed sort icon .
*
* @ param $style
2006-05-07 00:08:36 +00:00
* Set to either asc or desc . This sets which icon to show .
2005-07-02 12:32:09 +00:00
* @ return
* A themed sort icon .
*/
function theme_tablesort_indicator ( $style ) {
2007-04-13 08:56:59 +00:00
if ( $style == " asc " ) {
2005-07-02 12:32:09 +00:00
return theme ( 'image' , 'misc/arrow-asc.png' , t ( 'sort icon' ), t ( 'sort ascending' ));
}
else {
return theme ( 'image' , 'misc/arrow-desc.png' , t ( 'sort icon' ), t ( 'sort descending' ));
}
}
2003-11-09 23:27:22 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed box .
*
* @ param $title
* The subject of the box .
* @ param $content
* The content of the box .
* @ param $region
* The region in which the box is displayed .
* @ return
* A string containing the box output .
2003-12-08 06:32:19 +00:00
*/
2004-02-08 21:04:08 +00:00
function theme_box ( $title , $content , $region = 'main' ) {
2004-07-22 16:06:54 +00:00
$output = '<h2 class="title">' . $title . '</h2><div>' . $content . '</div>' ;
2003-11-09 23:27:22 +00:00
return $output ;
2003-11-08 11:56:33 +00:00
}
2003-10-31 19:34:03 +00:00
/**
2005-01-30 09:53:19 +00:00
* Return a themed marker , useful for marking new or updated
* content .
2003-12-08 06:32:19 +00:00
*
2005-01-27 12:57:08 +00:00
* @ param $type
2005-01-30 09:53:19 +00:00
* Number representing the marker type to display
* @ see MARK_NEW , MARK_UPDATED , MARK_READ
2004-07-22 16:06:54 +00:00
* @ return
* A string containing the marker .
2003-12-08 06:32:19 +00:00
*/
2005-01-30 09:53:19 +00:00
function theme_mark ( $type = MARK_NEW ) {
global $user ;
2005-04-24 16:22:30 +00:00
if ( $user -> uid ) {
if ( $type == MARK_NEW ) {
2005-09-29 08:02:55 +00:00
return ' <span class="marker">' . t ( 'new' ) . '</span>' ;
2005-04-24 16:22:30 +00:00
}
else if ( $type == MARK_UPDATED ) {
2005-09-29 08:02:55 +00:00
return ' <span class="marker">' . t ( 'updated' ) . '</span>' ;
2005-04-24 16:22:30 +00:00
}
2005-01-30 09:53:19 +00:00
}
2002-10-22 18:46:43 +00:00
}
2003-10-31 19:34:03 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a themed list of items .
*
* @ param $items
2006-07-02 00:25:40 +00:00
* An array of items to be displayed in the list . If an item is a string ,
* then it is used as is . If an item is an array , then the " data " element of
2006-08-17 06:55:26 +00:00
* the array is used as the contents of the list item . If an item is an array
* with a " children " element , those children are displayed in a nested list .
* All other elements are treated as attributes of the list item element .
2004-07-22 16:06:54 +00:00
* @ param $title
* The title of the list .
2006-05-20 01:24:30 +00:00
* @ param $attributes
* The attributes applied to the list element .
2005-10-18 14:45:09 +00:00
* @ param $type
* The type of list to return ( e . g . " ul " , " ol " )
2004-07-22 16:06:54 +00:00
* @ return
* A string containing the list output .
2003-12-08 06:32:19 +00:00
*/
2006-05-20 01:24:30 +00:00
function theme_item_list ( $items = array (), $title = NULL , $type = 'ul' , $attributes = NULL ) {
2004-07-22 16:06:54 +00:00
$output = '<div class="item-list">' ;
2002-11-09 20:12:03 +00:00
if ( isset ( $title )) {
2004-07-22 16:06:54 +00:00
$output .= '<h3>' . $title . '</h3>' ;
2002-11-09 13:59:36 +00:00
}
2005-11-24 20:08:54 +00:00
if ( ! empty ( $items )) {
2007-04-13 08:56:59 +00:00
$output .= " < $type " . drupal_attributes ( $attributes ) . '>' ;
2002-11-09 20:12:03 +00:00
foreach ( $items as $item ) {
2006-07-02 00:25:40 +00:00
$attributes = array ();
2006-08-17 06:55:26 +00:00
$children = array ();
2006-07-02 00:25:40 +00:00
if ( is_array ( $item )) {
foreach ( $item as $key => $value ) {
if ( $key == 'data' ) {
$data = $value ;
}
2006-08-17 06:55:26 +00:00
elseif ( $key == 'children' ) {
$children = $value ;
}
2006-07-02 00:25:40 +00:00
else {
$attributes [ $key ] = $value ;
}
}
}
else {
$data = $item ;
}
2006-08-17 06:55:26 +00:00
if ( count ( $children ) > 0 ) {
$data .= theme_item_list ( $children , NULL , $type , $attributes ); // Render nested list
}
2007-04-13 08:56:59 +00:00
$output .= '<li' . drupal_attributes ( $attributes ) . '>' . $data . '</li>' ;
2002-11-09 20:12:03 +00:00
}
2005-10-18 14:45:09 +00:00
$output .= " </ $type > " ;
2002-11-09 13:59:36 +00:00
}
2004-07-22 16:06:54 +00:00
$output .= '</div>' ;
2002-11-09 13:59:36 +00:00
return $output ;
}
2003-10-31 19:34:03 +00:00
/**
2005-05-05 22:22:46 +00:00
* Returns code that emits the 'more help' - link .
2003-12-08 06:32:19 +00:00
*/
2004-08-10 05:44:17 +00:00
function theme_more_help_link ( $url ) {
2007-04-13 08:56:59 +00:00
return '<div class="more-help-link">' . t ( '[<a href="@link">more help...</a>]' , array ( '@link' => check_url ( $url ))) . '</div>' ;
2004-08-10 05:44:17 +00:00
}
2004-01-11 15:05:21 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return code that emits an XML icon .
2004-01-11 15:05:21 +00:00
*/
function theme_xml_icon ( $url ) {
2004-08-04 20:40:01 +00:00
if ( $image = theme ( 'image' , 'misc/xml.png' , t ( 'XML feed' ), t ( 'XML feed' ))) {
2007-04-13 08:56:59 +00:00
return '<a href="' . check_url ( $url ) . '" class="xml-icon">' . $image . '</a>' ;
2004-08-04 20:40:01 +00:00
}
2004-01-11 15:05:21 +00:00
}
2005-12-29 04:46:40 +00:00
/**
* Return code that emits an feed icon .
2007-05-31 12:14:04 +00:00
*
* @ param $url
* The url of the feed .
* @ param $title
* A descriptive title of the feed .
*/
function theme_feed_icon ( $url , $title ) {
if ( $image = theme ( 'image' , 'misc/feed.png' , t ( 'Syndicate content' ), $title )) {
2007-04-13 08:56:59 +00:00
return '<a href="' . check_url ( $url ) . '" class="feed-icon">' . $image . '</a>' ;
2005-12-29 04:46:40 +00:00
}
}
2003-10-31 19:34:03 +00:00
/**
2004-07-22 16:06:54 +00:00
* Execute hook_footer () which is run at the end of the page right before the
* close of the body tag .
2003-12-08 06:32:19 +00:00
*
* @ param $main ( optional )
2006-12-08 16:20:09 +00:00
* Whether the current page is the front page of the site .
2004-07-22 16:06:54 +00:00
* @ return
* A string containing the results of the hook_footer () calls .
2003-12-08 06:32:19 +00:00
*/
2003-11-08 11:56:33 +00:00
function theme_closure ( $main = 0 ) {
2004-02-08 21:04:08 +00:00
$footer = module_invoke_all ( 'footer' , $main );
2006-08-22 09:00:31 +00:00
return implode ( " \n " , $footer ) . drupal_get_js ( 'footer' );
2003-04-21 13:56:09 +00:00
}
2003-02-01 19:54:19 +00:00
/**
2004-07-22 16:06:54 +00:00
* Return a set of blocks available for the current user .
2003-11-19 16:13:07 +00:00
*
2004-07-22 16:06:54 +00:00
* @ param $region
* Which set of blocks to retrieve .
* @ return
* A string containing the themed blocks for this region .
2003-11-19 16:13:07 +00:00
*/
function theme_blocks ( $region ) {
2004-02-08 21:04:08 +00:00
$output = '' ;
2003-11-19 16:13:07 +00:00
2006-06-29 20:40:26 +00:00
if ( $list = block_list ( $region )) {
2003-11-19 16:13:07 +00:00
foreach ( $list as $key => $block ) {
// $key == <i>module</i>_<i>delta</i>
$output .= theme ( 'block' , $block );
2000-12-23 23:25:28 +00:00
}
}
2005-08-16 18:06:18 +00:00
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content ( $region );
2003-11-09 23:27:22 +00:00
return $output ;
2000-12-23 23:25:28 +00:00
}
2005-03-03 20:51:27 +00:00
2005-08-01 05:14:05 +00:00
/**
* Format a username .
*
* @ param $object
* The user object to format , usually returned from user_load () .
* @ return
* A string containing an HTML link to the user ' s page if the passed object
* suggests that this is a site user . Otherwise , only the username is returned .
*/
function theme_username ( $object ) {
if ( $object -> uid && $object -> name ) {
// Shorten the name when it is too long or it will break many tables.
if ( drupal_strlen ( $object -> name ) > 20 ) {
$name = drupal_substr ( $object -> name , 0 , 15 ) . '...' ;
}
else {
$name = $object -> name ;
}
if ( user_access ( 'access user profiles' )) {
$output = l ( $name , 'user/' . $object -> uid , array ( 'title' => t ( 'View user profile.' )));
}
else {
2006-03-13 21:42:35 +00:00
$output = check_plain ( $name );
2005-08-01 05:14:05 +00:00
}
}
else if ( $object -> name ) {
// Sometimes modules display content composed by people who are
// not registered members of the site (e.g. mailing list or news
// aggregator modules). This clause enables modules to display
// the true author of the content.
if ( $object -> homepage ) {
2007-08-19 11:02:35 +00:00
$output = l ( $object -> name , $object -> homepage , array ( 'rel' => 'nofollow' ));
2005-08-01 05:14:05 +00:00
}
else {
2006-03-13 21:42:35 +00:00
$output = check_plain ( $object -> name );
2005-08-01 05:14:05 +00:00
}
$output .= ' (' . t ( 'not verified' ) . ')' ;
}
else {
2006-11-24 09:01:57 +00:00
$output = variable_get ( 'anonymous' , t ( 'Anonymous' ));
2005-08-01 05:14:05 +00:00
}
return $output ;
}
2005-03-03 20:51:27 +00:00
2005-12-06 09:25:22 +00:00
function theme_progress_bar ( $percent , $message ) {
$output = '<div id="progress" class="progress">' ;
$output .= '<div class="bar"><div class="filled" style="width: ' . $percent . '%"></div></div>' ;
2007-05-04 09:41:37 +00:00
$output .= '<div class="percentage">' . $percent . '%</div>' ;
$output .= '<div class="message">' . $message . '</div>' ;
2005-12-06 09:25:22 +00:00
$output .= '</div>' ;
return $output ;
}
2004-07-22 16:06:54 +00:00
/**
2004-09-09 05:51:08 +00:00
* @ } End of " defgroup themeable " .
2004-07-22 16:06:54 +00:00
*/
2001-10-22 12:55:41 +00:00
2006-08-03 20:37:52 +00:00
function _theme_table_cell ( $cell , $header = FALSE ) {
2004-07-02 18:46:42 +00:00
$attributes = '' ;
2003-11-26 16:17:13 +00:00
if ( is_array ( $cell )) {
2007-01-31 15:49:26 +00:00
$data = isset ( $cell [ 'data' ]) ? $cell [ 'data' ] : '' ;
2006-08-03 20:37:52 +00:00
$header |= isset ( $cell [ 'header' ]);
unset ( $cell [ 'data' ]);
unset ( $cell [ 'header' ]);
$attributes = drupal_attributes ( $cell );
2002-10-22 18:46:43 +00:00
}
2003-11-26 16:17:13 +00:00
else {
$data = $cell ;
2002-06-23 13:31:30 +00:00
}
2003-11-09 23:27:22 +00:00
2003-11-26 16:17:13 +00:00
if ( $header ) {
$output = " <th $attributes > $data </th> " ;
2003-04-21 13:56:09 +00:00
}
2003-11-26 16:17:13 +00:00
else {
$output = " <td $attributes > $data </td> " ;
2003-04-21 13:56:09 +00:00
}
2003-11-24 22:54:49 +00:00
2003-11-26 16:17:13 +00:00
return $output ;
}
2005-08-25 21:14:17 +00:00
2007-04-27 07:42:54 +00:00
/**
2007-08-28 11:35:34 +00:00
* Adds a default set of helper variables for preprocess functions and
* templates . This comes in before any other preprocess function which makes
* it possible to be used in default theme implementations ( non - overriden
* theme functions ) .
*/
function template_preprocess ( & $variables , $hook ) {
global $user ;
static $count = array ();
// Track run count for each hook to provide zebra striping.
2007-09-01 05:42:49 +00:00
// See "template_preprocess_block()" which provides the same feature specific to blocks.
2007-08-28 11:35:34 +00:00
$count [ $hook ] = isset ( $count [ $hook ]) && is_int ( $count [ $hook ]) ? $count [ $hook ] : 1 ;
$variables [ 'zebra' ] = ( $count [ $hook ] % 2 ) ? 'odd' : 'even' ;
$variables [ 'id' ] = $count [ $hook ] ++ ;
// Tell all templates where they are located.
$variables [ 'directory' ] = path_to_theme ();
// Flag front page status.
$variables [ 'is_front' ] = drupal_is_front_page ();
// Tell all templates by which kind of user they're viewed.
$variables [ 'logged_in' ] = ( $user -> uid > 0 );
$variables [ 'is_admin' ] = user_access ( 'access administration pages' );
}
/**
* Process variables for page . tpl . php
*
* Most themes utilize their own copy of page . tpl . php . The default is located
* inside " modules/system/page.tpl.php " . Look in there for the full list of
* variables .
*
* Uses the arg () function to generate a series of page template suggestions
* based on the current path .
*
* The $variables array contains the following arguments :
* - $content
* - $show_blocks
*
* @ see page . tpl . php
2007-04-27 07:42:54 +00:00
*/
function template_preprocess_page ( & $variables ) {
/* Set title and breadcrumb to declared values */
if ( drupal_is_front_page ()) {
$variables [ 'mission' ] = filter_xss_admin ( theme_get_setting ( 'mission' ));
}
/* Add favicon */
if ( theme_get_setting ( 'toggle_favicon' )) {
drupal_set_html_head ( '<link rel="shortcut icon" href="' . check_url ( theme_get_setting ( 'favicon' )) . '" type="image/x-icon" />' );
}
global $theme ;
2007-09-01 05:42:49 +00:00
// Populate all block regions.
2007-04-27 07:42:54 +00:00
$regions = system_region_list ( $theme );
// Load all region content assigned via blocks.
foreach ( array_keys ( $regions ) as $region ) {
2007-09-01 05:42:49 +00:00
// Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE.
if ( ! ( ! $variables [ 'show_blocks' ] && ( $region == 'left' || $region == 'right' ))) {
$blocks = theme ( 'blocks' , $region );
2007-04-27 07:42:54 +00:00
}
2007-09-01 05:42:49 +00:00
else {
$blocks = '' ;
}
// Assign region to a region variable.
isset ( $variables [ $region ]) ? $variables [ $region ] .= $blocks : $variables [ $region ] = $blocks ;
}
// Setup layout variable.
$variables [ 'layout' ] = 'none' ;
if ( ! empty ( $variables [ 'left' ])) {
$variables [ 'layout' ] = 'left' ;
}
if ( ! empty ( $variables [ 'right' ])) {
$variables [ 'layout' ] = ( $variables [ 'layout' ] == 'left' ) ? 'both' : 'right' ;
2007-04-27 07:42:54 +00:00
}
// Construct page title
if ( drupal_get_title ()) {
$head_title = array ( strip_tags ( drupal_get_title ()), variable_get ( 'site_name' , 'Drupal' ));
}
else {
$head_title = array ( variable_get ( 'site_name' , 'Drupal' ));
if ( variable_get ( 'site_slogan' , '' )) {
$head_title [] = variable_get ( 'site_slogan' , '' );
}
}
$variables [ 'head_title' ] = implode ( ' | ' , $head_title );
$variables [ 'base_path' ] = base_path ();
$variables [ 'breadcrumb' ] = theme ( 'breadcrumb' , drupal_get_breadcrumb ());
$variables [ 'feed_icons' ] = drupal_get_feeds ();
2007-09-01 05:42:49 +00:00
$variables [ 'footer_message' ] = filter_xss_admin ( variable_get ( 'site_footer' , FALSE ));
2007-04-27 07:42:54 +00:00
$variables [ 'head' ] = drupal_get_html_head ();
$variables [ 'help' ] = theme ( 'help' );
$variables [ 'language' ] = $GLOBALS [ 'language' ];
$variables [ 'logo' ] = theme_get_setting ( 'logo' );
2007-05-04 09:41:37 +00:00
$variables [ 'messages' ] = $variables [ 'show_messages' ] ? theme ( 'status_messages' ) : '' ;
2007-04-27 07:42:54 +00:00
$variables [ 'mission' ] = isset ( $mission ) ? $mission : '' ;
2007-08-20 18:26:41 +00:00
$variables [ 'primary_links' ] = theme_get_setting ( 'toggle_primary_links' ) ? menu_primary_links () : array ();
$variables [ 'secondary_links' ] = theme_get_setting ( 'toggle_secondary_links' ) ? menu_secondary_links () : array ();
2007-04-27 07:42:54 +00:00
$variables [ 'search_box' ] = ( theme_get_setting ( 'toggle_search' ) ? drupal_get_form ( 'search_theme_form' ) : '' );
$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 ();
2007-07-18 07:05:49 +00:00
// Closure should be filled last.
$variables [ 'closure' ] = theme ( 'closure' );
2007-04-27 07:42:54 +00:00
if (( arg ( 0 ) == 'node' ) && is_numeric ( arg ( 1 ))) {
$variables [ 'node' ] = node_load ( arg ( 1 ));
}
2007-08-02 20:08:53 +00:00
// Compile a list of classes that are going to be applied to the body element.
// This allows advanced theming based on context (home page, node of certain type, etc.).
$body_classes = array ();
// Add a class that tells us whether we're on the front page or not.
2007-09-01 05:42:49 +00:00
$body_classes [] = $variables [ 'is_front' ] ? 'front' : 'not-front' ;
2007-08-02 20:08:53 +00:00
// Add a class that tells us whether the page is viewed by an authenticated user or not.
2007-09-01 05:42:49 +00:00
$body_classes [] = $variables [ 'logged_in' ] ? 'logged-in' : 'not-logged-in' ;
2007-08-02 20:08:53 +00:00
// Add arg(0) to make it possible to theme the page depending on the current page
// type (e.g. node, admin, user, etc.). To avoid illegal characters in the class,
// we're removing everything disallowed. We are not using 'a-z' as that might leave
// in certain international characters (e.g. German umlauts).
$body_classes [] = preg_replace ( '![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s' , '' , 'page-' . form_clean_id ( drupal_strtolower ( arg ( 0 ))));
// If on an individual node page, add the node type.
if ( isset ( $variables [ 'node' ]) && $variables [ 'node' ] -> type ) {
$body_classes [] = 'node-type-' . form_clean_id ( $variables [ 'node' ] -> type );
}
// Add information about the number of sidebars.
2007-09-01 05:42:49 +00:00
if ( $variables [ 'left' ] && $variables [ 'right' ]) {
2007-08-02 20:08:53 +00:00
$body_classes [] = 'two-sidebars' ;
}
2007-09-01 05:42:49 +00:00
elseif ( $variables [ 'left' ]) {
2007-08-02 20:08:53 +00:00
$body_classes [] = 'one-sidebar sidebar-left' ;
}
2007-09-01 05:42:49 +00:00
elseif ( $variables [ 'right' ]) {
2007-08-02 20:08:53 +00:00
$body_classes [] = 'one-sidebar sidebar-right' ;
}
else {
$body_classes [] = 'no-sidebars' ;
}
// Implode with spaces.
$variables [ 'body_classes' ] = implode ( ' ' , $body_classes );
2007-04-27 07:42:54 +00:00
// Build a list of suggested template files in order of specificity. One
// suggestion is made for every element of the current path, though
// numeric elements are not carried to subsequent suggestions. For example,
// http://www.example.com/node/1/edit would result in the following
// suggestions:
//
// page-node-edit.tpl.php
// page-node-1.tpl.php
// page-node.tpl.php
// page.tpl.php
$i = 0 ;
$suggestion = 'page' ;
$suggestions = array ();
while ( $arg = arg ( $i ++ )) {
$suggestions [] = $suggestion . '-' . $arg ;
if ( ! is_numeric ( $arg )) {
$suggestion .= '-' . $arg ;
}
}
if ( drupal_is_front_page ()) {
$suggestions [] = 'page-front' ;
}
if ( $suggestions ) {
$variables [ 'template_files' ] = $suggestions ;
}
}
2007-08-28 11:35:34 +00:00
/**
* Process variables for node . tpl . php
*
* Most themes utilize their own copy of node . tpl . php . The default is located
* inside " modules/node/node.tpl.php " . Look in there for the full list of
* variables .
*
* The $variables array contains the following arguments :
* - $node
* - $teaser
* - $page
*
* @ see node . tpl . php
2007-04-27 07:42:54 +00:00
*/
function template_preprocess_node ( & $variables ) {
$node = $variables [ 'node' ];
if ( module_exists ( 'taxonomy' )) {
$variables [ 'taxonomy' ] = taxonomy_link ( 'taxonomy terms' , $node );
}
else {
$variables [ 'taxonomy' ] = array ();
}
if ( $variables [ 'teaser' ] && $node -> teaser ) {
$variables [ 'content' ] = $node -> teaser ;
}
elseif ( isset ( $node -> body )) {
$variables [ 'content' ] = $node -> body ;
}
else {
$variables [ 'content' ] = '' ;
}
$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 );
// Display info only on certain node types.
if ( theme_get_setting ( 'toggle_node_info_' . $node -> type )) {
2007-07-01 23:15:41 +00:00
$variables [ 'submitted' ] = theme ( 'node_submitted' , $node );
2007-04-27 07:42:54 +00:00
$variables [ 'picture' ] = theme_get_setting ( 'toggle_node_user_picture' ) ? theme ( 'user_picture' , $node ) : '' ;
}
else {
$variables [ 'submitted' ] = '' ;
$variables [ 'picture' ] = '' ;
}
2007-08-28 11:35:34 +00:00
// Clean up name so there are no underscores.
2007-04-27 07:42:54 +00:00
$variables [ 'template_files' ][] = 'node-' . $node -> type ;
}
/**
2007-08-28 11:35:34 +00:00
* Process variables for block . tpl . php
*
2007-04-27 07:42:54 +00:00
* Prepare the values passed to the theme_block function to be passed
* into a pluggable template engine . Uses block properties to generate a
* series of template file suggestions . If none are found , the default
* block . tpl . php is used .
2007-08-28 11:35:34 +00:00
*
* Most themes utilize their own copy of page . tpl . php . The default is located
* inside " modules/system/block.tpl.php " . Look in there for the full list of
* variables .
*
* The $variables array contains the following arguments :
* - $block
*
* @ see block . tpl . php
2007-04-27 07:42:54 +00:00
*/
function template_preprocess_block ( & $variables ) {
2007-09-01 05:42:49 +00:00
static $block_counter = array ();
// All blocks get an independent counter for each region.
if ( ! isset ( $block_counter [ $variables [ 'block' ] -> region ])) {
$block_counter [ $variables [ 'block' ] -> region ] = 1 ;
}
// Same with zebra striping.
$variables [ 'block_zebra' ] = ( $block_counter [ $variables [ 'block' ] -> region ] % 2 ) ? 'odd' : 'even' ;
$variables [ 'block_id' ] = $block_counter [ $variables [ 'block' ] -> region ] ++ ;
2007-04-27 07:42:54 +00:00
$variables [ 'template_files' ][] = 'block-' . $variables [ 'block' ] -> region ;
$variables [ 'template_files' ][] = 'block-' . $variables [ 'block' ] -> module ;
$variables [ 'template_files' ][] = 'block-' . $variables [ 'block' ] -> module . '-' . $variables [ 'block' ] -> delta ;
}
2007-07-01 23:15:41 +00:00