theme.inc 12.8 KB
Newer Older
Dries's avatar
   
Dries committed
1
<?php
Dries's avatar
   
Dries committed
2
3
/* $Id$ */

4
/**
Dries's avatar
   
Dries committed
5
 @file
6

Dries's avatar
   
Dries committed
7
 Theme System - controls the output of Drupal.
Dries's avatar
   
Dries committed
8

Dries's avatar
   
Dries committed
9
10
 The theme system allows for nearly all output of the Drupal system to be
 customized by user themes.
Dries's avatar
   
Dries committed
11

Dries's avatar
   
Dries committed
12
13
 @see <a href="http://drupal.org/node/view/253">Theme system</a>
 @see themeable
Dries's avatar
   
Dries committed
14
**/
Dries's avatar
   
Dries committed
15

Dries's avatar
   
Dries committed
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
  Hook Help - returns theme specific help and information.

  @param section defines the \a section of the help to be returned.

  @return a string containing the help output.
**/
function theme_help($section) {
  $ouptout = "";

  switch ($section) {
    case 'admin/system/themes#description':
      $output = t("The base theme");
      break;
  }
  return $output;
}

/**
  Initialized the theme system.

  @return the name of the currently selected theme.
**/
function init_theme() {
  global $user;

  $themes = list_themes();
  $name = $user->theme ? $user->theme : variable_get("theme_default", 0);

  $theme->path = "";
  $theme->name = "";

  if (is_object($themes[$name])) {
    include_once($themes[$name]->filename);
    $theme->path = dirname($themes[$name]->filename);
    $theme->name = $name;
  }

  return $theme;
}

/**
  Provides a list of currently available themes.

  @param $refresh

  @return an array of the currently available themes.
**/
function list_themes($refresh = 0) {
  static $list;

  if ($refresh) {
    unset($list);
  }

  if (!$list) {
    $list = array();
    $result = db_query("SELECT * FROM {system} where type = 'theme' AND status = '1' ORDER BY name");
    while ($theme = db_fetch_object($result)) {
      if (file_exists($theme->filename)) {
        $list[$theme->name] = $theme;
      }
    }
  }

  return $list;
}

/**
  External interface of the theme system to all other modules, and core files.

  All requests for themed functions must go through this function. It examines
  the request and routes it to the appropriate theme function. If the current
  theme does not implement the requested function, then the base theme function
  is called.
  Example: \verbatim $header_text = theme("header"); \endverbatim

  @return themed output.
**/
function theme() {
  global $theme;

  $args = func_get_args();
  $function = array_shift($args);

  if (($theme->name != "") && (function_exists($theme->name ."_". $function))) {
    return call_user_func_array($theme->name ."_". $function, $args);
  }
  elseif (function_exists("theme_". $function)){
    return call_user_func_array("theme_". $function, $args);
  }
}

/**
  Returns the path to the currently selected theme.

  @return the path to the the currently selected theme.
**/
function path_to_theme() {
  global $theme;
  return $theme->path;
}

/**
Dries's avatar
Dries committed
120
  @defgroup themeable Themeable functions
Dries's avatar
   
Dries committed
121
122
  @{

Dries's avatar
Dries committed
123
  Themeable functions - functions that can be styled differently in themes.
Dries's avatar
   
Dries committed
124
125
126
127

  @see  theme
  @see  theme.inc
**/
Dries's avatar
   
Dries committed
128

Dries's avatar
   
Dries committed
129
130
/**
  Returns the theme header.
Dries's avatar
   
Dries committed
131

Kjartan's avatar
Kjartan committed
132
  @return a string containing the \a header output.
Dries's avatar
   
Dries committed
133
**/
Dries's avatar
   
