webmaster@1
|
1 <?php |
webmaster@5
|
2 // $Id: theme.inc,v 1.415.2.2 2008/03/25 11:55:08 goba Exp $ |
webmaster@1
|
3 |
webmaster@1
|
4 /** |
webmaster@1
|
5 * @file |
webmaster@1
|
6 * The theme system, which controls the output of Drupal. |
webmaster@1
|
7 * |
webmaster@1
|
8 * The theme system allows for nearly all output of the Drupal system to be |
webmaster@1
|
9 * customized by user themes. |
webmaster@1
|
10 * |
webmaster@1
|
11 * @see <a href="http://drupal.org/node/253">Theme system</a> |
webmaster@1
|
12 * @see themeable |
webmaster@1
|
13 */ |
webmaster@1
|
14 |
webmaster@1
|
15 /** |
webmaster@1
|
16 * @name Content markers |
webmaster@1
|
17 * @{ |
webmaster@1
|
18 * Markers used by theme_mark() and node_mark() to designate content. |
webmaster@1
|
19 * @see theme_mark(), node_mark() |
webmaster@1
|
20 */ |
webmaster@1
|
21 define('MARK_READ', 0); |
webmaster@1
|
22 define('MARK_NEW', 1); |
webmaster@1
|
23 define('MARK_UPDATED', 2); |
webmaster@1
|
24 /** |
webmaster@1
|
25 * @} End of "Content markers". |
webmaster@1
|
26 */ |
webmaster@1
|
27 |
webmaster@1
|
28 /** |
webmaster@1
|
29 * Initialize the theme system by loading the theme. |
webmaster@1
|
30 */ |
webmaster@1
|
31 function init_theme() { |
webmaster@1
|
32 global $theme, $user, $custom_theme, $theme_key; |
webmaster@1
|
33 |
webmaster@1
|
34 // If $theme is already set, assume the others are set, too, and do nothing |
webmaster@1
|
35 if (isset($theme)) { |
webmaster@1
|
36 return; |
webmaster@1
|
37 } |
webmaster@1
|
38 |
webmaster@1
|
39 drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); |
webmaster@1
|
40 $themes = list_themes(); |
webmaster@1
|
41 |
webmaster@1
|
42 // Only select the user selected theme if it is available in the |
webmaster@1
|
43 // list of enabled themes. |
webmaster@1
|
44 $theme = !empty($user->theme) && !empty($themes[$user->theme]->status) ? $user->theme : variable_get('theme_default', 'garland'); |
webmaster@1
|
45 |
webmaster@1
|
46 // Allow modules to override the present theme... only select custom theme |
webmaster@1
|
47 // if it is available in the list of installed themes. |
webmaster@1
|
48 $theme = $custom_theme && $themes[$custom_theme] ? $custom_theme : $theme; |
webmaster@1
|
49 |
webmaster@1
|
50 // Store the identifier for retrieving theme settings with. |
webmaster@1
|
51 $theme_key = $theme; |
webmaster@1
|
52 |
webmaster@1
|
53 // Find all our ancestor themes and put them in an array. |
webmaster@1
|
54 $base_theme = array(); |
webmaster@1
|
55 $ancestor = $theme; |
webmaster@1
|
56 while ($ancestor && isset($themes[$ancestor]->base_theme)) { |
webmaster@1
|
57 $base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme]; |
webmaster@1
|
58 $ancestor = $themes[$ancestor]->base_theme; |
webmaster@1
|
59 } |
webmaster@1
|
60 _init_theme($themes[$theme], array_reverse($base_theme)); |
webmaster@1
|
61 } |
webmaster@1
|
62 |
webmaster@1
|
63 /** |
webmaster@1
|
64 * Initialize the theme system given already loaded information. This |
webmaster@1
|
65 * function is useful to initialize a theme when no database is present. |
webmaster@1
|
66 * |
webmaster@1
|
67 * @param $theme |
webmaster@1
|
68 * An object with the following information: |
webmaster@1
|
69 * filename |
webmaster@1
|
70 * The .info file for this theme. The 'path' to |
webmaster@1
|
71 * the theme will be in this file's directory. (Required) |
webmaster@1
|
72 * owner |
webmaster@1
|
73 * The path to the .theme file or the .engine file to load for |
webmaster@1
|
74 * the theme. (Required) |
webmaster@1
|
75 * stylesheet |
webmaster@1
|
76 * The primary stylesheet for the theme. (Optional) |
webmaster@1
|
77 * engine |
webmaster@1
|
78 * The name of theme engine to use. (Optional) |
webmaster@1
|
79 * @param $base_theme |
webmaster@1
|
80 * An optional array of objects that represent the 'base theme' if the |
webmaster@1
|
81 * theme is meant to be derivative of another theme. It requires |
webmaster@1
|
82 * the same information as the $theme object. It should be in |
webmaster@1
|
83 * 'oldest first' order, meaning the top level of the chain will |
webmaster@1
|
84 * be first. |
webmaster@1
|
85 * @param $registry_callback |
webmaster@1
|
86 * The callback to invoke to set the theme registry. |
webmaster@1
|
87 */ |
webmaster@1
|
88 function _init_theme($theme, $base_theme = array(), $registry_callback = '_theme_load_registry') { |
webmaster@1
|
89 global $theme_info, $base_theme_info, $theme_engine, $theme_path; |
webmaster@1
|
90 $theme_info = $theme; |
webmaster@1
|
91 $base_theme_info = $base_theme; |
webmaster@1
|
92 |
webmaster@1
|
93 $theme_path = dirname($theme->filename); |
webmaster@1
|
94 |
webmaster@1
|
95 // Prepare stylesheets from this theme as well as all ancestor themes. |
webmaster@1
|
96 // We work it this way so that we can have child themes override parent |
webmaster@1
|
97 // theme stylesheets easily. |
webmaster@1
|
98 $final_stylesheets = array(); |
webmaster@1
|
99 |
webmaster@1
|
100 // Grab stylesheets from base theme |
webmaster@1
|
101 foreach ($base_theme as $base) { |
webmaster@1
|
102 if (!empty($base->stylesheets)) { |
webmaster@1
|
103 foreach ($base->stylesheets as $media => $stylesheets) { |
webmaster@1
|
104 foreach ($stylesheets as $name => $stylesheet) { |
webmaster@1
|
105 $final_stylesheets[$media][$name] = $stylesheet; |
webmaster@1
|
106 } |
webmaster@1
|
107 } |
webmaster@1
|
108 } |
webmaster@1
|
109 } |
webmaster@1
|
110 |
webmaster@1
|
111 // Add stylesheets used by this theme. |
webmaster@1
|
112 if (!empty($theme->stylesheets)) { |
webmaster@1
|
113 foreach ($theme->stylesheets as $media => $stylesheets) { |
webmaster@1
|
114 foreach ($stylesheets as $name => $stylesheet) { |
webmaster@1
|
115 $final_stylesheets[$media][$name] = $stylesheet; |
webmaster@1
|
116 } |
webmaster@1
|
117 } |
webmaster@1
|
118 } |
webmaster@1
|
119 |
webmaster@1
|
120 // And now add the stylesheets properly |
webmaster@1
|
121 foreach ($final_stylesheets as $media => $stylesheets) { |
webmaster@1
|
122 foreach ($stylesheets as $stylesheet) { |
webmaster@1
|
123 drupal_add_css($stylesheet, 'theme', $media); |
webmaster@1
|
124 } |
webmaster@1
|
125 } |
webmaster@1
|
126 |
webmaster@1
|
127 // Do basically the same as the above for scripts |
webmaster@1
|
128 $final_scripts = array(); |
webmaster@1
|
129 |
webmaster@1
|
130 // Grab scripts from base theme |
webmaster@1
|
131 foreach ($base_theme as $base) { |
webmaster@1
|
132 if (!empty($base->scripts)) { |
webmaster@1
|
133 foreach ($base->scripts as $name => $script) { |
webmaster@1
|
134 $final_scripts[$name] = $script; |
webmaster@1
|
135 } |
webmaster@1
|
136 } |
webmaster@1
|
137 } |
webmaster@1
|
138 |
webmaster@1
|
139 // Add scripts used by this theme. |
webmaster@1
|
140 if (!empty($theme->scripts)) { |
webmaster@1
|
141 foreach ($theme->scripts as $name => $script) { |
webmaster@1
|
142 $final_scripts[$name] = $script; |
webmaster@1
|
143 } |
webmaster@1
|
144 } |
webmaster@1
|
145 |
webmaster@1
|
146 // Add scripts used by this theme. |
webmaster@1
|
147 foreach ($final_scripts as $script) { |
webmaster@1
|
148 drupal_add_js($script, 'theme'); |
webmaster@1
|
149 } |
webmaster@1
|
150 |
webmaster@1
|
151 $theme_engine = NULL; |
webmaster@1
|
152 |
webmaster@1
|
153 // Initialize the theme. |
webmaster@1
|
154 if (isset($theme->engine)) { |
webmaster@1
|
155 // Include the engine. |
webmaster@1
|
156 include_once './'. $theme->owner; |
webmaster@1
|
157 |
webmaster@1
|
158 $theme_engine = $theme->engine; |
webmaster@1
|
159 if (function_exists($theme_engine .'_init')) { |
webmaster@1
|
160 foreach ($base_theme as $base) { |
webmaster@1
|
161 call_user_func($theme_engine .'_init', $base); |
webmaster@1
|
162 } |
webmaster@1
|
163 call_user_func($theme_engine .'_init', $theme); |
webmaster@1
|
164 } |
webmaster@1
|
165 } |
webmaster@1
|
166 else { |
webmaster@1
|
167 // include non-engine theme files |
webmaster@1
|
168 foreach ($base_theme as $base) { |
webmaster@1
|
169 // Include the theme file or the engine. |
webmaster@1
|
170 if (!empty($base->owner)) { |
webmaster@1
|
171 include_once './'. $base->owner; |
webmaster@1
|
172 } |
webmaster@1
|
173 } |
webmaster@1
|
174 // and our theme gets one too. |
webmaster@1
|
175 if (!empty($theme->owner)) { |
webmaster@1
|
176 include_once './'. $theme->owner; |
webmaster@1
|
177 } |
webmaster@1
|
178 } |
webmaster@1
|
179 |
webmaster@1
|
180 $registry_callback($theme, $base_theme, $theme_engine); |
webmaster@1
|
181 } |
webmaster@1
|
182 |
webmaster@1
|
183 /** |
webmaster@1
|
184 * Retrieve the stored theme registry. If the theme registry is already |
webmaster@1
|
185 * in memory it will be returned; otherwise it will attempt to load the |
webmaster@1
|
186 * registry from cache. If this fails, it will construct the registry and |
webmaster@1
|
187 * cache it. |
webmaster@1
|
188 */ |
webmaster@1
|
189 function theme_get_registry($registry = NULL) { |
webmaster@1
|
190 static $theme_registry = NULL; |
webmaster@1
|
191 if (isset($registry)) { |
webmaster@1
|
192 $theme_registry = $registry; |
webmaster@1
|
193 } |
webmaster@1
|
194 |
webmaster@1
|
195 return $theme_registry; |
webmaster@1
|
196 } |
webmaster@1
|
197 |
webmaster@1
|
198 /** |
webmaster@1
|
199 * Store the theme registry in memory. |
webmaster@1
|
200 */ |
webmaster@1
|
201 function _theme_set_registry($registry) { |
webmaster@1
|
202 // Pass through for setting of static variable. |
webmaster@1
|
203 return theme_get_registry($registry); |
webmaster@1
|
204 } |
webmaster@1
|
205 |
webmaster@1
|
206 /** |
webmaster@1
|
207 * Get the theme_registry cache from the database; if it doesn't exist, build |
webmaster@1
|
208 * it. |
webmaster@1
|
209 * |
webmaster@1
|
210 * @param $theme |
webmaster@1
|
211 * The loaded $theme object. |
webmaster@1
|
212 * @param $base_theme |
webmaster@1
|
213 * An array of loaded $theme objects representing the ancestor themes in |
webmaster@1
|
214 * oldest first order. |
webmaster@1
|
215 * @param theme_engine |
webmaster@1
|
216 * The name of the theme engine. |
webmaster@1
|
217 */ |
webmaster@1
|
218 function _theme_load_registry($theme, $base_theme = NULL, $theme_engine = NULL) { |
webmaster@1
|
219 // Check the theme registry cache; if it exists, use it. |
webmaster@1
|
220 $cache = cache_get("theme_registry:$theme->name", 'cache'); |
webmaster@1
|
221 if (isset($cache->data)) { |
webmaster@1
|
222 $registry = $cache->data; |
webmaster@1
|
223 } |
webmaster@1
|
224 else { |
webmaster@1
|
225 // If not, build one and cache it. |
webmaster@1
|
226 $registry = _theme_build_registry($theme, $base_theme, $theme_engine); |
webmaster@1
|
227 _theme_save_registry($theme, $registry); |
webmaster@1
|
228 } |
webmaster@1
|
229 _theme_set_registry($registry); |
webmaster@1
|
230 } |
webmaster@1
|
231 |
webmaster@1
|
232 /** |
webmaster@1
|
233 * Write the theme_registry cache into the database. |
webmaster@1
|
234 */ |
webmaster@1
|
235 function _theme_save_registry($theme, $registry) { |
webmaster@1
|
236 cache_set("theme_registry:$theme->name", $registry); |
webmaster@1
|
237 } |
webmaster@1
|
238 |
webmaster@1
|
239 /** |
webmaster@1
|
240 * Force the system to rebuild the theme registry; this should be called |
webmaster@1
|
241 * when modules are added to the system, or when a dynamic system needs |
webmaster@1
|
242 * to add more theme hooks. |
webmaster@1
|
243 */ |
webmaster@1
|
244 function drupal_rebuild_theme_registry() { |
webmaster@1
|
245 cache_clear_all('theme_registry', 'cache', TRUE); |
webmaster@1
|
246 } |
webmaster@1
|
247 |
webmaster@1
|
248 /** |
webmaster@1
|
249 * Process a single invocation of the theme hook. $type will be one |
webmaster@1
|
250 * of 'module', 'theme_engine' or 'theme' and it tells us some |
webmaster@1
|
251 * important information. |
webmaster@1
|
252 * |
webmaster@1
|
253 * Because $cache is a reference, the cache will be continually |
webmaster@1
|
254 * expanded upon; new entries will replace old entries in the |
webmaster@1
|
255 * array_merge, but we are careful to ensure some data is carried |
webmaster@1
|
256 * forward, such as the arguments a theme hook needs. |
webmaster@1
|
257 * |
webmaster@1
|
258 * An override flag can be set for preprocess functions. When detected the |
webmaster@1
|
259 * cached preprocessors for the hook will not be merged with the newly set. |
webmaster@1
|
260 * This can be useful to themes and theme engines by giving them more control |
webmaster@1
|
261 * over how and when the preprocess functions are run. |
webmaster@1
|
262 */ |
webmaster@1
|
263 function _theme_process_registry(&$cache, $name, $type, $theme, $path) { |
webmaster@1
|
264 $function = $name .'_theme'; |
webmaster@1
|
265 if (function_exists($function)) { |
webmaster@1
|
266 $result = $function($cache, $type, $theme, $path); |
webmaster@1
|
267 |
webmaster@1
|
268 foreach ($result as $hook => $info) { |
webmaster@1
|
269 $result[$hook]['type'] = $type; |
webmaster@1
|
270 $result[$hook]['theme path'] = $path; |
webmaster@1
|
271 // if function and file are left out, default to standard naming |
webmaster@1
|
272 // conventions. |
webmaster@1
|
273 if (!isset($info['template']) && !isset($info['function'])) { |
webmaster@1
|
274 $result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name .'_') . $hook; |
webmaster@1
|
275 } |
webmaster@1
|
276 // If a path is set in the info, use what was set. Otherwise use the |
webmaster@1
|
277 // default path. This is mostly so system.module can declare theme |
webmaster@1
|
278 // functions on behalf of core .include files. |
webmaster@1
|
279 // All files are included to be safe. Conditionally included |
webmaster@1
|
280 // files can prevent them from getting registered. |
webmaster@1
|
281 if (isset($info['file']) && !isset($info['path'])) { |
webmaster@1
|
282 $result[$hook]['file'] = $path .'/'. $info['file']; |
webmaster@1
|
283 include_once($result[$hook]['file']); |
webmaster@1
|
284 } |
webmaster@1
|
285 elseif (isset($info['file']) && isset($info['path'])) { |
webmaster@1
|
286 include_once($info['path'] .'/'. $info['file']); |
webmaster@1
|
287 } |
webmaster@1
|
288 |
webmaster@1
|
289 if (isset($info['template']) && !isset($info['path'])) { |
webmaster@1
|
290 $result[$hook]['template'] = $path .'/'. $info['template']; |
webmaster@1
|
291 } |
webmaster@1
|
292 // If 'arguments' have been defined previously, carry them forward. |
webmaster@1
|
293 // This should happen if a theme overrides a Drupal defined theme |
webmaster@1
|
294 // function, for example. |
webmaster@1
|
295 if (!isset($info['arguments']) && isset($cache[$hook])) { |
webmaster@1
|
296 $result[$hook]['arguments'] = $cache[$hook]['arguments']; |
webmaster@1
|
297 } |
webmaster@1
|
298 // Likewise with theme paths. These are used for template naming suggestions. |
webmaster@1
|
299 // Theme implementations can occur in multiple paths. Suggestions should follow. |
webmaster@1
|
300 if (!isset($info['theme paths']) && isset($cache[$hook])) { |
webmaster@1
|
301 $result[$hook]['theme paths'] = $cache[$hook]['theme paths']; |
webmaster@1
|
302 } |
webmaster@1
|
303 // Check for sub-directories. |
webmaster@1
|
304 $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path; |
webmaster@1
|
305 |
webmaster@1
|
306 // Check for default _preprocess_ functions. Ensure arrayness. |
webmaster@1
|
307 if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) { |
webmaster@1
|
308 $info['preprocess functions'] = array(); |
webmaster@1
|
309 $prefixes = array(); |
webmaster@1
|
310 if ($type == 'module') { |
webmaster@1
|
311 // Default preprocessor prefix. |
webmaster@1
|
312 $prefixes[] = 'template'; |
webmaster@1
|
313 // Add all modules so they can intervene with their own preprocessors. This allows them |
webmaster@1
|
314 // to provide preprocess functions even if they are not the owner of the current hook. |
webmaster@1
|
315 $prefixes += module_list(); |
webmaster@1
|
316 } |
webmaster@1
|
317 elseif ($type == 'theme_engine') { |
webmaster@1
|
318 // Theme engines get an extra set that come before the normally named preprocessors. |
webmaster@1
|
319 $prefixes[] = $name .'_engine'; |
webmaster@1
|
320 // The theme engine also registers on behalf of the theme. The theme or engine name can be used. |
webmaster@1
|
321 $prefixes[] = $name; |
webmaster@1
|
322 $prefixes[] = $theme; |
webmaster@1
|
323 } |
webmaster@1
|
324 else { |
webmaster@1
|
325 // This applies when the theme manually registers their own preprocessors. |
webmaster@1
|
326 $prefixes[] = $name; |
webmaster@1
|
327 } |
webmaster@1
|
328 |
webmaster@1
|
329 foreach ($prefixes as $prefix) { |
webmaster@1
|
330 if (function_exists($prefix .'_preprocess')) { |
webmaster@1
|
331 $info['preprocess functions'][] = $prefix .'_preprocess'; |
webmaster@1
|
332 } |
webmaster@1
|
333 if (function_exists($prefix .'_preprocess_'. $hook)) { |
webmaster@1
|
334 $info['preprocess functions'][] = $prefix .'_preprocess_'. $hook; |
webmaster@1
|
335 } |
webmaster@1
|
336 } |
webmaster@1
|
337 } |
webmaster@1
|
338 // Check for the override flag and prevent the cached preprocess functions from being used. |
webmaster@1
|
339 // This allows themes or theme engines to remove preprocessors set earlier in the registry build. |
webmaster@1
|
340 if (!empty($info['override preprocess functions'])) { |
webmaster@1
|
341 // Flag not needed inside the registry. |
webmaster@1
|
342 unset($result[$hook]['override preprocess functions']); |
webmaster@1
|
343 } |
webmaster@1
|
344 elseif (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions'])) { |
webmaster@1
|
345 $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']); |
webmaster@1
|
346 } |
webmaster@1
|
347 $result[$hook]['preprocess functions'] = $info['preprocess functions']; |
webmaster@1
|
348 } |
webmaster@1
|
349 |
webmaster@1
|
350 // Merge the newly created theme hooks into the existing cache. |
webmaster@1
|
351 $cache = array_merge($cache, $result); |
webmaster@1
|
352 } |
webmaster@1
|
353 } |
webmaster@1
|
354 |
webmaster@1
|
355 /** |
webmaster@1
|
356 * Rebuild the hook theme_registry cache. |
webmaster@1
|
357 * |
webmaster@1
|
358 * @param $theme |
webmaster@1
|
359 * The loaded $theme object. |
webmaster@1
|
360 * @param $base_theme |
webmaster@1
|
361 * An array of loaded $theme objects representing the ancestor themes in |
webmaster@1
|
362 * oldest first order. |
webmaster@1
|
363 * @param theme_engine |
webmaster@1
|
364 * The name of the theme engine. |
webmaster@1
|
365 */ |
webmaster@1
|
366 function _theme_build_registry($theme, $base_theme, $theme_engine) { |
webmaster@1
|
367 $cache = array(); |
webmaster@1
|
368 // First, process the theme hooks advertised by modules. This will |
webmaster@1
|
369 // serve as the basic registry. |
webmaster@1
|
370 foreach (module_implements('theme') as $module) { |
webmaster@1
|
371 _theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module)); |
webmaster@1
|
372 } |
webmaster@1
|
373 |
webmaster@1
|
374 // Process each base theme. |
webmaster@1
|
375 foreach ($base_theme as $base) { |
webmaster@1
|
376 // If the theme uses a theme engine, process its hooks. |
webmaster@1
|
377 $base_path = dirname($base->filename); |
webmaster@1
|
378 if ($theme_engine) { |
webmaster@1
|
379 _theme_process_registry($cache, $theme_engine, 'base_theme_engine', $base->name, $base_path); |
webmaster@1
|
380 } |
webmaster@1
|
381 _theme_process_registry($cache, $base->name, 'base_theme', $base->name, $base_path); |
webmaster@1
|
382 } |
webmaster@1
|
383 |
webmaster@1
|
384 // And then the same thing, but for the theme. |
webmaster@1
|
385 if ($theme_engine) { |
webmaster@1
|
386 _theme_process_registry($cache, $theme_engine, 'theme_engine', $theme->name, dirname($theme->filename)); |
webmaster@1
|
387 } |
webmaster@1
|
388 |
webmaster@1
|
389 // Finally, hooks provided by the theme itself. |
webmaster@1
|
390 _theme_process_registry($cache, $theme->name, 'theme', $theme->name, dirname($theme->filename)); |
webmaster@1
|
391 |
webmaster@1
|
392 // Let modules alter the registry |
webmaster@1
|
393 drupal_alter('theme_registry', $cache); |
webmaster@1
|
394 return $cache; |
webmaster@1
|
395 } |
webmaster@1
|
396 |
webmaster@1
|
397 /** |
webmaster@1
|
398 * Provides a list of currently available themes. |
webmaster@1
|
399 * |
webmaster@1
|
400 * If the database is active then it will be retrieved from the database. |
webmaster@1
|
401 * Otherwise it will retrieve a new list. |
webmaster@1
|
402 * |
webmaster@1
|
403 * @param $refresh |
webmaster@1
|
404 * Whether to reload the list of themes from the database. |
webmaster@1
|
405 * @return |
webmaster@1
|
406 * An array of the currently available themes. |
webmaster@1
|
407 */ |
webmaster@1
|
408 function list_themes($refresh = FALSE) { |
webmaster@1
|
409 static $list = array(); |
webmaster@1
|
410 |
webmaster@1
|
411 if ($refresh) { |
webmaster@1
|
412 $list = array(); |
webmaster@1
|
413 } |
webmaster@1
|
414 |
webmaster@1
|
415 if (empty($list)) { |
webmaster@1
|
416 $list = array(); |
webmaster@1
|
417 $themes = array(); |
webmaster@1
|
418 // Extract from the database only when it is available. |
webmaster@1
|
419 // Also check that the site is not in the middle of an install or update. |
webmaster@1
|
420 if (db_is_active() && !defined('MAINTENANCE_MODE')) { |
webmaster@1
|
421 $result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme'); |
webmaster@1
|
422 while ($theme = db_fetch_object($result)) { |
webmaster@1
|
423 if (file_exists($theme->filename)) { |
webmaster@1
|
424 $theme->info = unserialize($theme->info); |
webmaster@1
|
425 $themes[] = $theme; |
webmaster@1
|
426 } |
webmaster@1
|
427 } |
webmaster@1
|
428 } |
webmaster@1
|
429 else { |
webmaster@1
|
430 // Scan the installation when the database should not be read. |
webmaster@1
|
431 $themes = _system_theme_data(); |
webmaster@1
|
432 } |
webmaster@1
|
433 |
webmaster@1
|
434 foreach ($themes as $theme) { |
webmaster@1
|
435 foreach ($theme->info['stylesheets'] as $media => $stylesheets) { |
webmaster@1
|
436 foreach ($stylesheets as $stylesheet => $path) { |
webmaster@1
|
437 if (file_exists($path)) { |
webmaster@1
|
438 $theme->stylesheets[$media][$stylesheet] = $path; |
webmaster@1
|
439 } |
webmaster@1
|
440 } |
webmaster@1
|
441 } |
webmaster@1
|
442 foreach ($theme->info['scripts'] as $script => $path) { |
webmaster@1
|
443 if (file_exists($path)) { |
webmaster@1
|
444 $theme->scripts[$script] = $path; |
webmaster@1
|
445 } |
webmaster@1
|
446 } |
webmaster@1
|
447 if (isset($theme->info['engine'])) { |
webmaster@1
|
448 $theme->engine = $theme->info['engine']; |
webmaster@1
|
449 } |
webmaster@1
|
450 if (isset($theme->info['base theme'])) { |
webmaster@1
|
451 $theme->base_theme = $theme->info['base theme']; |
webmaster@1
|
452 } |
webmaster@1
|
453 // Status is normally retrieved from the database. Add zero values when |
webmaster@1
|
454 // read from the installation directory to prevent notices. |
webmaster@1
|
455 if (!isset($theme->status)) { |
webmaster@1
|
456 $theme->status = 0; |
webmaster@1
|
457 } |
webmaster@1
|
458 $list[$theme->name] = $theme; |
webmaster@1
|
459 } |
webmaster@1
|
460 } |
webmaster@1
|
461 |
webmaster@1
|
462 return $list; |
webmaster@1
|
463 } |
webmaster@1
|
464 |
webmaster@1
|
465 /** |
webmaster@1
|
466 * Generate the themed output. |
webmaster@1
|
467 * |
webmaster@1
|
468 * All requests for theme hooks must go through this function. It examines |
webmaster@1
|
469 * the request and routes it to the appropriate theme function. The theme |
webmaster@1
|
470 * registry is checked to determine which implementation to use, which may |
webmaster@1
|
471 * be a function or a template. |
webmaster@1
|
472 * |
webmaster@1
|
473 * If the implementation is a function, it is executed and its return value |
webmaster@1
|
474 * passed along. |
webmaster@1
|
475 * |
webmaster@1
|
476 * If the implementation is a template, the arguments are converted to a |
webmaster@1
|
477 * $variables array. This array is then modified by the module implementing |
webmaster@1
|
478 * the hook, theme engine (if applicable) and the theme. The following |
webmaster@1
|
479 * functions may be used to modify the $variables array. They are processed in |
webmaster@1
|
480 * this order when available: |
webmaster@1
|
481 * |
webmaster@1
|
482 * - template_preprocess(&$variables) |
webmaster@1
|
483 * This sets a default set of variables for all template implementations. |
webmaster@1
|
484 * |
webmaster@1
|
485 * - template_preprocess_HOOK(&$variables) |
webmaster@1
|
486 * This is the first preprocessor called specific to the hook; it should be |
webmaster@1
|
487 * implemented by the module that registers it. |
webmaster@1
|
488 * |
webmaster@1
|
489 * - MODULE_preprocess(&$variables) |
webmaster@1
|
490 * This will be called for all templates; it should only be used if there |
webmaster@1
|
491 * is a real need. It's purpose is similar to template_preprocess(). |
webmaster@1
|
492 * |
webmaster@1
|
493 * - MODULE_preprocess_HOOK(&$variables) |
webmaster@1
|
494 * This is for modules that want to alter or provide extra variables for |
webmaster@1
|
495 * theming hooks not registered to itself. For example, if a module named |
webmaster@1
|
496 * "foo" wanted to alter the $submitted variable for the hook "node" a |
webmaster@1
|
497 * preprocess function of foo_preprocess_node() can be created to intercept |
webmaster@1
|
498 * and alter the variable. |
webmaster@1
|
499 * |
webmaster@1
|
500 * - ENGINE_engine_preprocess(&$variables) |
webmaster@1
|
501 * This function should only be implemented by theme engines and exists |
webmaster@1
|
502 * so that it can set necessary variables for all hooks. |
webmaster@1
|
503 * |
webmaster@1
|
504 * - ENGINE_engine_preprocess_HOOK(&$variables) |
webmaster@1
|
505 * This is the same as the previous function, but it is called for a single |
webmaster@1
|
506 * theming hook. |
webmaster@1
|
507 * |
webmaster@1
|
508 * - ENGINE_preprocess(&$variables) |
webmaster@1
|
509 * This is meant to be used by themes that utilize a theme engine. It is |
webmaster@1
|
510 * provided so that the preprocessor is not locked into a specific theme. |
webmaster@1
|
511 * This makes it easy to share and transport code but theme authors must be |
webmaster@1
|
512 * careful to prevent fatal re-declaration errors when using sub-themes that |
webmaster@1
|
513 * have their own preprocessor named exactly the same as its base theme. In |
webmaster@1
|
514 * the default theme engine (PHPTemplate), sub-themes will load their own |
webmaster@1
|
515 * template.php file in addition to the one used for its parent theme. This |
webmaster@1
|
516 * increases the risk for these errors. A good practice is to use the engine |
webmaster@1
|
517 * name for the base theme and the theme name for the sub-themes to minimize |
webmaster@1
|
518 * this possibility. |
webmaster@1
|
519 * |
webmaster@1
|
520 * - ENGINE_preprocess_HOOK(&$variables) |
webmaster@1
|
521 * The same applies from the previous function, but it is called for a |
webmaster@1
|
522 * specific hook. |
webmaster@1
|
523 * |
webmaster@1
|
524 * - THEME_preprocess(&$variables) |
webmaster@1
|
525 * These functions are based upon the raw theme; they should primarily be |
webmaster@1
|
526 * used by themes that do not use an engine or by sub-themes. It serves the |
webmaster@1
|
527 * same purpose as ENGINE_preprocess(). |
webmaster@1
|
528 * |
webmaster@1
|
529 * - THEME_preprocess_HOOK(&$variables) |
webmaster@1
|
530 * The same applies from the previous function, but it is called for a |
webmaster@1
|
531 * specific hook. |
webmaster@1
|
532 * |
webmaster@1
|
533 * There are two special variables that these hooks can set: |
webmaster@1
|
534 * 'template_file' and 'template_files'. These will be merged together |
webmaster@1
|
535 * to form a list of 'suggested' alternate template files to use, in |
webmaster@1
|
536 * reverse order of priority. template_file will always be a higher |
webmaster@1
|
537 * priority than items in template_files. theme() will then look for these |
webmaster@1
|
538 * files, one at a time, and use the first one |
webmaster@1
|
539 * that exists. |
webmaster@1
|
540 * @param $hook |
webmaster@1
|
541 * The name of the theme function to call. May be an array, in which |
webmaster@1
|
542 * case the first hook that actually has an implementation registered |
webmaster@1
|
543 * will be used. This can be used to choose 'fallback' theme implementations, |
webmaster@1
|
544 * so that if the specific theme hook isn't implemented anywhere, a more |
webmaster@1
|
545 * generic one will be used. This can allow themes to create specific theme |
webmaster@1
|
546 * implementations for named objects. |
webmaster@1
|
547 * @param ... |
webmaster@1
|
548 * Additional arguments to pass along to the theme function. |
webmaster@1
|
549 * @return |
webmaster@1
|
550 * An HTML string that generates the themed output. |
webmaster@1
|
551 */ |
webmaster@1
|
552 function theme() { |
webmaster@1
|
553 $args = func_get_args(); |
webmaster@1
|
554 $hook = array_shift($args); |
webmaster@1
|
555 |
webmaster@1
|
556 static $hooks = NULL; |
webmaster@1
|
557 if (!isset($hooks)) { |
webmaster@1
|
558 init_theme(); |
webmaster@1
|
559 $hooks = theme_get_registry(); |
webmaster@1
|
560 } |
webmaster@1
|
561 |
webmaster@1
|
562 if (is_array($hook)) { |
webmaster@1
|
563 foreach ($hook as $candidate) { |
webmaster@1
|
564 if (isset($hooks[$candidate])) { |
webmaster@1
|
565 break; |
webmaster@1
|
566 } |
webmaster@1
|
567 } |
webmaster@1
|
568 $hook = $candidate; |
webmaster@1
|
569 } |
webmaster@1
|
570 |
webmaster@1
|
571 if (!isset($hooks[$hook])) { |
webmaster@1
|
572 return; |
webmaster@1
|
573 } |
webmaster@1
|
574 |
webmaster@1
|
575 $info = $hooks[$hook]; |
webmaster@1
|
576 global $theme_path; |
webmaster@1
|
577 $temp = $theme_path; |
webmaster@1
|
578 // point path_to_theme() to the currently used theme path: |
webmaster@1
|
579 $theme_path = $hooks[$hook]['theme path']; |
webmaster@1
|
580 |
webmaster@1
|
581 // Include a file if the theme function or preprocess function is held elsewhere. |
webmaster@1
|
582 if (!empty($info['file'])) { |
webmaster@1
|
583 $include_file = $info['file']; |
webmaster@1
|
584 if (isset($info['path'])) { |
webmaster@1
|
585 $include_file = $info['path'] .'/'. $include_file; |
webmaster@1
|
586 } |
webmaster@1
|
587 include_once($include_file); |
webmaster@1
|
588 } |
webmaster@1
|
589 if (isset($info['function'])) { |
webmaster@1
|
590 // The theme call is a function. |
webmaster@1
|
591 $output = call_user_func_array($info['function'], $args); |
webmaster@1
|
592 } |
webmaster@1
|
593 else { |
webmaster@1
|
594 // The theme call is a template. |
webmaster@1
|
595 $variables = array( |
webmaster@1
|
596 'template_files' => array() |
webmaster@1
|
597 ); |
webmaster@1
|
598 if (!empty($info['arguments'])) { |
webmaster@1
|
599 $count = 0; |
webmaster@1
|
600 foreach ($info['arguments'] as $name => $default) { |
webmaster@1
|
601 $variables[$name] = isset($args[$count]) ? $args[$count] : $default; |
webmaster@1
|
602 $count++; |
webmaster@1
|
603 } |
webmaster@1
|
604 } |
webmaster@1
|
605 |
webmaster@1
|
606 // default render function and extension. |
webmaster@1
|
607 $render_function = 'theme_render_template'; |
webmaster@1
|
608 $extension = '.tpl.php'; |
webmaster@1
|
609 |
webmaster@1
|
610 // Run through the theme engine variables, if necessary |
webmaster@1
|
611 global $theme_engine; |
webmaster@1
|
612 if (isset($theme_engine)) { |
webmaster@1
|
613 // If theme or theme engine is implementing this, it may have |
webmaster@1
|
614 // a different extension and a different renderer. |
webmaster@1
|
615 if ($hooks[$hook]['type'] != 'module') { |
webmaster@1
|
616 if (function_exists($theme_engine .'_render_template')) { |
webmaster@1
|
617 $render_function = $theme_engine .'_render_template'; |
webmaster@1
|
618 } |
webmaster@1
|
619 $extension_function = $theme_engine .'_extension'; |
webmaster@1
|
620 if (function_exists($extension_function)) { |
webmaster@1
|
621 $extension = $extension_function(); |
webmaster@1
|
622 } |
webmaster@1
|
623 } |
webmaster@1
|
624 } |
webmaster@1
|
625 |
webmaster@1
|
626 if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) { |
webmaster@1
|
627 // This construct ensures that we can keep a reference through |
webmaster@1
|
628 // call_user_func_array. |
webmaster@1
|
629 $args = array(&$variables, $hook); |
webmaster@1
|
630 foreach ($info['preprocess functions'] as $preprocess_function) { |
webmaster@1
|
631 if (function_exists($preprocess_function)) { |
webmaster@1
|
632 call_user_func_array($preprocess_function, $args); |
webmaster@1
|
633 } |
webmaster@1
|
634 } |
webmaster@1
|
635 } |
webmaster@1
|
636 |
webmaster@1
|
637 // Get suggestions for alternate templates out of the variables |
webmaster@1
|
638 // that were set. This lets us dynamically choose a template |
webmaster@1
|
639 // from a list. The order is FILO, so this array is ordered from |
webmaster@1
|
640 // least appropriate first to most appropriate last. |
webmaster@1
|
641 $suggestions = array(); |
webmaster@1
|
642 |
webmaster@1
|
643 if (isset($variables['template_files'])) { |
webmaster@1
|
644 $suggestions = $variables['template_files']; |
webmaster@1
|
645 } |
webmaster@1
|
646 if (isset($variables['template_file'])) { |
webmaster@1
|
647 $suggestions[] = $variables['template_file']; |
webmaster@1
|
648 } |
webmaster@1
|
649 |
webmaster@1
|
650 if ($suggestions) { |
webmaster@1
|
651 $template_file = drupal_discover_template($info['theme paths'], $suggestions, $extension); |
webmaster@1
|
652 } |
webmaster@1
|
653 |
webmaster@1
|
654 if (empty($template_file)) { |
webmaster@1
|
655 $template_file = $hooks[$hook]['template'] . $extension; |
webmaster@1
|
656 if (isset($hooks[$hook]['path'])) { |
webmaster@1
|
657 $template_file = $hooks[$hook]['path'] .'/'. $template_file; |
webmaster@1
|
658 } |
webmaster@1
|
659 } |
webmaster@1
|
660 $output = $render_function($template_file, $variables); |
webmaster@1
|
661 } |
webmaster@1
|
662 // restore path_to_theme() |
webmaster@1
|
663 $theme_path = $temp; |
webmaster@1
|
664 return $output; |
webmaster@1
|
665 } |
webmaster@1
|
666 |
webmaster@1
|
667 /** |
webmaster@1
|
668 * Choose which template file to actually render. These are all suggested |
webmaster@1
|
669 * templates from themes and modules. Theming implementations can occur on |
webmaster@1
|
670 * multiple levels. All paths are checked to account for this. |
webmaster@1
|
671 */ |
webmaster@1
|
672 function drupal_discover_template($paths, $suggestions, $extension = '.tpl.php') { |
webmaster@1
|
673 global $theme_engine; |
webmaster@1
|
674 |
webmaster@1
|
675 // Loop through all paths and suggestions in FIFO order. |
webmaster@1
|
676 $suggestions = array_reverse($suggestions); |
webmaster@1
|
677 $paths = array_reverse($paths); |
webmaster@1
|
678 foreach ($suggestions as $suggestion) { |
webmaster@1
|
679 if (!empty($suggestion)) { |
webmaster@1
|
680 foreach ($paths as $path) { |
webmaster@1
|
681 if (file_exists($file = $path .'/'. $suggestion . $extension)) { |
webmaster@1
|
682 return $file; |
webmaster@1
|
683 } |
webmaster@1
|
684 } |
webmaster@1
|
685 } |
webmaster@1
|
686 } |
webmaster@1
|
687 } |
webmaster@1
|
688 |
webmaster@1
|
689 /** |
webmaster@1
|
690 * Return the path to the currently selected theme. |
webmaster@1
|
691 */ |
webmaster@1
|
692 function path_to_theme() { |
webmaster@1
|
693 global $theme_path; |
webmaster@1
|
694 |
webmaster@1
|
695 if (!isset($theme_path)) { |
webmaster@1
|
696 init_theme(); |
webmaster@1
|
697 } |
webmaster@1
|
698 |
webmaster@1
|
699 return $theme_path; |
webmaster@1
|
700 } |
webmaster@1
|
701 |
webmaster@1
|
702 /** |
webmaster@1
|
703 * Find overridden theme functions. Called by themes and/or theme engines to |
webmaster@1
|
704 * easily discover theme functions. |
webmaster@1
|
705 * |
webmaster@1
|
706 * @param $cache |
webmaster@1
|
707 * The existing cache of theme hooks to test against. |
webmaster@1
|
708 * @param $prefixes |
webmaster@1
|
709 * An array of prefixes to test, in reverse order of importance. |
webmaster@1
|
710 * |
webmaster@1
|
711 * @return $templates |
webmaster@1
|
712 * The functions found, suitable for returning from hook_theme; |
webmaster@1
|
713 */ |
webmaster@1
|
714 function drupal_find_theme_functions($cache, $prefixes) { |
webmaster@1
|
715 $templates = array(); |
webmaster@1
|
716 $functions = get_defined_functions(); |
webmaster@1
|
717 |
webmaster@1
|
718 foreach ($cache as $hook => $info) { |
webmaster@1
|
719 foreach ($prefixes as $prefix) { |
webmaster@1
|
720 if (!empty($info['pattern'])) { |
webmaster@1
|
721 $matches = preg_grep('/^'. $prefix .'_'. $info['pattern'] .'/', $functions['user']); |
webmaster@1
|
722 if ($matches) { |
webmaster@1
|
723 foreach ($matches as $match) { |
webmaster@1
|
724 $new_hook = str_replace($prefix .'_', '', $match); |
webmaster@1
|
725 $templates[$new_hook] = array( |
webmaster@1
|
726 'function' => $match, |
webmaster@1
|
727 'arguments' => $info['arguments'], |
webmaster@1
|
728 ); |
webmaster@1
|
729 } |
webmaster@1
|
730 } |
webmaster@1
|
731 } |
webmaster@1
|
732 if (function_exists($prefix .'_'. $hook)) { |
webmaster@1
|
733 $templates[$hook] = array( |
webmaster@1
|
734 'function' => $prefix .'_'. $hook, |
webmaster@1
|
735 ); |
webmaster@1
|
736 } |
webmaster@1
|
737 } |
webmaster@1
|
738 } |
webmaster@1
|
739 |
webmaster@1
|
740 return $templates; |
webmaster@1
|
741 } |
webmaster@1
|
742 |
webmaster@1
|
743 /** |
webmaster@1
|
744 * Find overridden theme templates. Called by themes and/or theme engines to |
webmaster@1
|
745 * easily discover templates. |
webmaster@1
|
746 * |
webmaster@1
|
747 * @param $cache |
webmaster@1
|
748 * The existing cache of theme hooks to test against. |
webmaster@1
|
749 * @param $extension |
webmaster@1
|
750 * The extension that these templates will have. |
webmaster@1
|
751 * @param $path |
webmaster@1
|
752 * The path to search. |
webmaster@1
|
753 */ |
webmaster@1
|
754 function drupal_find_theme_templates($cache, $extension, $path) { |
webmaster@1
|
755 $templates = array(); |
webmaster@1
|
756 |
webmaster@1
|
757 // Collect paths to all sub-themes grouped by base themes. These will be |
webmaster@1
|
758 // used for filtering. This allows base themes to have sub-themes in its |
webmaster@1
|
759 // folder hierarchy without affecting the base themes template discovery. |
webmaster@1
|
760 $theme_paths = array(); |
webmaster@1
|
761 foreach (list_themes() as $theme_info) { |
webmaster@1
|
762 if (!empty($theme_info->base_theme)) { |
webmaster@1
|
763 $theme_paths[$theme_info->base_theme][$theme_info->name] = dirname($theme_info->filename); |
webmaster@1
|
764 } |
webmaster@1
|
765 } |
webmaster@1
|
766 foreach ($theme_paths as $basetheme => $subthemes) { |
webmaster@1
|
767 foreach ($subthemes as $subtheme => $subtheme_path) { |
webmaster@1
|
768 if (isset($theme_paths[$subtheme])) { |
webmaster@1
|
769 $theme_paths[$basetheme] = array_merge($theme_paths[$basetheme], $theme_paths[$subtheme]); |
webmaster@1
|
770 } |
webmaster@1
|
771 } |
webmaster@1
|
772 } |
webmaster@1
|
773 global $theme; |
webmaster@1
|
774 $subtheme_paths = isset($theme_paths[$theme]) ? $theme_paths[$theme] : array(); |
webmaster@1
|
775 |
webmaster@1
|
776 // Escape the periods in the extension. |
webmaster@1
|
777 $regex = str_replace('.', '\.', $extension) .'$'; |
webmaster@1
|
778 // Because drupal_system_listing works the way it does, we check for real |
webmaster@1
|
779 // templates separately from checking for patterns. |
webmaster@1
|
780 $files = drupal_system_listing($regex, $path, 'name', 0); |
webmaster@1
|
781 foreach ($files as $template => $file) { |
webmaster@1
|
782 // Ignore sub-theme templates for the current theme. |
webmaster@1
|
783 if (strpos($file->filename, str_replace($subtheme_paths, '', $file->filename)) !== 0) { |
webmaster@1
|
784 continue; |
webmaster@1
|
785 } |
webmaster@1
|
786 // Chop off the remaining extensions if there are any. $template already |
webmaster@1
|
787 // has the rightmost extension removed, but there might still be more, |
webmaster@1
|
788 // such as with .tpl.php, which still has .tpl in $template at this point. |
webmaster@1
|
789 if (($pos = strpos($template, '.')) !== FALSE) { |
webmaster@1
|
790 $template = substr($template, 0, $pos); |
webmaster@1
|
791 } |
webmaster@1
|
792 // Transform - in filenames to _ to match function naming scheme |
webmaster@1
|
793 // for the purposes of searching. |
webmaster@1
|
794 $hook = strtr($template, '-', '_'); |
webmaster@1
|
795 if (isset($cache[$hook])) { |
webmaster@1
|
796 $templates[$hook] = array( |
webmaster@1
|
797 'template' => $template, |
webmaster@1
|
798 'path' => dirname($file->filename), |
webmaster@1
|
799 ); |
webmaster@1
|
800 } |
webmaster@1
|
801 } |
webmaster@1
|
802 |
webmaster@1
|
803 $patterns = array_keys($files); |
webmaster@1
|
804 |
webmaster@1
|
805 foreach ($cache as $hook => $info) { |
webmaster@1
|
806 if (!empty($info['pattern'])) { |
webmaster@1
|
807 // Transform _ in pattern to - to match file naming scheme |
webmaster@1
|
808 // for the purposes of searching. |
webmaster@1
|
809 $pattern = strtr($info['pattern'], '_', '-'); |
webmaster@1
|
810 |
webmaster@1
|
811 $matches = preg_grep('/^'. $pattern .'/', $patterns); |
webmaster@1
|
812 if ($matches) { |
webmaster@1
|
813 foreach ($matches as $match) { |
webmaster@1
|
814 $file = substr($match, 0, strpos($match, '.')); |
webmaster@1
|
815 // Put the underscores back in for the hook name and register this pattern. |
webmaster@1
|
816 $templates[strtr($file, '-', '_')] = array( |
webmaster@1
|
817 'template' => $file, |
webmaster@1
|
818 'path' => dirname($files[$match]->filename), |
webmaster@1
|
819 'arguments' => $info['arguments'], |
webmaster@1
|
820 ); |
webmaster@1
|
821 } |
webmaster@1
|
822 } |
webmaster@1
|
823 } |
webmaster@1
|
824 } |
webmaster@1
|
825 return $templates; |
webmaster@1
|
826 } |
webmaster@1
|
827 |
webmaster@1
|
828 /** |
webmaster@1
|
829 * Retrieve an associative array containing the settings for a theme. |
webmaster@1
|
830 * |
webmaster@1
|
831 * The final settings are arrived at by merging the default settings, |
webmaster@1
|
832 * the site-wide settings, and the settings defined for the specific theme. |
webmaster@1
|
833 * If no $key was specified, only the site-wide theme defaults are retrieved. |
webmaster@1
|
834 * |
webmaster@1
|
835 * The default values for each of settings are also defined in this function. |
webmaster@1
|
836 * To add new settings, add their default values here, and then add form elements |
webmaster@1
|
837 * to system_theme_settings() in system.module. |
webmaster@1
|
838 * |
webmaster@1
|
839 * @param $key |
webmaster@1
|
840 * The template/style value for a given theme. |
webmaster@1
|
841 * |
webmaster@1
|
842 * @return |
webmaster@1
|
843 * An associative array containing theme settings. |
webmaster@1
|
844 */ |
webmaster@1
|
845 function theme_get_settings($key = NULL) { |
webmaster@1
|
846 $defaults = array( |
webmaster@1
|
847 'mission' => '', |
webmaster@1
|
848 'default_logo' => 1, |
webmaster@1
|
849 'logo_path' => '', |
webmaster@1
|
850 'default_favicon' => 1, |
webmaster@1
|
851 'favicon_path' => '', |
webmaster@1
|
852 'primary_links' => 1, |
webmaster@1
|
853 'secondary_links' => 1, |
webmaster@1
|
854 'toggle_logo' => 1, |
webmaster@1
|
855 'toggle_favicon' => 1, |
webmaster@1
|
856 'toggle_name' => 1, |
webmaster@1
|
857 'toggle_search' => 1, |
webmaster@1
|
858 'toggle_slogan' => 0, |
webmaster@1
|
859 'toggle_mission' => 1, |
webmaster@1
|
860 'toggle_node_user_picture' => 0, |
webmaster@1
|
861 'toggle_comment_user_picture' => 0, |
webmaster@1
|
862 'toggle_primary_links' => 1, |
webmaster@1
|
863 'toggle_secondary_links' => 1, |
webmaster@1
|
864 ); |
webmaster@1
|
865 |
webmaster@1
|
866 if (module_exists('node')) { |
webmaster@1
|
867 foreach (node_get_types() as $type => $name) { |
webmaster@1
|
868 $defaults['toggle_node_info_'. $type] = 1; |
webmaster@1
|
869 } |
webmaster@1
|
870 } |
webmaster@1
|
871 $settings = array_merge($defaults, variable_get('theme_settings', array())); |
webmaster@1
|
872 |
webmaster@1
|
873 if ($key) { |
webmaster@1
|
874 $settings = array_merge($settings, variable_get(str_replace('/', '_', 'theme_'. $key .'_settings'), array())); |
webmaster@1
|
875 } |
webmaster@1
|
876 |
webmaster@1
|
877 // Only offer search box if search.module is enabled. |
webmaster@1
|
878 if (!module_exists('search') || !user_access('search content')) { |
webmaster@1
|
879 $settings['toggle_search'] = 0; |
webmaster@1
|
880 } |
webmaster@1
|
881 |
webmaster@1
|
882 return $settings; |
webmaster@1
|
883 } |
webmaster@1
|
884 |
webmaster@1
|
885 /** |
webmaster@1
|
886 * Retrieve a setting for the current theme. |
webmaster@1
|
887 * This function is designed for use from within themes & engines |
webmaster@1
|
888 * to determine theme settings made in the admin interface. |
webmaster@1
|
889 * |
webmaster@1
|
890 * Caches values for speed (use $refresh = TRUE to refresh cache) |
webmaster@1
|
891 * |
webmaster@1
|
892 * @param $setting_name |
webmaster@1
|
893 * The name of the setting to be retrieved. |
webmaster@1
|
894 * |
webmaster@1
|
895 * @param $refresh |
webmaster@1
|
896 * Whether to reload the cache of settings. |
webmaster@1
|
897 * |
webmaster@1
|
898 * @return |
webmaster@1
|
899 * The value of the requested setting, NULL if the setting does not exist. |
webmaster@1
|
900 */ |
webmaster@1
|
901 function theme_get_setting($setting_name, $refresh = FALSE) { |
webmaster@1
|
902 global $theme_key; |
webmaster@1
|
903 static $settings; |
webmaster@1
|
904 |
webmaster@1
|
905 if (empty($settings) || $refresh) { |
webmaster@1
|
906 $settings = theme_get_settings($theme_key); |
webmaster@1
|
907 |
webmaster@1
|
908 $themes = list_themes(); |
webmaster@1
|
909 $theme_object = $themes[$theme_key]; |
webmaster@1
|
910 |
webmaster@1
|
911 if ($settings['mission'] == '') { |
webmaster@1
|
912 $settings['mission'] = variable_get('site_mission', ''); |
webmaster@1
|
913 } |
webmaster@1
|
914 |
webmaster@1
|
915 if (!$settings['toggle_mission']) { |
webmaster@1
|
916 $settings['mission'] = ''; |
webmaster@1
|
917 } |
webmaster@1
|
918 |
webmaster@1
|
919 if ($settings['toggle_logo']) { |
webmaster@1
|
920 if ($settings['default_logo']) { |
webmaster@1
|
921 $settings['logo'] = base_path() . dirname($theme_object->filename) .'/logo.png'; |
webmaster@1
|
922 } |
webmaster@1
|
923 elseif ($settings['logo_path']) { |
webmaster@1
|
924 $settings['logo'] = base_path() . $settings['logo_path']; |
webmaster@1
|
925 } |
webmaster@1
|
926 } |
webmaster@1
|
927 |
webmaster@1
|
928 if ($settings['toggle_favicon']) { |
webmaster@1
|
929 if ($settings['default_favicon']) { |
webmaster@1
|
930 if (file_exists($favicon = dirname($theme_object->filename) .'/favicon.ico')) { |
webmaster@1
|
931 $settings['favicon'] = base_path() . $favicon; |
webmaster@1
|
932 } |
webmaster@1
|
933 else { |
webmaster@1
|
934 $settings['favicon'] = base_path() .'misc/favicon.ico'; |
webmaster@1
|
935 } |
webmaster@1
|
936 } |
webmaster@1
|
937 elseif ($settings['favicon_path']) { |
webmaster@1
|
938 $settings['favicon'] = base_path() . $settings['favicon_path']; |
webmaster@1
|
939 } |
webmaster@1
|
940 else { |
webmaster@1
|
941 $settings['toggle_favicon'] = FALSE; |
webmaster@1
|
942 } |
webmaster@1
|
943 } |
webmaster@1
|
944 } |
webmaster@1
|
945 |
webmaster@1
|
946 return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL; |
webmaster@1
|
947 } |
webmaster@1
|
948 |
webmaster@1
|
949 /** |
webmaster@1
|
950 * Render a system default template, which is essentially a PHP template. |
webmaster@1
|
951 * |
webmaster@1
|
952 * @param $file |
webmaster@1
|
953 * The filename of the template to render. |
webmaster@1
|
954 * @param $variables |
webmaster@1
|
955 * A keyed array of variables that will appear in the output. |
webmaster@1
|
956 * |
webmaster@1
|
957 * @return |
webmaster@1
|
958 * The output generated by the template. |
webmaster@1
|
959 */ |
webmaster@1
|
960 function theme_render_template($file, $variables) { |
webmaster@1
|
961 extract($variables, EXTR_SKIP); // Extract the variables to a local namespace |
webmaster@1
|
962 ob_start(); // Start output buffering |
webmaster@1
|
963 include "./$file"; // Include the file |
webmaster@1
|
964 $contents = ob_get_contents(); // Get the contents of the buffer |
webmaster@1
|
965 ob_end_clean(); // End buffering and discard |
webmaster@1
|
966 return $contents; // Return the contents |
webmaster@1
|
967 } |
webmaster@1
|
968 |
webmaster@1
|
969 /** |
webmaster@1
|
970 * @defgroup themeable Default theme implementations |
webmaster@1
|
971 * @{ |
webmaster@1
|
972 * Functions and templates that present output to the user, and can be |
webmaster@1
|
973 * implemented by themes. |
webmaster@1
|
974 * |
webmaster@1
|
975 * Drupal's presentation layer is a pluggable system known as the theme |
webmaster@1
|
976 * layer. Each theme can take control over most of Drupal's output, and |
webmaster@1
|
977 * has complete control over the CSS. |
webmaster@1
|
978 * |
webmaster@1
|
979 * Inside Drupal, the theme layer is utilized by the use of the theme() |
webmaster@1
|
980 * function, which is passed the name of a component (the theme hook) |
webmaster@1
|
981 * and several arguments. For example, theme('table', $header, $rows); |
webmaster@1
|
982 * Additionally, the theme() function can take an array of theme |
webmaster@1
|
983 * hooks, which can be used to provide 'fallback' implementations to |
webmaster@1
|
984 * allow for more specific control of output. For example, the function: |
webmaster@1
|
985 * theme(array('table__foo', 'table'), $header, $rows) would look to see if |
webmaster@1
|
986 * 'table__foo' is registered anywhere; if it is not, it would 'fall back' |
webmaster@1
|
987 * to the generic 'table' implementation. This can be used to attach specific |
webmaster@1
|
988 * theme functions to named objects, allowing the themer more control over |
webmaster@1
|
989 * specific types of output. |
webmaster@1
|
990 * |
webmaster@1
|
991 * As of Drupal 6, every theme hook is required to be registered by the |
webmaster@1
|
992 * module that owns it, so that Drupal can tell what to do with it and |
webmaster@1
|
993 * to make it simple for themes to identify and override the behavior |
webmaster@1
|
994 * for these calls. |
webmaster@1
|
995 * |
webmaster@1
|
996 * The theme hooks are registered via hook_theme(), which returns an |
webmaster@1
|
997 * array of arrays with information about the hook. It describes the |
webmaster@1
|
998 * arguments the function or template will need, and provides |
webmaster@1
|
999 * defaults for the template in case they are not filled in. If the default |
webmaster@1
|
1000 * implementation is a function, by convention it is named theme_HOOK(). |
webmaster@1
|
1001 * |
webmaster@1
|
1002 * Each module should provide a default implementation for themes that |
webmaster@1
|
1003 * it registers. This implementation may be either a function or a template; |
webmaster@1
|
1004 * if it is a function it must be specified via hook_theme(). By convention, |
webmaster@1
|
1005 * default implementations of theme hooks are named theme_HOOK. Default |
webmaster@1
|
1006 * template implementations are stored in the module directory. |
webmaster@1
|
1007 * |
webmaster@1
|
1008 * Drupal's default template renderer is a simple PHP parsing engine that |
webmaster@1
|
1009 * includes the template and stores the output. Drupal's theme engines |
webmaster@1
|
1010 * can provide alternate template engines, such as XTemplate, Smarty and |
webmaster@1
|
1011 * PHPTal. The most common template engine is PHPTemplate (included with |
webmaster@1
|
1012 * Drupal and implemented in phptemplate.engine, which uses Drupal's default |
webmaster@1
|
1013 * template renderer. |
webmaster@1
|
1014 * |
webmaster@1
|
1015 * In order to create theme-specific implementations of these hooks, |
webmaster@1
|
1016 * themes can implement their own version of theme hooks, either as functions |
webmaster@1
|
1017 * or templates. These implementations will be used instead of the default |
webmaster@1
|
1018 * implementation. If using a pure .theme without an engine, the .theme is |
webmaster@1
|
1019 * required to implement its own version of hook_theme() to tell Drupal what |
webmaster@1
|
1020 * it is implementing; themes utilizing an engine will have their well-named |
webmaster@1
|
1021 * theming functions automatically registered for them. While this can vary |
webmaster@1
|
1022 * based upon the theme engine, the standard set by phptemplate is that theme |
webmaster@1
|
1023 * functions should be named either phptemplate_HOOK or THEMENAME_HOOK. For |
webmaster@1
|
1024 * example, for Drupal's default theme (Garland) to implement the 'table' hook, |
webmaster@1
|
1025 * the phptemplate.engine would find phptemplate_table() or garland_table(). |
webmaster@1
|
1026 * The ENGINE_HOOK() syntax is preferred, as this can be used by sub-themes |
webmaster@1
|
1027 * (which are themes that share code but use different stylesheets). |
webmaster@1
|
1028 * |
webmaster@1
|
1029 * The theme system is described and defined in theme.inc. |
webmaster@1
|
1030 * |
webmaster@1
|
1031 * @see theme() |
webmaster@1
|
1032 * @see hook_theme() |
webmaster@1
|
1033 */ |
webmaster@1
|
1034 |
webmaster@1
|
1035 /** |
webmaster@1
|
1036 * Formats text for emphasized display in a placeholder inside a sentence. |
webmaster@1
|
1037 * Used automatically by t(). |
webmaster@1
|
1038 * |
webmaster@1
|
1039 * @param $text |
webmaster@1
|
1040 * The text to format (plain-text). |
webmaster@1
|
1041 * @return |
webmaster@1
|
1042 * The formatted text (html). |
webmaster@1
|
1043 */ |
webmaster@1
|
1044 function theme_placeholder($text) { |
webmaster@1
|
1045 return '<em>'. check_plain($text) .'</em>'; |
webmaster@1
|
1046 } |
webmaster@1
|
1047 |
webmaster@1
|
1048 /** |
webmaster@1
|
1049 * Return a themed set of status and/or error messages. The messages are grouped |
webmaster@1
|
1050 * by type. |
webmaster@1
|
1051 * |
webmaster@1
|
1052 * @param $display |
webmaster@1
|
1053 * (optional) Set to 'status' or 'error' to display only messages of that type. |
webmaster@1
|
1054 * |
webmaster@1
|
1055 * @return |
webmaster@1
|
1056 * A string containing the messages. |
webmaster@1
|
1057 */ |
webmaster@1
|
1058 function theme_status_messages($display = NULL) { |
webmaster@1
|
1059 $output = ''; |
webmaster@1
|
1060 foreach (drupal_get_messages($display) as $type => $messages) { |
webmaster@1
|
1061 $output .= "<div class=\"messages $type\">\n"; |
webmaster@1
|
1062 if (count($messages) > 1) { |
webmaster@1
|
1063 $output .= " <ul>\n"; |
webmaster@1
|
1064 foreach ($messages as $message) { |
webmaster@1
|
1065 $output .= ' <li>'. $message ."</li>\n"; |
webmaster@1
|
1066 } |
webmaster@1
|
1067 $output .= " </ul>\n"; |
webmaster@1
|
1068 } |
webmaster@1
|
1069 else { |
webmaster@1
|
1070 $output .= $messages[0]; |
webmaster@1
|
1071 } |
webmaster@1
|
1072 $output .= "</div>\n"; |
webmaster@1
|
1073 } |
webmaster@1
|
1074 return $output; |
webmaster@1
|
1075 } |
webmaster@1
|
1076 |
webmaster@1
|
1077 /** |
webmaster@1
|
1078 * Return a themed set of links. |
webmaster@1
|
1079 * |
webmaster@1
|
1080 * @param $links |
webmaster@1
|
1081 * A keyed array of links to be themed. |
webmaster@1
|
1082 * @param $attributes |
webmaster@1
|
1083 * A keyed array of attributes |
webmaster@1
|
1084 * @return |
webmaster@1
|
1085 * A string containing an unordered list of links. |
webmaster@1
|
1086 */ |
webmaster@1
|
1087 function theme_links($links, $attributes = array('class' => 'links')) { |
webmaster@1
|
1088 $output = ''; |
webmaster@1
|
1089 |
webmaster@1
|
1090 if (count($links) > 0) { |
webmaster@1
|
1091 $output = '<ul'. drupal_attributes($attributes) .'>'; |
webmaster@1
|
1092 |
webmaster@1
|
1093 $num_links = count($links); |
webmaster@1
|
1094 $i = 1; |
webmaster@1
|
1095 |
webmaster@1
|
1096 foreach ($links as $key => $link) { |
webmaster@1
|
1097 $class = $key; |
webmaster@1
|
1098 |
webmaster@1
|
1099 // Add first, last and active classes to the list of links to help out themers. |
webmaster@1
|
1100 if ($i == 1) { |
webmaster@1
|
1101 $class .= ' first'; |
webmaster@1
|
1102 } |
webmaster@1
|
1103 if ($i == $num_links) { |
webmaster@1
|
1104 $class .= ' last'; |
webmaster@1
|
1105 } |
webmaster@5
|
1106 if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) { |
webmaster@1
|
1107 $class .= ' active'; |
webmaster@1
|
1108 } |
webmaster@1
|
1109 $output .= '<li class="'. $class .'">'; |
webmaster@1
|
1110 |
webmaster@1
|
1111 if (isset($link['href'])) { |
webmaster@1
|
1112 // Pass in $link as $options, they share the same keys. |
webmaster@1
|
1113 $output .= l($link['title'], $link['href'], $link); |
webmaster@1
|
1114 } |
webmaster@1
|
1115 else if (!empty($link['title'])) { |
webmaster@1
|
1116 // Some links are actually not links, but we wrap these in <span> for adding title and class attributes |
webmaster@1
|
1117 if (empty($link['html'])) { |
webmaster@1
|
1118 $link['title'] = check_plain($link['title']); |
webmaster@1
|
1119 } |
webmaster@1
|
1120 $span_attributes = ''; |
webmaster@1
|
1121 if (isset($link['attributes'])) { |
webmaster@1
|
1122 $span_attributes = drupal_attributes($link['attributes']); |
webmaster@1
|
1123 } |
webmaster@1
|
1124 $output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>'; |
webmaster@1
|
1125 } |
webmaster@1
|
1126 |
webmaster@1
|
1127 $i++; |
webmaster@1
|
1128 $output .= "</li>\n"; |
webmaster@1
|
1129 } |
webmaster@1
|
1130 |
webmaster@1
|
1131 $output .= '</ul>'; |
webmaster@1
|
1132 } |
webmaster@1
|
1133 |
webmaster@1
|
1134 return $output; |
webmaster@1
|
1135 } |
webmaster@1
|
1136 |
webmaster@1
|
1137 /** |
webmaster@1
|
1138 * Return a themed image. |
webmaster@1
|
1139 * |
webmaster@1
|
1140 * @param $path |
webmaster@1
|
1141 * Either the path of the image file (relative to base_path()) or a full URL. |
webmaster@1
|
1142 * @param $alt |
webmaster@1
|
1143 * The alternative text for text-based browsers. |
webmaster@1
|
1144 * @param $title |
webmaster@1
|
1145 * The title text is displayed when the image is hovered in some popular browsers. |
webmaster@1
|
1146 * @param $attributes |
webmaster@1
|
1147 * Associative array of attributes to be placed in the img tag. |
webmaster@1
|
1148 * @param $getsize |
webmaster@1
|
1149 * If set to TRUE, the image's dimension are fetched and added as width/height attributes. |
webmaster@1
|
1150 * @return |
webmaster@1
|
1151 * A string containing the image tag. |
webmaster@1
|
1152 */ |
webmaster@1
|
1153 function theme_image($path, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) { |
webmaster@1
|
1154 if (!$getsize || (is_file($path) && (list($width, $height, $type, $image_attributes) = @getimagesize($path)))) { |
webmaster@1
|
1155 $attributes = drupal_attributes($attributes); |
webmaster@1
|
1156 $url = (url($path) == $path) ? $path : (base_path() . $path); |
webmaster@1
|
1157 return '<img src="'. check_url($url) .'" alt="'. check_plain($alt) .'" title="'. check_plain($title) .'" '. (isset($image_attributes) ? $image_attributes : '') . $attributes .' />'; |
webmaster@1
|
1158 } |
webmaster@1
|
1159 } |
webmaster@1
|
1160 |
webmaster@1
|
1161 /** |
webmaster@1
|
1162 * Return a themed breadcrumb trail. |
webmaster@1
|
1163 * |
webmaster@1
|
1164 * @param $breadcrumb |
webmaster@1
|
1165 * An array containing the breadcrumb links. |
webmaster@1
|
1166 * @return a string containing the breadcrumb output. |
webmaster@1
|
1167 */ |
webmaster@1
|
1168 function theme_breadcrumb($breadcrumb) { |
webmaster@1
|
1169 if (!empty($breadcrumb)) { |
webmaster@1
|
1170 return '<div class="breadcrumb">'. implode(' » ', $breadcrumb) .'</div>'; |
webmaster@1
|
1171 } |
webmaster@1
|
1172 } |
webmaster@1
|
1173 |
webmaster@1
|
1174 /** |
webmaster@1
|
1175 * Return a themed help message. |
webmaster@1
|
1176 * |
webmaster@1
|
1177 * @return a string containing the helptext for the current page. |
webmaster@1
|
1178 */ |
webmaster@1
|
1179 function theme_help() { |
webmaster@1
|
1180 if ($help = menu_get_active_help()) { |
webmaster@1
|
1181 return '<div class="help">'. $help .'</div>'; |
webmaster@1
|
1182 } |
webmaster@1
|
1183 } |
webmaster@1
|
1184 |
webmaster@1
|
1185 /** |
webmaster@1
|
1186 * Return a themed submenu, typically displayed under the tabs. |
webmaster@1
|
1187 * |
webmaster@1
|
1188 * @param $links |
webmaster@1
|
1189 * An array of links. |
webmaster@1
|
1190 */ |
webmaster@1
|
1191 function theme_submenu($links) { |
webmaster@1
|
1192 return '<div class="submenu">'. implode(' | ', $links) .'</div>'; |
webmaster@1
|
1193 } |
webmaster@1
|
1194 |
webmaster@1
|
1195 /** |
webmaster@1
|
1196 * Return a themed table. |
webmaster@1
|
1197 * |
webmaster@1
|
1198 * @param $header |
webmaster@1
|
1199 * An array containing the table headers. Each element of the array can be |
webmaster@1
|
1200 * either a localized string or an associative array with the following keys: |
webmaster@1
|
1201 * - "data": The localized title of the table column. |
webmaster@1
|
1202 * - "field": The database field represented in the table column (required if |
webmaster@1
|
1203 * user is to be able to sort on this column). |
webmaster@1
|
1204 * - "sort": A default sort order for this column ("asc" or "desc"). |
webmaster@1
|
1205 * - Any HTML attributes, such as "colspan", to apply to the column header cell. |
webmaster@1
|
1206 * @param $rows |
webmaster@1
|
1207 * An array of table rows. Every row is an array of cells, or an associative |
webmaster@1
|
1208 * array with the following keys: |
webmaster@1
|
1209 * - "data": an array of cells |
webmaster@1
|
1210 * - Any HTML attributes, such as "class", to apply to the table row. |
webmaster@1
|
1211 * |
webmaster@1
|
1212 * Each cell can be either a string or an associative array with the following keys: |
webmaster@1
|
1213 * - "data": The string to display in the table cell. |
webmaster@1
|
1214 * - "header": Indicates this cell is a header. |
webmaster@1
|
1215 * - Any HTML attributes, such as "colspan", to apply to the table cell. |
webmaster@1
|
1216 * |
webmaster@1
|
1217 * Here's an example for $rows: |
webmaster@1
|
1218 * @verbatim |
webmaster@1
|
1219 * $rows = array( |
webmaster@1
|
1220 * // Simple row |
webmaster@1
|
1221 * array( |
webmaster@1
|
1222 * 'Cell 1', 'Cell 2', 'Cell 3' |
webmaster@1
|
1223 * ), |
webmaster@1
|
1224 * // Row with attributes on the row and some of its cells. |
webmaster@1
|
1225 * array( |
webmaster@1
|
1226 * 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => 'funky' |
webmaster@1
|
1227 * ) |
webmaster@1
|
1228 * ); |
webmaster@1
|
1229 * @endverbatim |
webmaster@1
|
1230 * |
webmaster@1
|
1231 * @param $attributes |
webmaster@1
|
1232 * An array of HTML attributes to apply to the table tag. |
webmaster@1
|
1233 * @param $caption |
webmaster@1
|
1234 * A localized string to use for the <caption> tag. |
webmaster@1
|
1235 * @return |
webmaster@1
|
1236 * An HTML string representing the table. |
webmaster@1
|
1237 */ |
webmaster@1
|
1238 function theme_table($header, $rows, $attributes = array(), $caption = NULL) { |
webmaster@1
|
1239 |
webmaster@1
|
1240 // Add sticky headers, if applicable. |
webmaster@1
|
1241 if (count($header)) { |
webmaster@1
|
1242 drupal_add_js('misc/tableheader.js'); |
webmaster@1
|
1243 // Add 'sticky-enabled' class to the table to identify it for JS. |
webmaster@1
|
1244 // This is needed to target tables constructed by this function. |
webmaster@1
|
1245 $attributes['class'] = empty($attributes['class']) ? 'sticky-enabled' : ($attributes['class'] .' sticky-enabled'); |
webmaster@1
|
1246 } |
webmaster@1
|
1247 |
webmaster@1
|
1248 $output = '<table'. drupal_attributes($attributes) .">\n"; |
webmaster@1
|
1249 |
webmaster@1
|
1250 if (isset($caption)) { |
webmaster@1
|
1251 $output .= '<caption>'. $caption ."</caption>\n"; |
webmaster@1
|
1252 } |
webmaster@1
|
1253 |
webmaster@1
|
1254 // Format the table header: |
webmaster@1
|
1255 if (count($header)) { |
webmaster@1
|
1256 $ts = tablesort_init($header); |
webmaster@1
|
1257 // HTML requires that the thead tag has tr tags in it follwed by tbody |
webmaster@1
|
1258 // tags. Using ternary operator to check and see if we have any rows. |
webmaster@1
|
1259 $output .= (count($rows) ? ' <thead><tr>' : ' <tr>'); |
webmaster@1
|
1260 foreach ($header as $cell) { |
webmaster@1
|
1261 $cell = tablesort_header($cell, $header, $ts); |
webmaster@1
|
1262 $output .= _theme_table_cell($cell, TRUE); |
webmaster@1
|
1263 } |
webmaster@1
|
1264 // Using ternary operator to close the tags based on whether or not there are rows |
webmaster@1
|
1265 $output .= (count($rows) ? " </tr></thead>\n" : "</tr>\n"); |
webmaster@1
|
1266 } |
webmaster@1
|
1267 else { |
webmaster@1
|
1268 $ts = array(); |
webmaster@1
|
1269 } |
webmaster@1
|
1270 |
webmaster@1
|
1271 // Format the table rows: |
webmaster@1
|
1272 if (count($rows)) { |
webmaster@1
|
1273 $output .= "<tbody>\n"; |
webmaster@1
|
1274 $flip = array('even' => 'odd', 'odd' => 'even'); |
webmaster@1
|
1275 $class = 'even'; |
webmaster@1
|
1276 foreach ($rows as $number => $row) { |
webmaster@1
|
1277 $attributes = array(); |
webmaster@1
|
1278 |
webmaster@1
|
1279 // Check if we're dealing with a simple or complex row |
webmaster@1
|
1280 if (isset($row['data'])) { |
webmaster@1
|
1281 foreach ($row as $key => $value) { |
webmaster@1
|
1282 if ($key == 'data') { |
webmaster@1
|
1283 $cells = $value; |
webmaster@1
|
1284 } |
webmaster@1
|
1285 else { |
webmaster@1
|
1286 $attributes[$key] = $value; |
webmaster@1
|
1287 } |
webmaster@1
|
1288 } |
webmaster@1
|
1289 } |
webmaster@1
|
1290 else { |
webmaster@1
|
1291 $cells = $row; |
webmaster@1
|
1292 } |
webmaster@1
|
1293 if (count($cells)) { |
webmaster@1
|
1294 // Add odd/even class |
webmaster@1
|
1295 $class = $flip[$class]; |
webmaster@1
|
1296 if (isset($attributes['class'])) { |
webmaster@1
|
1297 $attributes['class'] .= ' '. $class; |
webmaster@1
|
1298 } |
webmaster@1
|
1299 else { |
webmaster@1
|
1300 $attributes['class'] = $class; |
webmaster@1
|
1301 } |
webmaster@1
|
1302 |
webmaster@1
|
1303 // Build row |
webmaster@1
|
1304 $output .= ' <tr'. drupal_attributes($attributes) .'>'; |
webmaster@1
|
1305 $i = 0; |
webmaster@1
|
1306 foreach ($cells as $cell) { |
webmaster@1
|
1307 $cell = tablesort_cell($cell, $header, $ts, $i++); |
webmaster@1
|
1308 $output .= _theme_table_cell($cell); |
webmaster@1
|
1309 } |
webmaster@1
|
1310 $output .= " </tr>\n"; |
webmaster@1
|
1311 } |
webmaster@1
|
1312 } |
webmaster@1
|
1313 $output .= "</tbody>\n"; |
webmaster@1
|
1314 } |
webmaster@1
|
1315 |
webmaster@1
|
1316 $output .= "</table>\n"; |
webmaster@1
|
1317 return $output; |
webmaster@1
|
1318 } |
webmaster@1
|
1319 |
webmaster@1
|
1320 /** |
webmaster@1
|
1321 * Returns a header cell for tables that have a select all functionality. |
webmaster@1
|
1322 */ |
webmaster@1
|
1323 function theme_table_select_header_cell() { |
webmaster@1
|
1324 drupal_add_js('misc/tableselect.js'); |
webmaster@1
|
1325 |
webmaster@1
|
1326 return array('class' => 'select-all'); |
webmaster@1
|
1327 } |
webmaster@1
|
1328 |
webmaster@1
|
1329 /** |
webmaster@1
|
1330 * Return a themed sort icon. |
webmaster@1
|
1331 * |
webmaster@1
|
1332 * @param $style |
webmaster@1
|
1333 * Set to either asc or desc. This sets which icon to show. |
webmaster@1
|
1334 * @return |
webmaster@1
|
1335 * A themed sort icon. |
webmaster@1
|
1336 */ |
webmaster@1
|
1337 function theme_tablesort_indicator($style) { |
webmaster@1
|
1338 if ($style == "asc") { |
webmaster@1
|
1339 return theme('image', 'misc/arrow-asc.png', t('sort icon'), t('sort ascending')); |
webmaster@1
|
1340 } |
webmaster@1
|
1341 else { |
webmaster@1
|
1342 return theme('image', 'misc/arrow-desc.png', t('sort icon'), t('sort descending')); |
webmaster@1
|
1343 } |
webmaster@1
|
1344 } |
webmaster@1
|
1345 |
webmaster@1
|
1346 /** |
webmaster@1
|
1347 * Return a themed box. |
webmaster@1
|
1348 * |
webmaster@1
|
1349 * @param $title |
webmaster@1
|
1350 * The subject of the box. |
webmaster@1
|
1351 * @param $content |
webmaster@1
|
1352 * The content of the box. |
webmaster@1
|
1353 * @param $region |
webmaster@1
|
1354 * The region in which the box is displayed. |
webmaster@1
|
1355 * @return |
webmaster@1
|
1356 * A string containing the box output. |
webmaster@1
|
1357 */ |
webmaster@1
|
1358 function theme_box($title, $content, $region = 'main') { |
webmaster@1
|
1359 $output = '<h2 class="title">'. $title .'</h2><div>'. $content .'</div>'; |
webmaster@1
|
1360 return $output; |
webmaster@1
|
1361 } |
webmaster@1
|
1362 |
webmaster@1
|
1363 /** |
webmaster@1
|
1364 * Return a themed marker, useful for marking new or updated |
webmaster@1
|
1365 * content. |
webmaster@1
|
1366 * |
webmaster@1
|
1367 * @param $type |
webmaster@1
|
1368 * Number representing the marker type to display |
webmaster@1
|
1369 * @see MARK_NEW, MARK_UPDATED, MARK_READ |
webmaster@1
|
1370 * @return |
webmaster@1
|
1371 * A string containing the marker. |
webmaster@1
|
1372 */ |
webmaster@1
|
1373 function theme_mark($type = MARK_NEW) { |
webmaster@1
|
1374 global $user; |
webmaster@1
|
1375 if ($user->uid) { |
webmaster@1
|
1376 if ($type == MARK_NEW) { |
webmaster@1
|
1377 return ' <span class="marker">'. t('new') .'</span>'; |
webmaster@1
|
1378 } |
webmaster@1
|
1379 else if ($type == MARK_UPDATED) { |
webmaster@1
|
1380 return ' <span class="marker">'. t('updated') .'</span>'; |
webmaster@1
|
1381 } |
webmaster@1
|
1382 } |
webmaster@1
|
1383 } |
webmaster@1
|
1384 |
webmaster@1
|
1385 /** |
webmaster@1
|
1386 * Return a themed list of items. |
webmaster@1
|
1387 * |
webmaster@1
|
1388 * @param $items |
webmaster@1
|
1389 * An array of items to be displayed in the list. If an item is a string, |
webmaster@1
|
1390 * then it is used as is. If an item is an array, then the "data" element of |
webmaster@1
|
1391 * the array is used as the contents of the list item. If an item is an array |
webmaster@1
|
1392 * with a "children" element, those children are displayed in a nested list. |
webmaster@1
|
1393 * All other elements are treated as attributes of the list item element. |
webmaster@1
|
1394 * @param $title |
webmaster@1
|
1395 * The title of the list. |
webmaster@1
|
1396 * @param $attributes |
webmaster@1
|
1397 * The attributes applied to the list element. |
webmaster@1
|
1398 * @param $type |
webmaster@1
|
1399 * The type of list to return (e.g. "ul", "ol") |
webmaster@1
|
1400 * @return |
webmaster@1
|
1401 * A string containing the list output. |
webmaster@1
|
1402 */ |
webmaster@1
|
1403 function theme_item_list($items = array(), $title = NULL, $type = 'ul', $attributes = NULL) { |
webmaster@1
|
1404 $output = '<div class="item-list">'; |
webmaster@1
|
1405 if (isset($title)) { |
webmaster@1
|
1406 $output .= '<h3>'. $title .'</h3>'; |
webmaster@1
|
1407 } |
webmaster@1
|
1408 |
webmaster@1
|
1409 if (!empty($items)) { |
webmaster@1
|
1410 $output .= "<$type". drupal_attributes($attributes) .'>'; |
webmaster@1
|
1411 $num_items = count($items); |
webmaster@1
|
1412 foreach ($items as $i => $item) { |
webmaster@1
|
1413 $attributes = array(); |
webmaster@1
|
1414 $children = array(); |
webmaster@1
|
1415 if (is_array($item)) { |
webmaster@1
|
1416 foreach ($item as $key => $value) { |
webmaster@1
|
1417 if ($key == 'data') { |
webmaster@1
|
1418 $data = $value; |
webmaster@1
|
1419 } |
webmaster@1
|
1420 elseif ($key == 'children') { |
webmaster@1
|
1421 $children = $value; |
webmaster@1
|
1422 } |
webmaster@1
|
1423 else { |
webmaster@1
|
1424 $attributes[$key] = $value; |
webmaster@1
|
1425 } |
webmaster@1
|
1426 } |
webmaster@1
|
1427 } |
webmaster@1
|
1428 else { |
webmaster@1
|
1429 $data = $item; |
webmaster@1
|
1430 } |
webmaster@1
|
1431 if (count($children) > 0) { |
webmaster@1
|
1432 $data .= theme_item_list($children, NULL, $type, $attributes); // Render nested list |
webmaster@1
|
1433 } |
webmaster@1
|
1434 if ($i == 0) { |
webmaster@1
|
1435 $attributes['class'] = empty($attributes['class']) ? 'first' : ($attributes['class'] .' first'); |
webmaster@1
|
1436 } |
webmaster@1
|
1437 if ($i == $num_items - 1) { |
webmaster@1
|
1438 $attributes['class'] = empty($attributes['class']) ? 'last' : ($attributes['class'] .' last'); |
webmaster@1
|
1439 } |
webmaster@1
|
1440 $output .= '<li'. drupal_attributes($attributes) .'>'. $data ."</li>\n"; |
webmaster@1
|
1441 } |
webmaster@1
|
1442 $output .= "</$type>"; |
webmaster@1
|
1443 } |
webmaster@1
|
1444 $output .= '</div>'; |
webmaster@1
|
1445 return $output; |
webmaster@1
|
1446 } |
webmaster@1
|
1447 |
webmaster@1
|
1448 /** |
webmaster@1
|
1449 * Returns code that emits the 'more help'-link. |
webmaster@1
|
1450 */ |
webmaster@1
|
1451 function theme_more_help_link($url) { |
webmaster@1
|
1452 return '<div class="more-help-link">'. t('[<a href="@link">more help...</a>]', array('@link' => check_url($url))) .'</div>'; |
webmaster@1
|
1453 } |
webmaster@1
|
1454 |
webmaster@1
|
1455 /** |
webmaster@1
|
1456 * Return code that emits an XML icon. |
webmaster@1
|
1457 * |
webmaster@1
|
1458 * For most use cases, this function has been superseded by theme_feed_icon(). |
webmaster@1
|
1459 * |
webmaster@1
|
1460 * @see theme_feed_icon() |
webmaster@1
|
1461 * @param $url |
webmaster@1
|
1462 * The url of the feed. |
webmaster@1
|
1463 */ |
webmaster@1
|
1464 function theme_xml_icon($url) { |
webmaster@1
|
1465 if ($image = theme('image', 'misc/xml.png', t('XML feed'), t('XML feed'))) { |
webmaster@1
|
1466 return '<a href="'. check_url($url) .'" class="xml-icon">'. $image .'</a>'; |
webmaster@1
|
1467 } |
webmaster@1
|
1468 } |
webmaster@1
|
1469 |
webmaster@1
|
1470 /** |
webmaster@1
|
1471 * Return code that emits an feed icon. |
webmaster@1
|
1472 * |
webmaster@1
|
1473 * @param $url |
webmaster@1
|
1474 * The url of the feed. |
webmaster@1
|
1475 * @param $title |
webmaster@1
|
1476 * A descriptive title of the feed. |
webmaster@1
|
1477 */ |
webmaster@1
|
1478 function theme_feed_icon($url, $title) { |
webmaster@1
|
1479 if ($image = theme('image', 'misc/feed.png', t('Syndicate content'), $title)) { |
webmaster@1
|
1480 return '<a href="'. check_url($url) .'" class="feed-icon">'. $image .'</a>'; |
webmaster@1
|
1481 } |
webmaster@1
|
1482 } |
webmaster@1
|
1483 |
webmaster@1
|
1484 /** |
webmaster@1
|
1485 * Returns code that emits the 'more' link used on blocks. |
webmaster@1
|
1486 * |
webmaster@1
|
1487 * @param $url |
webmaster@1
|
1488 * The url of the main page |
webmaster@1
|
1489 * @param $title |
webmaster@1
|
1490 * A descriptive verb for the link, like 'Read more' |
webmaster@1
|
1491 */ |
webmaster@1
|
1492 function theme_more_link($url, $title) { |
webmaster@1
|
1493 return '<div class="more-link">'. t('<a href="@link" title="@title">more</a>', array('@link' => check_url($url), '@title' => $title)) .'</div>'; |
webmaster@1
|
1494 } |
webmaster@1
|
1495 |
webmaster@1
|
1496 /** |
webmaster@1
|
1497 * Execute hook_footer() which is run at the end of the page right before the |
webmaster@1
|
1498 * close of the body tag. |
webmaster@1
|
1499 * |
webmaster@1
|
1500 * @param $main (optional) |
webmaster@1
|
1501 * Whether the current page is the front page of the site. |
webmaster@1
|
1502 * @return |
webmaster@1
|
1503 * A string containing the results of the hook_footer() calls. |
webmaster@1
|
1504 */ |
webmaster@1
|
1505 function theme_closure($main = 0) { |
webmaster@1
|
1506 $footer = module_invoke_all('footer', $main); |
webmaster@1
|
1507 return implode("\n", $footer) . drupal_get_js('footer'); |
webmaster@1
|
1508 } |
webmaster@1
|
1509 |
webmaster@1
|
1510 /** |
webmaster@1
|
1511 * Return a set of blocks available for the current user. |
webmaster@1
|
1512 * |
webmaster@1
|
1513 * @param $region |
webmaster@1
|
1514 * Which set of blocks to retrieve. |
webmaster@1
|
1515 * @return |
webmaster@1
|
1516 * A string containing the themed blocks for this region. |
webmaster@1
|
1517 */ |
webmaster@1
|
1518 function theme_blocks($region) { |
webmaster@1
|
1519 $output = ''; |
webmaster@1
|
1520 |
webmaster@1
|
1521 if ($list = block_list($region)) { |
webmaster@1
|
1522 foreach ($list as $key => $block) { |
webmaster@1
|
1523 // $key == <i>module</i>_<i>delta</i> |
webmaster@1
|
1524 $output .= theme('block', $block); |
webmaster@1
|
1525 } |
webmaster@1
|
1526 } |
webmaster@1
|
1527 |
webmaster@1
|
1528 // Add any content assigned to this region through drupal_set_content() calls. |
webmaster@1
|
1529 $output .= drupal_get_content($region); |
webmaster@1
|
1530 |
webmaster@1
|
1531 return $output; |
webmaster@1
|
1532 } |
webmaster@1
|
1533 |
webmaster@1
|
1534 /** |
webmaster@1
|
1535 * Format a username. |
webmaster@1
|
1536 * |
webmaster@1
|
1537 * @param $object |
webmaster@1
|
1538 * The user object to format, usually returned from user_load(). |
webmaster@1
|
1539 * @return |
webmaster@1
|
1540 * A string containing an HTML link to the user's page if the passed object |
webmaster@1
|
1541 * suggests that this is a site user. Otherwise, only the username is returned. |
webmaster@1
|
1542 */ |
webmaster@1
|
1543 function theme_username($object) { |
webmaster@1
|
1544 |
webmaster@1
|
1545 if ($object->uid && $object->name) { |
webmaster@1
|
1546 // Shorten the name when it is too long or it will break many tables. |
webmaster@1
|
1547 if (drupal_strlen($object->name) > 20) { |
webmaster@1
|
1548 $name = drupal_substr($object->name, 0, 15) .'...'; |
webmaster@1
|
1549 } |
webmaster@1
|
1550 else { |
webmaster@1
|
1551 $name = $object->name; |
webmaster@1
|
1552 } |
webmaster@1
|
1553 |
webmaster@1
|
1554 if (user_access('access user profiles')) { |
webmaster@5
|
1555 $output = l($name, 'user/'. $object->uid, array('attributes' => array('title' => t('View user profile.')))); |
webmaster@1
|
1556 } |
webmaster@1
|
1557 else { |
webmaster@1
|
1558 $output = check_plain($name); |
webmaster@1
|
1559 } |
webmaster@1
|
1560 } |
webmaster@1
|
1561 else if ($object->name) { |
webmaster@1
|
1562 // Sometimes modules display content composed by people who are |
webmaster@1
|
1563 // not registered members of the site (e.g. mailing list or news |
webmaster@1
|
1564 // aggregator modules). This clause enables modules to display |
webmaster@1
|
1565 // the true author of the content. |
webmaster@1
|
1566 if (!empty($object->homepage)) { |
webmaster@1
|
1567 $output = l($object->name, $object->homepage, array('rel' => 'nofollow')); |
webmaster@1
|
1568 } |
webmaster@1
|
1569 else { |
webmaster@1
|
1570 $output = check_plain($object->name); |
webmaster@1
|
1571 } |
webmaster@1
|
1572 |
webmaster@1
|
1573 $output .= ' ('. t('not verified') .')'; |
webmaster@1
|
1574 } |
webmaster@1
|
1575 else { |
webmaster@1
|
1576 $output = variable_get('anonymous', t('Anonymous')); |
webmaster@1
|
1577 } |
webmaster@1
|
1578 |
webmaster@1
|
1579 return $output; |
webmaster@1
|
1580 } |
webmaster@1
|
1581 |
webmaster@1
|
1582 /** |
webmaster@1
|
1583 * Return a themed progress bar. |
webmaster@1
|
1584 * |
webmaster@1
|
1585 * @param $percent |
webmaster@1
|
1586 * The percentage of the progress. |
webmaster@1
|
1587 * @param $message |
webmaster@1
|
1588 * A string containing information to be displayed. |
webmaster@1
|
1589 * @return |
webmaster@1
|
1590 * A themed HTML string representing the progress bar. |
webmaster@1
|
1591 */ |
webmaster@1
|
1592 function theme_progress_bar($percent, $message) { |
webmaster@1
|
1593 $output = '<div id="progress" class="progress">'; |
webmaster@1
|
1594 $output .= '<div class="bar"><div class="filled" style="width: '. $percent .'%"></div></div>'; |
webmaster@1
|
1595 $output .= '<div class="percentage">'. $percent .'%</div>'; |
webmaster@1
|
1596 $output .= '<div class="message">'. $message .'</div>'; |
webmaster@1
|
1597 $output .= '</div>'; |
webmaster@1
|
1598 |
webmaster@1
|
1599 return $output; |
webmaster@1
|
1600 } |
webmaster@1
|
1601 |
webmaster@1
|
1602 /** |
webmaster@1
|
1603 * Create a standard indentation div. Used for drag and drop tables. |
webmaster@1
|
1604 * |
webmaster@1
|
1605 * @param $size |
webmaster@1
|
1606 * Optional. The number of indentations to create. |
webmaster@1
|
1607 * @return |
webmaster@1
|
1608 * A string containing indentations. |
webmaster@1
|
1609 */ |
webmaster@1
|
1610 function theme_indentation($size = 1) { |
webmaster@1
|
1611 $output = ''; |
webmaster@1
|
1612 for ($n = 0; $n < $size; $n++) { |
webmaster@1
|
1613 $output .= '<div class="indentation"> </div>'; |
webmaster@1
|
1614 } |
webmaster@1
|
1615 return $output; |
webmaster@1
|
1616 } |
webmaster@1
|
1617 |
webmaster@1
|
1618 /** |
webmaster@1
|
1619 * @} End of "defgroup themeable". |
webmaster@1
|
1620 */ |
webmaster@1
|
1621 |
webmaster@1
|
1622 function _theme_table_cell($cell, $header = FALSE) { |
webmaster@1
|
1623 $attributes = ''; |
webmaster@1
|
1624 |
webmaster@1
|
1625 if (is_array($cell)) { |
webmaster@1
|
1626 $data = isset($cell['data']) ? $cell['data'] : ''; |
webmaster@1
|
1627 $header |= isset($cell['header']); |
webmaster@1
|
1628 unset($cell['data']); |
webmaster@1
|
1629 unset($cell['header']); |
webmaster@1
|
1630 $attributes = drupal_attributes($cell); |
webmaster@1
|
1631 } |
webmaster@1
|
1632 else { |
webmaster@1
|
1633 $data = $cell; |
webmaster@1
|
1634 } |
webmaster@1
|
1635 |
webmaster@1
|
1636 if ($header) { |
webmaster@1
|
1637 $output = "<th$attributes>$data</th>"; |
webmaster@1
|
1638 } |
webmaster@1
|
1639 else { |
webmaster@1
|
1640 $output = "<td$attributes>$data</td>"; |
webmaster@1
|
1641 } |
webmaster@1
|
1642 |
webmaster@1
|
1643 return $output; |
webmaster@1
|
1644 } |
webmaster@1
|
1645 |
webmaster@1
|
1646 /** |
webmaster@1
|
1647 * Adds a default set of helper variables for preprocess functions and |
webmaster@1
|
1648 * templates. This comes in before any other preprocess function which makes |
webmaster@1
|
1649 * it possible to be used in default theme implementations (non-overriden |
webmaster@1
|
1650 * theme functions). |
webmaster@1
|
1651 */ |
webmaster@1
|
1652 function template_preprocess(&$variables, $hook) { |
webmaster@1
|
1653 global $user; |
webmaster@1
|
1654 static $count = array(); |
webmaster@1
|
1655 |
webmaster@1
|
1656 // Track run count for each hook to provide zebra striping. |
webmaster@1
|
1657 // See "template_preprocess_block()" which provides the same feature specific to blocks. |
webmaster@1
|
1658 $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1; |
webmaster@1
|
1659 $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even'; |
webmaster@1
|
1660 $variables['id'] = $count[$hook]++; |
webmaster@1
|
1661 |
webmaster@1
|
1662 // Tell all templates where they are located. |
webmaster@1
|
1663 $variables['directory'] = path_to_theme(); |
webmaster@1
|
1664 |
webmaster@1
|
1665 // Set default variables that depend on the database. |
webmaster@1
|
1666 $variables['is_admin'] = FALSE; |
webmaster@1
|
1667 $variables['is_front'] = FALSE; |
webmaster@1
|
1668 $variables['logged_in'] = FALSE; |
webmaster@1
|
1669 if ($variables['db_is_active'] = db_is_active() && !defined('MAINTENANCE_MODE')) { |
webmaster@1
|
1670 // Check for administrators. |
webmaster@1
|
1671 if (user_access('access administration pages')) { |
webmaster@1
|
1672 $variables['is_admin'] = TRUE; |
webmaster@1
|
1673 } |
webmaster@1
|
1674 // Flag front page status. |
webmaster@1
|
1675 $variables['is_front'] = drupal_is_front_page(); |
webmaster@1
|
1676 // Tell all templates by which kind of user they're viewed. |
webmaster@1
|
1677 $variables['logged_in'] = ($user->uid > 0); |
webmaster@1
|
1678 // Provide user object to all templates |
webmaster@1
|
1679 $variables['user'] = $user; |
webmaster@1
|
1680 } |
webmaster@1
|
1681 } |
webmaster@1
|
1682 |
webmaster@1
|
1683 /** |
webmaster@1
|
1684 * Process variables for page.tpl.php |
webmaster@1
|
1685 * |
webmaster@1
|
1686 * Most themes utilize their own copy of page.tpl.php. The default is located |
webmaster@1
|
1687 * inside "modules/system/page.tpl.php". Look in there for the full list of |
webmaster@1
|
1688 * variables. |
webmaster@1
|
1689 * |
webmaster@1
|
1690 * Uses the arg() function to generate a series of page template suggestions |
webmaster@1
|
1691 * based on the current path. |
webmaster@1
|
1692 * |
webmaster@1
|
1693 * Any changes to variables in this preprocessor should also be changed inside |
webmaster@1
|
1694 * template_preprocess_maintenance_page() to keep all them consistent. |
webmaster@1
|
1695 * |
webmaster@1
|
1696 * The $variables array contains the following arguments: |
webmaster@1
|
1697 * - $content |
webmaster@1
|
1698 * - $show_blocks |
webmaster@1
|
1699 * |
webmaster@1
|
1700 * @see page.tpl.php |
webmaster@1
|
1701 */ |
webmaster@1
|
1702 function template_preprocess_page(&$variables) { |
webmaster@1
|
1703 // Add favicon |
webmaster@1
|
1704 if (theme_get_setting('toggle_favicon')) { |
webmaster@1
|
1705 drupal_set_html_head('<link rel="shortcut icon" href="'. check_url(theme_get_setting('favicon')) .'" type="image/x-icon" />'); |
webmaster@1
|
1706 } |
webmaster@1
|
1707 |
webmaster@1
|
1708 global $theme; |
webmaster@1
|
1709 // Populate all block regions. |
webmaster@1
|
1710 $regions = system_region_list($theme); |
webmaster@1
|
1711 // Load all region content assigned via blocks. |
webmaster@1
|
1712 foreach (array_keys($regions) as $region) { |
webmaster@1
|
1713 // Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE. |
webmaster@1
|
1714 if (!(!$variables['show_blocks'] && ($region == 'left' || $region == 'right'))) { |
webmaster@1
|
1715 $blocks = theme('blocks', $region); |
webmaster@1
|
1716 } |
webmaster@1
|
1717 else { |
webmaster@1
|
1718 $blocks = ''; |
webmaster@1
|
1719 } |
webmaster@1
|
1720 // Assign region to a region variable. |
webmaster@1
|
1721 isset($variables[$region]) ? $variables[$region] .= $blocks : $variables[$region] = $blocks; |
webmaster@1
|
1722 } |
webmaster@1
|
1723 |
webmaster@1
|
1724 // Set up layout variable. |
webmaster@1
|
1725 $variables['layout'] = 'none'; |
webmaster@1
|
1726 if (!empty($variables['left'])) { |
webmaster@1
|
1727 $variables['layout'] = 'left'; |
webmaster@1
|
1728 } |
webmaster@1
|
1729 if (!empty($variables['right'])) { |
webmaster@1
|
1730 $variables['layout'] = ($variables['layout'] == 'left') ? 'both' : 'right'; |
webmaster@1
|
1731 } |
webmaster@1
|
1732 |
webmaster@1
|
1733 // Set mission when viewing the frontpage. |
webmaster@1
|
1734 if (drupal_is_front_page()) { |
webmaster@1
|
1735 $mission = filter_xss_admin(theme_get_setting('mission')); |
webmaster@1
|
1736 } |
webmaster@1
|
1737 |
webmaster@1
|
1738 // Construct page title |
webmaster@1
|
1739 if (drupal_get_title()) { |
webmaster@1
|
1740 $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name', 'Drupal')); |
webmaster@1
|
1741 } |
webmaster@1
|
1742 else { |
webmaster@1
|
1743 $head_title = array(variable_get('site_name', 'Drupal')); |
webmaster@1
|
1744 if (variable_get('site_slogan', '')) { |
webmaster@1
|
1745 $head_title[] = variable_get('site_slogan', ''); |
webmaster@1
|
1746 } |
webmaster@1
|
1747 } |
webmaster@1
|
1748 $variables['head_title'] = implode(' | ', $head_title); |
webmaster@1
|
1749 $variables['base_path'] = base_path(); |
webmaster@1
|
1750 $variables['front_page'] = url(); |
webmaster@1
|
1751 $variables['breadcrumb'] = theme('breadcrumb', drupal_get_breadcrumb()); |
webmaster@1
|
1752 $variables['feed_icons'] = drupal_get_feeds(); |
webmaster@1
|
1753 $variables['footer_message'] = filter_xss_admin(variable_get('site_footer', FALSE)); |
webmaster@1
|
1754 $variables['head'] = drupal_get_html_head(); |
webmaster@1
|
1755 $variables['help'] = theme('help'); |
webmaster@1
|
1756 $variables['language'] = $GLOBALS['language']; |
webmaster@1
|
1757 $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr'; |
webmaster@1
|
1758 $variables['logo'] = theme_get_setting('logo'); |
webmaster@1
|
1759 $variables['messages'] = $variables['show_messages'] ? theme('status_messages') : ''; |
webmaster@1
|
1760 $variables['mission'] = isset($mission) ? $mission : ''; |
webmaster@1
|
1761 $variables['primary_links'] = theme_get_setting('toggle_primary_links') ? menu_primary_links() : array(); |
webmaster@1
|
1762 $variables['secondary_links'] = theme_get_setting('toggle_secondary_links') ? menu_secondary_links() : array(); |
webmaster@1
|
1763 $variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''); |
webmaster@1
|
1764 $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''); |
webmaster@1
|
1765 $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''); |
webmaster@1
|
1766 $variables['css'] = drupal_add_css(); |
webmaster@1
|
1767 $variables['styles'] = drupal_get_css(); |
webmaster@1
|
1768 $variables['scripts'] = drupal_get_js(); |
webmaster@1
|
1769 $variables['tabs'] = theme('menu_local_tasks'); |
webmaster@1
|
1770 $variables['title'] = drupal_get_title(); |
webmaster@1
|
1771 // Closure should be filled last. |
webmaster@1
|
1772 $variables['closure'] = theme('closure'); |
webmaster@1
|
1773 |
webmaster@1
|
1774 if ($node = menu_get_object()) { |
webmaster@1
|
1775 $variables['node'] = $node; |
webmaster@1
|
1776 } |
webmaster@1
|
1777 |
webmaster@1
|
1778 // Compile a list of classes that are going to be applied to the body element. |
webmaster@1
|
1779 // This allows advanced theming based on context (home page, node of certain type, etc.). |
webmaster@1
|
1780 $body_classes = array(); |
webmaster@1
|
1781 // Add a class that tells us whether we're on the front page or not. |
webmaster@1
|
1782 $body_classes[] = $variables['is_front'] ? 'front' : 'not-front'; |
webmaster@1
|
1783 // Add a class that tells us whether the page is viewed by an authenticated user or not. |
webmaster@1
|
1784 $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in'; |
webmaster@1
|
1785 // Add arg(0) to make it possible to theme the page depending on the current page |
webmaster@1
|
1786 // type (e.g. node, admin, user, etc.). To avoid illegal characters in the class, |
webmaster@1
|
1787 // we're removing everything disallowed. We are not using 'a-z' as that might leave |
webmaster@1
|
1788 // in certain international characters (e.g. German umlauts). |
webmaster@1
|
1789 $body_classes[] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', 'page-'. form_clean_id(drupal_strtolower(arg(0)))); |
webmaster@1
|
1790 // If on an individual node page, add the node type. |
webmaster@1
|
1791 if (isset($variables['node']) && $variables['node']->type) { |
webmaster@1
|
1792 $body_classes[] = 'node-type-'. form_clean_id($variables['node']->type); |
webmaster@1
|
1793 } |
webmaster@1
|
1794 // Add information about the number of sidebars. |
webmaster@1
|
1795 if ($variables['layout'] == 'both') { |
webmaster@1
|
1796 $body_classes[] = 'two-sidebars'; |
webmaster@1
|
1797 } |
webmaster@1
|
1798 elseif ($variables['layout'] == 'none') { |
webmaster@1
|
1799 $body_classes[] = 'no-sidebars'; |
webmaster@1
|
1800 } |
webmaster@1
|
1801 else { |
webmaster@1
|
1802 $body_classes[] = 'one-sidebar sidebar-'. $variables['layout']; |
webmaster@1
|
1803 } |
webmaster@1
|
1804 // Implode with spaces. |
webmaster@1
|
1805 $variables['body_classes'] = implode(' ', $body_classes); |
webmaster@1
|
1806 |
webmaster@1
|
1807 // Build a list of suggested template files in order of specificity. One |
webmaster@1
|
1808 // suggestion is made for every element of the current path, though |
webmaster@1
|
1809 // numeric elements are not carried to subsequent suggestions. For example, |
webmaster@1
|
1810 // http://www.example.com/node/1/edit would result in the following |
webmaster@1
|
1811 // suggestions: |
webmaster@1
|
1812 // |
webmaster@1
|
1813 // page-node-edit.tpl.php |
webmaster@1
|
1814 // page-node-1.tpl.php |
webmaster@1
|
1815 // page-node.tpl.php |
webmaster@1
|
1816 // page.tpl.php |
webmaster@1
|
1817 $i = 0; |
webmaster@1
|
1818 $suggestion = 'page'; |
webmaster@1
|
1819 $suggestions = array(); |
webmaster@1
|
1820 while ($arg = arg($i++)) { |
webmaster@1
|
1821 $suggestions[] = $suggestion .'-'. $arg; |
webmaster@1
|
1822 if (!is_numeric($arg)) { |
webmaster@1
|
1823 $suggestion .= '-'. $arg; |
webmaster@1
|
1824 } |
webmaster@1
|
1825 } |
webmaster@1
|
1826 if (drupal_is_front_page()) { |
webmaster@1
|
1827 $suggestions[] = 'page-front'; |
webmaster@1
|
1828 } |
webmaster@1
|
1829 |
webmaster@1
|
1830 if ($suggestions) { |
webmaster@1
|
1831 $variables['template_files'] = $suggestions; |
webmaster@1
|
1832 } |
webmaster@1
|
1833 } |
webmaster@1
|
1834 |
webmaster@1
|
1835 /** |
webmaster@1
|
1836 * Process variables for node.tpl.php |
webmaster@1
|
1837 * |
webmaster@1
|
1838 * Most themes utilize their own copy of node.tpl.php. The default is located |
webmaster@1
|
1839 * inside "modules/node/node.tpl.php". Look in there for the full list of |
webmaster@1
|
1840 * variables. |
webmaster@1
|
1841 * |
webmaster@1
|
1842 * The $variables array contains the following arguments: |
webmaster@1
|
1843 * - $node |
webmaster@1
|
1844 * - $teaser |
webmaster@1
|
1845 * - $page |
webmaster@1
|
1846 * |
webmaster@1
|
1847 * @see node.tpl.php |
webmaster@1
|
1848 */ |
webmaster@1
|
1849 function template_preprocess_node(&$variables) { |
webmaster@1
|
1850 $node = $variables['node']; |
webmaster@1
|
1851 if (module_exists('taxonomy')) { |
webmaster@1
|
1852 $variables['taxonomy'] = taxonomy_link('taxonomy terms', $node); |
webmaster@1
|
1853 } |
webmaster@1
|
1854 else { |
webmaster@1
|
1855 $variables['taxonomy'] = array(); |
webmaster@1
|
1856 } |
webmaster@1
|
1857 |
webmaster@1
|
1858 if ($variables['teaser'] && $node->teaser) { |
webmaster@1
|
1859 $variables['content'] = $node->teaser; |
webmaster@1
|
1860 } |
webmaster@1
|
1861 elseif (isset($node->body)) { |
webmaster@1
|
1862 $variables['content'] = $node->body; |
webmaster@1
|
1863 } |
webmaster@1
|
1864 else { |
webmaster@1
|
1865 $variables['content'] = ''; |
webmaster@1
|
1866 } |
webmaster@1
|
1867 |
webmaster@1
|
1868 $variables['date'] = format_date($node->created); |
webmaster@1
|
1869 $variables['links'] = !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : ''; |
webmaster@1
|
1870 $variables['name'] = theme('username', $node); |
webmaster@1
|
1871 $variables['node_url'] = url('node/'. $node->nid); |
webmaster@1
|
1872 $variables['terms'] = theme('links', $variables['taxonomy'], array('class' => 'links inline')); |
webmaster@1
|
1873 $variables['title'] = check_plain($node->title); |
webmaster@1
|
1874 |
webmaster@1
|
1875 // Flatten the node object's member fields. |
webmaster@1
|
1876 $variables = array_merge((array)$node, $variables); |
webmaster@1
|
1877 |
webmaster@1
|
1878 // Display info only on certain node types. |
webmaster@1
|
1879 if (theme_get_setting('toggle_node_info_'. $node->type)) { |
webmaster@1
|
1880 $variables['submitted'] = theme('node_submitted', $node); |
webmaster@1
|
1881 $variables['picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', $node) : ''; |
webmaster@1
|
1882 } |
webmaster@1
|
1883 else { |
webmaster@1
|
1884 $variables['submitted'] = ''; |
webmaster@1
|
1885 $variables['picture'] = ''; |
webmaster@1
|
1886 } |
webmaster@1
|
1887 // Clean up name so there are no underscores. |
webmaster@1
|
1888 $variables['template_files'][] = 'node-'. $node->type; |
webmaster@1
|
1889 } |
webmaster@1
|
1890 |
webmaster@1
|
1891 /** |
webmaster@1
|
1892 * Process variables for block.tpl.php |
webmaster@1
|
1893 * |
webmaster@1
|
1894 * Prepare the values passed to the theme_block function to be passed |
webmaster@1
|
1895 * into a pluggable template engine. Uses block properties to generate a |
webmaster@1
|
1896 * series of template file suggestions. If none are found, the default |
webmaster@1
|
1897 * block.tpl.php is used. |
webmaster@1
|
1898 * |
webmaster@1
|
1899 * Most themes utilize their own copy of block.tpl.php. The default is located |
webmaster@1
|
1900 * inside "modules/system/block.tpl.php". Look in there for the full list of |
webmaster@1
|
1901 * variables. |
webmaster@1
|
1902 * |
webmaster@1
|
1903 * The $variables array contains the following arguments: |
webmaster@1
|
1904 * - $block |
webmaster@1
|
1905 * |
webmaster@1
|
1906 * @see block.tpl.php |
webmaster@1
|
1907 */ |
webmaster@1
|
1908 function template_preprocess_block(&$variables) { |
webmaster@1
|
1909 static $block_counter = array(); |
webmaster@1
|
1910 // All blocks get an independent counter for each region. |
webmaster@1
|
1911 if (!isset($block_counter[$variables['block']->region])) { |
webmaster@1
|
1912 $block_counter[$variables['block']->region] = 1; |
webmaster@1
|
1913 } |
webmaster@1
|
1914 // Same with zebra striping. |
webmaster@1
|
1915 $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even'; |
webmaster@1
|
1916 $variables['block_id'] = $block_counter[$variables['block']->region]++; |
webmaster@1
|
1917 |
webmaster@1
|
1918 $variables['template_files'][] = 'block-'. $variables['block']->region; |
webmaster@1
|
1919 $variables['template_files'][] = 'block-'. $variables['block']->module; |
webmaster@1
|
1920 $variables['template_files'][] = 'block-'. $variables['block']->module .'-'. $variables['block']->delta; |
webmaster@1
|
1921 } |
webmaster@1
|
1922 |