Dries committed
134
function theme_header() {
Dries's avatar
   
Dries committed
135
  global $base_url;
Dries's avatar
   
Dries committed
136

Dries's avatar
   
Dries committed
137
138
  $output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
  $output .= "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
Dries's avatar
   
Dries committed
139
  $output .= "<head>";
Dries's avatar
   
Dries committed
140
  $output .= " <title>". drupal_get_title() ? drupal_get_title() : variable_get(site_name, "drupal") ."</title>";
Dries's avatar
   
Dries committed
141
  $output .= theme_head($main);
Dries's avatar
   
Dries committed
142
143
144
145
146
147
  $output .= " <style type=\"text/css\" media=\"all\">";
  $output .= "  @import url(misc/drupal.css);";
  $output .= " </style>";

  $output .= " </head>";
  $output .= " <body style=\"background-color: #fff; color: #000;\"". theme("onload_attribute"). "\">";
Dries's avatar
   
Dries committed
148
149
  $output .= "<table border=\"0\" cellspacing=\"4\" cellpadding=\"4\"><tr><td style=\"vertical-align: top; width: 170px;\">";

Dries's avatar
   
Dries committed
150
  $output .= theme("box", t("Navigation"), @implode("<br />", link_page()));
151
  $output .= theme("blocks", "all");
Dries's avatar
   
Dries committed
152
153
  $output .= "</td><td style=\"vertical-align: top;\">";

Dries's avatar
   
Dries committed
154
155
156
157
158
159
  $output .= theme("breadcrumb", drupal_get_breadcrumb());
  $output .= "<h1>" . drupal_get_title() . "</h1>";
  if ($help = menu_get_active_help()) {
    $output .= "<small>$help</small><hr />";
  }

Dries's avatar
   
Dries committed
160
  return $output;
Dries's avatar
   
Dries committed
161
}
Dries's avatar
   
Dries committed
162

Dries's avatar
   
Dries committed
163
/**
Dries's avatar
   
Dries committed
164
165
166
167
168
169
170
171
172
 * Returns an entire Drupal page displaying the supplied content.
 *
 * @param $content    a string containing the content to display
 * @param $title      (optional) page title (\<head>\<title>)
 * @param $breadcrumb (optional) page breadcrumb
 *
 * @see   drupal_breadcrumb
 *
 * @return a string containing the \a page output.
Dries's avatar
   
Dries committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
**/
function theme_page($content, $title = NULL, $breadcrumb = NULL) {
  if (isset($title)) {
    drupal_set_title($title);
  }
  if (isset($breadcrumb)) {
    drupal_set_breadcrumb($breadcrumb);
  }

  $output = theme("header");
  $output .= $content;
  $output .= theme("footer");

  return $output;
}

Dries's avatar
   
Dries committed
189
190
191
192
/**
  Returns themed set of links.

  @param $links an array of \a links to be themed.
Kjartan's avatar
Kjartan committed
193
  @param $delimiter (optional) \a delimiter used to separate the links.
Dries's avatar
   
Dries committed
194

Kjartan's avatar
Kjartan committed
195
  @return a string containing the \a links output.
Dries's avatar
   
Dries committed
196
**/
Dries's avatar
   
Dries committed
197
198
199
function theme_links($links, $delimiter = " | ") {
  return implode($delimiter, $links);
}
Dries's avatar
   
Dries committed
200

Dries's avatar
   
Dries committed
201
202
203
204
205
/**
  Returns themed image.

  @param $name the \a name of the image file.

Kjartan's avatar
Kjartan committed
206
  @return a string containing the \a image output.
Dries's avatar
   
Dries committed
207
**/
Dries's avatar
   
Dries committed
208
209
210
function theme_image($name) {
  return "misc/$name";
}
Dries's avatar
   
Dries committed
211

Dries's avatar
   
Dries committed
212
213
214
215
216
/**
  Returns a themed breadcrumb menu.

  @param $breadcrumb an array containing the breadcrumb links.

Kjartan's avatar
Kjartan committed
217
  @return a string containing the \a breadcrumb output.
Dries's avatar
   
Dries committed
218
**/
Dries's avatar
   
Dries committed
219
function theme_breadcrumb($breadcrumb) {
Dries's avatar
   
Dries committed
220
  return "<div class=\"breadcrumb\">". implode($breadcrumb, " &raquo; ") ."</div>";
Dries's avatar
   
Dries committed
221
}
Dries's avatar
   
Dries committed
222

Dries's avatar
   
Dries committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/**
  Returns themed node.

  The passed $node object provides a all relevant information for displaying a node:
  \li \c $node->nid
  \li \c $node->type i.e. story, blog, forum.
  \li \c $node->title
  \li \c $node->created a unix timestamp.
  \li \c $node->teaser
  \li \c $node->body
  \li \c $node->changed a unix timestamp.
  \li \c $node->uid the id of the poster.
  \li \c $node->username the username of the poster.

  @param $node the \a node to be themed.
Dries's avatar
   
Dries committed
238
239
  @param $main Display teaser only, as on main page?
  @param $page Display node as standalone page (no title)?
Dries's avatar
   
Dries committed
240

Kjartan's avatar
Kjartan committed
241
  @return a string containing the \a node output.
Dries's avatar
   
Dries committed
242
**/
Dries's avatar
   
Dries committed
243
function theme_node($node, $main = 0, $page = 0) {
Dries's avatar
   
Dries committed
244
245
  if (module_exist("taxonomy")) {
    $terms = taxonomy_link("taxonomy terms", $node);
Dries's avatar
   
Dries committed
246
247
  }

Dries's avatar
   
Dries committed
248
249
250
251
252
253
  if ($page == 0) {
    $output = "<h2>$node->title</h2> by ". format_name($node);
  }
  else {
    $output = "by ". format_name($node);
  }
Dries's avatar
   
Dries committed
254
255

  if (count($terms)) {
Dries's avatar
   
Dries committed
256
    $output .= " <small>(". print theme("links", $terms) .")</small><br />";
Dries's avatar
   
Dries committed
257
258
  }

Dries's avatar
   
Dries committed
259
260
261
262
263
  if ($main && $node->teaser) {
    $output .= $node->teaser;
  }
  else {
    $output .= $node->body;
Dries's avatar
   
Dries committed
264
265
  }

Dries's avatar
   
Dries committed
266
  if ($links = link_node($node, $main)) {
Dries's avatar
   
Dries committed
267
    $output .= "<br />[ ". print theme("links", $links) ." ]";
Dries's avatar
   
Dries committed
268
  }
Dries's avatar
   
Dries committed
269
270
  $output .= "<hr />";

Dries's avatar
   
Dries committed
271
  return $output;
Dries's avatar
   
Dries committed
272
273
}

Dries's avatar
   
Dries committed
274
/**
Dries's avatar
Dries committed
275
  Returns themed form element.
Dries's avatar
   
Dries committed
276
277
278
279
280
281
282
283
284

  @param $title the form element's title
  @param $value the form element's data
  @param $description the form element's description or explanation

  @return a string contraining the \a node output.
**/

function theme_form_element($title, $value, $description = 0) {
285
  return "<div class=\"form-item\">". ($title ? "<label>$title:</label><br />" : "") . $value . ($description ? "<div class=\"description\">$description</div>" : "") ."</div>\n";
Dries's avatar
   
Dries committed
286
}
Dries's avatar
   
Dries committed
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

/**
  Returns themed table.

  @param $header
  @param $rows

  @return a string contraining the \a node output.
**/

function theme_table($header, $rows) {

  $output = "<table>\n";

  /*
  ** Emit the table header:
  */

  if (is_array($header)) {
    $output .= " <tr>";
    foreach ($header as $cell) {
      if (is_array($cell) && $cell["field"]) {
        $cell = tablesort($cell, $header);
      }
      $output .= _theme_table_cell($cell, 1);
    }
    $output .= " </tr>\n";
  }

  /*
  ** Emit the table rows:
  */

  if (is_array($rows)) {
    foreach ($rows as $number => $row) {
      if ($number % 2 == 1) {
        $output .= " <tr class=\"light\">";
      }
      else {
        $output .= " <tr class=\"dark\">";
      }

      foreach ($row as $cell) {
        $output .= _theme_table_cell($cell, 0);
      }
      $output .= " </tr>\n";
    }
  }

  $output .= "</table>\n";

  return $output;
}

Dries's avatar
   
Dries committed
341
342
343
344
345
/**
  Returns themed box.

  @param $subject the \a subject of the box.
  @param $content the \a content of the box.
Kjartan's avatar
Kjartan committed
346
  @param $region the \a region of the box.
Dries's avatar
   
Dries committed
347

Kjartan's avatar
Kjartan committed
348
  @return a string containing the \a box output.
Dries's avatar
   
Dries committed
349
**/
Dries's avatar
   
Dries committed
350
351
function theme_box($subject, $content, $region = "main") {
  $output = "<h2>$subject</h2><p>$content</p>";
Dries's avatar
   
Dries committed
352
  return $output;
Dries's avatar
   
Dries committed
353
354
355
}

/**
Dries's avatar
   
Dries committed
356
357
358
359
360
361
362
363
364
365
  Returns a themed block.

  You can style your blocks by defining .block (all blocks),
  .block-<i>module</i> (all blocks of module <i>module</i>),
  and \#block-<i>module</i>-<i>delta</i> (specific block of
  module <i>module</i> with delta <i>delta</i>) in your
  theme's CSS.

  @param $block object "indexed with" fields from database table 'blocks' ($block->module, $block->delta, $block->region, ...) and fields returned by <i>module</i>_block("view") ($block->subject, $block->content, ...).

Kjartan's avatar
Kjartan committed
366
  @return a string containing the \a box output.
Dries's avatar
   
Dries committed
367
**/
Dries's avatar
   
Dries committed
368
369
function theme_block($block) {
  $output  = "<div class=\"block block-$block->module\" id=\"block-$block->module-$block->delta\">";
Dries's avatar
   
Dries committed
370
  $output .= " <h3>$block->subject</h3>";
Dries's avatar
   
Dries committed
371
372
  $output .= " <div class=\"content\">$block->content</div>";
  $output .= "</div>";
Dries's avatar
   
Dries committed
373
  return $output;
Dries's avatar
   
Dries committed
374
}
Dries's avatar
   
Dries committed
375

Dries's avatar
   
Dries committed
376
377
378
/**
  Returns themed page footer.

Kjartan's avatar
Kjartan committed
379
  @return a string containing the \a footer output.
Dries's avatar
   
Dries committed
380
**/
Dries's avatar
   
Dries committed
381
382
function theme_footer() {
  $output = "</td></tr></table>";
Dries's avatar
   
Dries committed
383
  $output .= theme_closure();
Dries's avatar
   
Dries committed
384
  $output .= "</body></html>";
Dries's avatar
   
Dries committed
385
  return $output;
Dries's avatar
   
Dries committed
386
}
Kjartan's avatar
Changes    
Kjartan committed
387

Dries's avatar
   
Dries committed
388
/**
Dries's avatar
   
Dries committed
389
390
  Returns themed marker, useful for marking new comments or required form elements.

Kjartan's avatar
Kjartan committed
391
  @return a string containing the \a mark output.
Dries's avatar
   
Dries committed
392
**/
Dries's avatar
   
Dries committed
393
function theme_mark() {
Dries's avatar
   
Dries committed
394
  return "<span class=\"marker\">*</span>";
Dries's avatar
   
Dries committed
395
396
}

Dries's avatar
   
Dries committed
397
/**
Dries's avatar
   
Dries committed
398
399
400
401
402
  Returns themed list of items.

  @param $items (optional) an array of the items to be displayed in a list.
  @param $title (optional) the title of the list.

Kjartan's avatar
Kjartan committed
403
  @return a string containing the \a list output.
Dries's avatar
   
Dries committed
404
**/
Dries's avatar
   
Dries committed
405
function theme_item_list($items = array(), $title = NULL) {
Dries's avatar
   
Dries committed
406
  $output .= "<div class=\"item-list\">";
Dries's avatar
   
Dries committed
407
  if (isset($title)) {
Dries's avatar
   
Dries committed
408
    $output .= "<h3>$title</h3>";
Dries's avatar
   
Dries committed
409
410
  }

Dries's avatar
   
Dries committed
411
  if (isset($items)) {
Dries's avatar
   
Dries committed
412
    $output .= "<ul>";
Dries's avatar
   
Dries committed
413
    foreach ($items as $item) {
Dries's avatar
   
Dries committed
414
      $output .= "<li>$item</li>";
Dries's avatar
   
Dries committed
415
    }
Dries's avatar
   
Dries committed
416
    $output .= "</ul>";
Dries's avatar
   
Dries committed
417
  }
Dries's avatar
   
Dries committed
418
  $output .= "</div>";
Dries's avatar
   
Dries committed
419
420
421
  return $output;
}

Dries's avatar
   
Dries committed
422
/**
Dries's avatar
   
Dries committed
423
424
425
426
  Returns themed error message.

  @param $message the error message to be themed.

Kjartan's avatar
Kjartan committed
427
  @return a string containing the \a error output.
Dries's avatar
   
Dries committed
428
**/
Dries's avatar
   
Dries committed
429
function theme_error($message) {
Dries's avatar
   
Dries committed
430
  return "<div class=\"error\">$message</div>";
Dries's avatar
   
Dries committed
431
432
}

Dries's avatar
   
Dries committed
433
434
/**
  Execute hook _head which is run at the start of the page, and output should be in the head tags.
Dries's avatar
   
Dries committed
435

Dries's avatar
   
Dries committed
436
  @param $main (optional)
437

Kjartan's avatar
Kjartan committed
438
  @return a string containing the \a error output.
Dries's avatar
   
Dries committed
439
**/
Dries's avatar
   
Dries committed
440
function theme_head($main = 0) {
Dries's avatar
   
Dries committed
441
  global $base_url;
Dries's avatar
   
Dries committed
442
  $output .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
Dries's avatar
   
Dries committed
443
444
445
446
  $output .= "<base href=\"$base_url/\" />\n";
  $output .= "<style type=\"text/css\">\n";
  $output .= "@import url(misc/drupal.css);\n";
  $output .= "</style>\n";
Dries's avatar
   
Dries committed
447
  $head = module_invoke_all("head", $main);
Dries's avatar
   
Dries committed
448
449
  $output .= implode($head, "\n");
  return $output;
Dries's avatar
   
Dries committed
450
451
}

Dries's avatar
   
Dries committed
452
/**
Dries's avatar
   
Dries committed
453
  Execute hook _footer() which is run at the end of the page right
Dries's avatar
   
Dries committed
454
  before the \</body> tag.
Dries's avatar
   
Dries committed
455
456
457

  @param $main (optional)

Kjartan's avatar
Kjartan committed
458
  @return a string containing the \a closure output.
Dries's avatar
   
Dries committed
459
**/
Dries's avatar
   
Dries committed
460
function theme_closure($main = 0) {
Dries's avatar
   
Dries committed
461
462
463
464
  $footer = module_invoke_all("footer", $main);
  return implode($footer, "\n");
}

Dries's avatar
   
Dries committed
465
466
467
/**
  Call _onload hook in all modules to enable modules to insert javascript
  that will get run once the page has been loaded by the browser.
468

Dries's avatar
   
Dries committed
469
  @param $theme_onloads (optional) addition onload directives.
Dries's avatar
   
Dries committed
470

Kjartan's avatar
Kjartan committed
471
  @return a string containing the \a onload output.
Dries's avatar
   
Dries committed
472
473
474
475
**/
function theme_onload_attribute($theme_onloads = array()) {
  if (!is_array($theme_onloads)) {
    $theme_onloads = array($theme_onloads);
Dries's avatar
   
Dries committed
476
  }
Dries's avatar
   
Dries committed
477
478
479
480
481
  // Merge theme onloads (javascript rollovers, image preloads, etc.)
  // with module onloads (htmlarea, etc.)
  $onloads = array_merge(module_invoke_all("onload"), $theme_onloads);
  if (count($onloads)) {
    return " onload=\"" . implode("; ", $onloads) . "\"";
Dries's avatar
   
Dries committed
482
  }
Dries's avatar
   
Dries committed
483
  return "";
Dries's avatar
   
Dries committed
484
485
}

Dries's avatar
   
Dries committed
486
/**
487
488
489
490
491
492
493
 * Returns themed blocks available for current $user at $region.
 *
 * @param       $region   main|left|right
 *
 * @return      a string containing the \a blocks output.
 */
function theme_blocks($region) {
Dries's avatar
   
Dries committed
494
  $output = "";
495
496
497
498
499

  if ($list = module_invoke('block', 'list', $region)) {
    foreach ($list as $key => $block) {
      // $key == <i>module</i>_<i>delta</i>
      $output .= theme('block', $block);
Dries's avatar
   
Dries committed
500
501
    }
  }
Dries's avatar
   
Dries committed
502
  return $output;
Dries's avatar
   
Dries committed
503
}
Dries's avatar
   
Dries committed
504
/* @} End of defgroup themeable */
505

Dries's avatar
   
Dries committed
506
507
508
509
510
511
function _theme_table_cell($cell, $header = 0) {
  if (is_array($cell)) {
    $data = $cell["data"];
    foreach ($cell as $key => $value) {
      if ($key != "data")  {
        $attributes .= " $key=\"$value\"";
Dries's avatar
   
Dries committed
512
513
      }
    }
Dries's avatar
   
Dries committed
514
  }
Dries's avatar
   
Dries committed
515
516
  else {
    $data = $cell;
Dries's avatar
   
Dries committed
517
  }
Dries's avatar
   
Dries committed
518

Dries's avatar
   
Dries committed
519
520
  if ($header) {
    $output = "<th$attributes>$data</th>";
Dries's avatar
   
Dries committed
521
  }
Dries's avatar
   
Dries committed
522
523
  else {
    $output = "<td$attributes>$data</td>";
Dries's avatar
   
Dries committed
524
  }
Dries's avatar
   
Dries committed
525

Dries's avatar
   
Dries committed
526
527
  return $output;
}
Dries's avatar
   
Dries committed
528
?>