LOnger caching options
[moodle.git] / lib / weblib.php
CommitLineData
abf45bed 1<?php // $Id$
f9903ed0 2
9fa49e22 3///////////////////////////////////////////////////////////////////////////
4// //
5// NOTICE OF COPYRIGHT //
6// //
7// Moodle - Modular Object-Oriented Dynamic Learning Environment //
8// http://moodle.com //
9// //
10// Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
11// //
12// This program is free software; you can redistribute it and/or modify //
13// it under the terms of the GNU General Public License as published by //
14// the Free Software Foundation; either version 2 of the License, or //
15// (at your option) any later version. //
16// //
17// This program is distributed in the hope that it will be useful, //
18// but WITHOUT ANY WARRANTY; without even the implied warranty of //
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
20// GNU General Public License for more details: //
21// //
22// http://www.gnu.org/copyleft/gpl.html //
23// //
24///////////////////////////////////////////////////////////////////////////
f9903ed0 25
7cf1c7bd 26/**
27 * Library of functions for web output
28 *
29 * Library of all general-purpose Moodle PHP functions and constants
30 * that produce HTML output
31 *
32 * Other main libraries:
33 * - datalib.php - functions that access the database.
34 * - moodlelib.php - general-purpose Moodle functions.
35 * @author Martin Dougiamas
36 * @version $Id$
89dcb99d 37 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7cf1c7bd 38 * @package moodlecore
39 */
772e78be 40
0095d5cd 41/// Constants
42
c1d57101 43/// Define text formatting types ... eventually we can add Wiki, BBcode etc
7cf1c7bd 44
45/**
46 * Does all sorts of transformations and filtering
47 */
b0ccd3fb 48define('FORMAT_MOODLE', '0'); // Does all sorts of transformations and filtering
7cf1c7bd 49
50/**
51 * Plain HTML (with some tags stripped)
52 */
b0ccd3fb 53define('FORMAT_HTML', '1'); // Plain HTML (with some tags stripped)
7cf1c7bd 54
55/**
56 * Plain text (even tags are printed in full)
57 */
b0ccd3fb 58define('FORMAT_PLAIN', '2'); // Plain text (even tags are printed in full)
7cf1c7bd 59
60/**
61 * Wiki-formatted text
6a6495ff 62 * Deprecated: left here just to note that '3' is not used (at the moment)
63 * and to catch any latent wiki-like text (which generates an error)
7cf1c7bd 64 */
b0ccd3fb 65define('FORMAT_WIKI', '3'); // Wiki-formatted text
7cf1c7bd 66
67/**
68 * Markdown-formatted text http://daringfireball.net/projects/markdown/
69 */
b0ccd3fb 70define('FORMAT_MARKDOWN', '4'); // Markdown-formatted text http://daringfireball.net/projects/markdown/
0095d5cd 71
7cf1c7bd 72
73/**
74 * Allowed tags - string of html tags that can be tested against for safe html tags
75 * @global string $ALLOWED_TAGS
76 */
39dda0fc 77$ALLOWED_TAGS =
21fca825 78'<p><br><b><i><u><font><table><tbody><span><div><tr><td><th><ol><ul><dl><li><dt><dd><h1><h2><h3><h4><h5><h6><hr><img><a><strong><emphasis><em><sup><sub><address><cite><blockquote><pre><strike><embed><object><param><acronym><nolink><lang><tex><algebra><math><mi><mn><mo><mtext><mspace><ms><mrow><mfrac><msqrt><mroot><mstyle><merror><mpadded><mphantom><mfenced><msub><msup><msubsup><munder><mover><munderover><mmultiscripts><mtable><mtr><mtd><maligngroup><malignmark><maction><cn><ci><apply><reln><fn><interval><inverse><sep><condition><declare><lambda><compose><ident><quotient><exp><factorial><divide><max><min><minus><plus><power><rem><times><root><gcd><and><or><xor><not><implies><forall><exists><abs><conjugate><eq><neq><gt><lt><geq><leq><ln><log><int><diff><partialdiff><lowlimit><uplimit><bvar><degree><set><list><union><intersect><in><notin><subset><prsubset><notsubset><notprsubset><setdiff><sum><product><limit><tendsto><mean><sdev><variance><median><mode><moment><vector><matrix><matrixrow><determinant><transpose><selector><annotation><semantics><annotation-xml><tt><code>';
3fe3851d 79
037dcbb6 80/**
81 * Allowed protocols - array of protocols that are safe to use in links and so on
82 * @global string $ALLOWED_PROTOCOLS
83 */
32d4301b 84$ALLOWED_PROTOCOLS = array('http', 'https', 'ftp', 'news', 'mailto', 'rtsp', 'teamspeak', 'gopher', 'color', 'callto');
037dcbb6 85
86
0095d5cd 87/// Functions
88
7cf1c7bd 89/**
90 * Add quotes to HTML characters
91 *
92 * Returns $var with HTML characters (like "<", ">", etc.) properly quoted.
93 * This function is very similar to {@link p()}
94 *
95 * @param string $var the string potentially containing HTML characters
96 * @return string
97 */
3662bce5 98function s($var) {
f9903ed0 99
3662bce5 100 if (empty($var)) {
b0ccd3fb 101 return '';
3662bce5 102 }
7d8f674d 103 return htmlSpecialChars(stripslashes_safe($var));
f9903ed0 104}
105
7cf1c7bd 106/**
107 * Add quotes to HTML characters
108 *
d48b00b4 109 * Prints $var with HTML characters (like "<", ">", etc.) properly quoted.
7cf1c7bd 110 * This function is very similar to {@link s()}
111 *
112 * @param string $var the string potentially containing HTML characters
113 * @return string
114 */
3662bce5 115function p($var) {
f9903ed0 116
3662bce5 117 if (empty($var)) {
b0ccd3fb 118 echo '';
3662bce5 119 }
7d8f674d 120 echo htmlSpecialChars(stripslashes_safe($var));
f9903ed0 121}
122
7cf1c7bd 123
124/**
125 * Ensure that a variable is set
126 *
772e78be 127 * Return $var if it is defined, otherwise return $default,
7cf1c7bd 128 * This function is very similar to {@link optional_variable()}
129 *
130 * @param mixed $var the variable which may be unset
131 * @param mixed $default the value to return if $var is unset
132 * @return mixed
133 */
b0ccd3fb 134function nvl(&$var, $default='') {
8553b700 135
136 return isset($var) ? $var : $default;
137}
f9903ed0 138
7cf1c7bd 139/**
140 * Remove query string from url
141 *
142 * Takes in a URL and returns it without the querystring portion
143 *
144 * @param string $url the url which may have a query string attached
145 * @return string
146 */
147 function strip_querystring($url) {
f9903ed0 148
b9b8ab69 149 if ($commapos = strpos($url, '?')) {
150 return substr($url, 0, $commapos);
151 } else {
152 return $url;
153 }
f9903ed0 154}
155
7cf1c7bd 156/**
157 * Returns the URL of the HTTP_REFERER, less the querystring portion
158 * @return string
159 */
f9903ed0 160function get_referer() {
f9903ed0 161
b0ccd3fb 162 return strip_querystring(nvl($_SERVER['HTTP_REFERER']));
f9903ed0 163}
164
c1d57101 165
7cf1c7bd 166/**
167 * Returns the name of the current script, WITH the querystring portion.
168 * this function is necessary because PHP_SELF and REQUEST_URI and SCRIPT_NAME
169 * return different things depending on a lot of things like your OS, Web
170 * server, and the way PHP is compiled (ie. as a CGI, module, ISAPI, etc.)
d48b00b4 171 * <b>NOTE:</b> This function returns false if the global variables needed are not set.
172 *
7cf1c7bd 173 * @return string
174 */
175 function me() {
f9903ed0 176
b0ccd3fb 177 if (!empty($_SERVER['REQUEST_URI'])) {
178 return $_SERVER['REQUEST_URI'];
c1d57101 179
b0ccd3fb 180 } else if (!empty($_SERVER['PHP_SELF'])) {
181 if (!empty($_SERVER['QUERY_STRING'])) {
182 return $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING'];
fced815c 183 }
b0ccd3fb 184 return $_SERVER['PHP_SELF'];
c1d57101 185
b0ccd3fb 186 } else if (!empty($_SERVER['SCRIPT_NAME'])) {
187 if (!empty($_SERVER['QUERY_STRING'])) {
188 return $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING'];
fced815c 189 }
b0ccd3fb 190 return $_SERVER['SCRIPT_NAME'];
fced815c 191
b0ccd3fb 192 } else if (!empty($_SERVER['URL'])) { // May help IIS (not well tested)
193 if (!empty($_SERVER['QUERY_STRING'])) {
194 return $_SERVER['URL'] .'?'. $_SERVER['QUERY_STRING'];
16c4d82a 195 }
b0ccd3fb 196 return $_SERVER['URL'];
16c4d82a 197
b9b8ab69 198 } else {
b0ccd3fb 199 notify('Warning: Could not find any of these web server variables: $REQUEST_URI, $PHP_SELF, $SCRIPT_NAME or $URL');
bcdfe14e 200 return false;
7fbd6b1c 201 }
f9903ed0 202}
203
7cf1c7bd 204/**
d48b00b4 205 * Like {@link me()} but returns a full URL
7cf1c7bd 206 * @see me()
7cf1c7bd 207 * @return string
208 */
f9903ed0 209function qualified_me() {
f9903ed0 210
b6e22603 211 global $CFG;
212
68796e6b 213 if (!empty($CFG->wwwroot)) {
214 $url = parse_url($CFG->wwwroot);
215 }
b6e22603 216
217 if (!empty($url['host'])) {
218 $hostname = $url['host'];
219 } else if (!empty($_SERVER['SERVER_NAME'])) {
b0ccd3fb 220 $hostname = $_SERVER['SERVER_NAME'];
221 } else if (!empty($_ENV['SERVER_NAME'])) {
222 $hostname = $_ENV['SERVER_NAME'];
223 } else if (!empty($_SERVER['HTTP_HOST'])) {
224 $hostname = $_SERVER['HTTP_HOST'];
225 } else if (!empty($_ENV['HTTP_HOST'])) {
226 $hostname = $_ENV['HTTP_HOST'];
39e018b3 227 } else {
b0ccd3fb 228 notify('Warning: could not find the name of this server!');
bcdfe14e 229 return false;
c1d57101 230 }
f77c261e 231 if (isset($_SERVER['HTTPS'])) {
232 $protocol = ($_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
233 } else if (isset($_SERVER['SERVER_PORT'])) { # Apache2 does not export $_SERVER['HTTPS']
234 $protocol = ($_SERVER['SERVER_PORT'] == '443') ? 'https://' : 'http://';
235 } else {
236 $protocol = 'http://';
237 }
f9903ed0 238
39e018b3 239 $url_prefix = $protocol.$hostname;
b9b8ab69 240 return $url_prefix . me();
f9903ed0 241}
242
7cf1c7bd 243/**
244 * Determine if a web referer is valid
245 *
246 * Returns true if the referer is the same as the goodreferer. If
247 * the referer to test is not specified, use {@link qualified_me()}.
248 * If the admin has not set secure forms ($CFG->secureforms) then
249 * this function returns true regardless of a match.
d48b00b4 250 *
7cf1c7bd 251 * @uses $CFG
252 * @param string $goodreferer the url to compare to referer
253 * @return boolean
254 */
b0ccd3fb 255function match_referer($goodreferer = '') {
60f18531 256 global $CFG;
257
ae384ef1 258 if (empty($CFG->secureforms)) { // Don't bother checking referer
60f18531 259 return true;
260 }
f9903ed0 261
b0ccd3fb 262 if ($goodreferer == 'nomatch') { // Don't bother checking referer
a0deb5db 263 return true;
264 }
265
ab9f24ad 266 if (empty($goodreferer)) {
267 $goodreferer = qualified_me();
c1d57101 268 }
67b1b6c2 269
9d54c2fb 270 $referer = get_referer();
271
b0ccd3fb 272 return (($referer == $goodreferer) or ($referer == $CFG->wwwroot .'/'));
f9903ed0 273}
274
7cf1c7bd 275/**
276 * Determine if there is data waiting to be processed from a form
277 *
278 * Used on most forms in Moodle to check for data
279 * Returns the data as an object, if it's found.
280 * This object can be used in foreach loops without
281 * casting because it's cast to (array) automatically
772e78be 282 *
7cf1c7bd 283 * Checks that submitted POST data exists, and also
284 * checks the referer against the given url (it uses
d48b00b4 285 * the current page if none was specified.
286 *
7cf1c7bd 287 * @uses $CFG
288 * @param string $url the url to compare to referer for secure forms
289 * @return boolean
290 */
b0ccd3fb 291function data_submitted($url='') {
d48b00b4 292
36b4f985 293
37208cd2 294 global $CFG;
295
607809b3 296 if (empty($_POST)) {
36b4f985 297 return false;
607809b3 298
36b4f985 299 } else {
300 if (match_referer($url)) {
607809b3 301 return (object)$_POST;
36b4f985 302 } else {
303 if ($CFG->debug > 10) {
b0ccd3fb 304 notice('The form did not come from this page! (referer = '. get_referer() .')');
36b4f985 305 }
306 return false;
307 }
308 }
309}
310
7cf1c7bd 311/**
312 * Moodle replacement for php stripslashes() function
313 *
772e78be 314 * The standard php stripslashes() removes ALL backslashes
7cf1c7bd 315 * even from strings - so C:\temp becomes C:temp - this isn't good.
316 * This function should work as a fairly safe replacement
317 * to be called on quoted AND unquoted strings (to be sure)
d48b00b4 318 *
7cf1c7bd 319 * @param string the string to remove unsafe slashes from
320 * @return string
321 */
7d8f674d 322function stripslashes_safe($string) {
7d8f674d 323
324 $string = str_replace("\\'", "'", $string);
325 $string = str_replace('\\"', '"', $string);
b403c32a 326 $string = str_replace('\\\\', '\\', $string);
7d8f674d 327 return $string;
328}
f9903ed0 329
9b4b78fd 330/**
331 * Recursive implementation of stripslashes()
332 *
333 * This function will allow you to strip the slashes from a variable.
334 * If the variable is an array or object, slashes will be stripped
335 * from the items (or properties) it contains, even if they are arrays
336 * or objects themselves.
337 *
338 * @param mixed the variable to remove slashes from
339 * @return mixed
340 */
341function stripslashes_recursive($var) {
342 if(is_object($var)) {
343 $properties = get_object_vars($var);
344 foreach($properties as $property => $value) {
345 $var->$property = stripslashes_recursive($value);
346 }
347 }
348 else if(is_array($var)) {
349 foreach($var as $property => $value) {
350 $var[$property] = stripslashes_recursive($value);
351 }
352 }
353 else if(is_string($var)) {
354 $var = stripslashes($var);
355 }
356 return $var;
357}
358
7cf1c7bd 359/**
d48b00b4 360 * Given some normal text this function will break up any
361 * long words to a given size by inserting the given character
362 *
7cf1c7bd 363 * @param string $string the string to be modified
89dcb99d 364 * @param int $maxsize maximum length of the string to be returned
7cf1c7bd 365 * @param string $cutchar the string used to represent word breaks
366 * @return string
367 */
4a5644e5 368function break_up_long_words($string, $maxsize=20, $cutchar=' ') {
a2b3f884 369
8f7dc7f1 370 static $currentlang;
4a5644e5 371
8f7dc7f1 372 if (empty($currentlang)) {
373 $currentlang = current_language();
374 }
375
376 if (in_array(substr($currentlang,0,2), array('ja', 'kn', 'sr', 'vi', 'zh'))) { // Multibyte languages
5b07d990 377 return $string;
378 }
379
4a5644e5 380 $output = '';
381 $length = strlen($string);
382 $wordlength = 0;
383
384 for ($i=0; $i<$length; $i++) {
385 $char = $string[$i];
386 if ($char == ' ' or $char == "\t" or $char == "\n" or $char == "\r") {
387 $wordlength = 0;
388 } else {
389 $wordlength++;
390 if ($wordlength > $maxsize) {
391 $output .= $cutchar;
392 $wordlength = 0;
393 }
394 }
395 $output .= $char;
396 }
397 return $output;
398}
399
7cf1c7bd 400/**
401 * This does a search and replace, ignoring case
402 * This function is only used for versions of PHP older than version 5
403 * which do not have a native version of this function.
404 * Taken from the PHP manual, by bradhuizenga @ softhome.net
d48b00b4 405 *
7cf1c7bd 406 * @param string $find the string to search for
407 * @param string $replace the string to replace $find with
408 * @param string $string the string to search through
409 * return string
410 */
ce57cc79 411if (!function_exists('str_ireplace')) { /// Only exists in PHP 5
7ec2fc00 412 function str_ireplace($find, $replace, $string) {
7ec2fc00 413
414 if (!is_array($find)) {
415 $find = array($find);
416 }
417
418 if(!is_array($replace)) {
419 if (!is_array($find)) {
420 $replace = array($replace);
421 } else {
422 // this will duplicate the string into an array the size of $find
423 $c = count($find);
424 $rString = $replace;
425 unset($replace);
426 for ($i = 0; $i < $c; $i++) {
427 $replace[$i] = $rString;
428 }
429 }
430 }
431
432 foreach ($find as $fKey => $fItem) {
433 $between = explode(strtolower($fItem),strtolower($string));
434 $pos = 0;
435 foreach($between as $bKey => $bItem) {
436 $between[$bKey] = substr($string,$pos,strlen($bItem));
437 $pos += strlen($bItem) + strlen($fItem);
438 }
439 $string = implode($replace[$fKey],$between);
72e4eac6 440 }
7ec2fc00 441 return ($string);
3fe3851d 442 }
3fe3851d 443}
444
7cf1c7bd 445/**
446 * Locate the position of a string in another string
447 *
448 * This function is only used for versions of PHP older than version 5
449 * which do not have a native version of this function.
450 * Taken from the PHP manual, by dmarsh @ spscc.ctc.edu
d48b00b4 451 *
7cf1c7bd 452 * @param string $haystack The string to be searched
453 * @param string $needle The string to search for
89dcb99d 454 * @param int $offset The position in $haystack where the search should begin.
7cf1c7bd 455 */
ce57cc79 456if (!function_exists('stripos')) { /// Only exists in PHP 5
457 function stripos($haystack, $needle, $offset=0) {
d48b00b4 458
ce57cc79 459 return strpos(strtoupper($haystack), strtoupper($needle), $offset);
460 }
461}
462
7cf1c7bd 463/**
464 * Load a template from file
465 *
466 * Returns a (big) string containing the contents of a template file with all
467 * the variables interpolated. all the variables must be in the $var[] array or
468 * object (whatever you decide to use).
469 *
470 * <b>WARNING: do not use this on big files!!</b>
d48b00b4 471 *
7cf1c7bd 472 * @param string $filename Location on the server's filesystem where template can be found.
473 * @param mixed $var Passed in by reference. An array or object which will be loaded with data from the template file.
474 */
f9903ed0 475function read_template($filename, &$var) {
f9903ed0 476
b0ccd3fb 477 $temp = str_replace("\\", "\\\\", implode(file($filename), ''));
b9b8ab69 478 $temp = str_replace('"', '\"', $temp);
479 eval("\$template = \"$temp\";");
480 return $template;
f9903ed0 481}
482
7cf1c7bd 483/**
484 * Set a variable's value depending on whether or not it already has a value.
485 *
772e78be 486 * If variable is set, set it to the set_value otherwise set it to the
7cf1c7bd 487 * unset_value. used to handle checkboxes when you are expecting them from
488 * a form
d48b00b4 489 *
7cf1c7bd 490 * @param mixed $var Passed in by reference. The variable to check.
491 * @param mixed $set_value The value to set $var to if $var already has a value.
492 * @param mixed $unset_value The value to set $var to if $var does not already have a value.
493 */
f9903ed0 494function checked(&$var, $set_value = 1, $unset_value = 0) {
f9903ed0 495
b9b8ab69 496 if (empty($var)) {
497 $var = $unset_value;
498 } else {
499 $var = $set_value;
500 }
f9903ed0 501}
502
7cf1c7bd 503/**
504 * Prints the word "checked" if a variable is true, otherwise prints nothing,
d48b00b4 505 * used for printing the word "checked" in a checkbox form element.
506 *
7cf1c7bd 507 * @param boolean $var Variable to be checked for true value
508 * @param string $true_value Value to be printed if $var is true
509 * @param string $false_value Value to be printed if $var is false
510 */
b0ccd3fb 511function frmchecked(&$var, $true_value = 'checked', $false_value = '') {
f9903ed0 512
b9b8ab69 513 if ($var) {
514 echo $true_value;
515 } else {
516 echo $false_value;
517 }
f9903ed0 518}
519
7cf1c7bd 520/**
521 * This function will create a HTML link that will work on both
522 * Javascript and non-javascript browsers.
523 * Relies on the Javascript function openpopup in javascript.php
d48b00b4 524 *
7cf1c7bd 525 * $url must be relative to home page eg /mod/survey/stuff.php
526 * @param string $url Web link relative to home page
527 * @param string $name Name to be assigned to the popup window
528 * @param string $linkname Text to be displayed as web link
89dcb99d 529 * @param int $height Height to assign to popup window
530 * @param int $width Height to assign to popup window
7cf1c7bd 531 * @param string $title Text to be displayed as popup page title
532 * @param string $options List of additional options for popup window
533 * @todo Add code examples and list of some options that might be used.
534 * @param boolean $return Should the link to the popup window be returned as a string (true) or printed immediately (false)?
535 * @return string
536 * @uses $CFG
537 */
b0ccd3fb 538function link_to_popup_window ($url, $name='popup', $linkname='click here',
539 $height=400, $width=500, $title='Popup window', $options='none', $return=false) {
f9903ed0 540
ff80e012 541 global $CFG;
542
b0ccd3fb 543 if ($options == 'none') {
544 $options = 'menubar=0,location=0,scrollbars,resizable,width='. $width .',height='. $height;
b48f834c 545 }
86aa7ccf 546 $fullscreen = 0;
f9903ed0 547
c80b7585 548 if (!(strpos($url,$CFG->wwwroot) === false)) { // some log url entries contain _SERVER[HTTP_REFERRER] in which case wwwroot is already there.
7cf1c7bd 549 $url = substr($url, strlen($CFG->wwwroot)+1);
c80b7585 550 }
551
b0ccd3fb 552 $link = '<a target="'. $name .'" title="'. $title .'" href="'. $CFG->wwwroot . $url .'" '.
9de39eae 553 "onclick=\"return openpopup('$url', '$name', '$options', $fullscreen);\">$linkname</a>";
1f2eec7b 554 if ($return) {
555 return $link;
556 } else {
557 echo $link;
558 }
f9903ed0 559}
560
7cf1c7bd 561/**
562 * This function will print a button submit form element
563 * that will work on both Javascript and non-javascript browsers.
564 * Relies on the Javascript function openpopup in javascript.php
d48b00b4 565 *
7cf1c7bd 566 * $url must be relative to home page eg /mod/survey/stuff.php
567 * @param string $url Web link relative to home page
568 * @param string $name Name to be assigned to the popup window
569 * @param string $linkname Text to be displayed as web link
89dcb99d 570 * @param int $height Height to assign to popup window
571 * @param int $width Height to assign to popup window
7cf1c7bd 572 * @param string $title Text to be displayed as popup page title
573 * @param string $options List of additional options for popup window
574 * @todo Add code examples and list of some options that might be used.
575 * @return string
576 * @uses $CFG
577 */
b0ccd3fb 578function button_to_popup_window ($url, $name='popup', $linkname='click here',
579 $height=400, $width=500, $title='Popup window', $options='none') {
52f1b496 580
581 global $CFG;
582
b0ccd3fb 583 if ($options == 'none') {
584 $options = 'menubar=0,location=0,scrollbars,resizable,width='. $width .',height='. $height;
52f1b496 585 }
586 $fullscreen = 0;
587
b0ccd3fb 588 echo '<input type="button" name="popupwindow" title="'. $title .'" value="'. $linkname .' ..." '.
d7d21c38 589 "onclick=\"return openpopup('$url', '$name', '$options', $fullscreen);\" />\n";
52f1b496 590}
591
592
7cf1c7bd 593/**
594 * Prints a simple button to close a window
595 */
08396bb2 596function close_window_button($name='closewindow') {
c1d57101 597
b0ccd3fb 598 echo '<center>' . "\n";
599 echo '<script type="text/javascript">' . "\n";
600 echo '<!--' . "\n";
86aa7ccf 601 echo "document.write('<form>');\n";
d7d21c38 602 echo "document.write('<input type=\"button\" onclick=\"self.close();\" value=\"".get_string("closewindow")."\" />');\n";
c01f71d4 603 echo "document.write('<\/form>');\n";
b0ccd3fb 604 echo '-->' . "\n";
605 echo '</script>' . "\n";
606 echo '<noscript>' . "\n";
08396bb2 607 print_string($name);
b0ccd3fb 608 echo '</noscript>' . "\n";
609 echo '</center>' . "\n";
f9903ed0 610}
611
08396bb2 612/*
613 * Try and close the current window immediately using Javascript
614 */
615function close_window($delay=0) {
616 echo '<script language="JavaScript" type="text/javascript">'."\n";
617 echo '<!--'."\n";
618 if ($delay) {
619 sleep($delay);
620 }
621 echo 'self.close();'."\n";
622 echo '-->'."\n";
623 echo '</script>'."\n";
624 exit;
625}
626
627
d48b00b4 628/**
629 * Given an array of value, creates a popup menu to be part of a form
630 * $options["value"]["label"]
631 *
632 * @param type description
633 * @todo Finish documenting this function
634 */
48e535bc 635function choose_from_menu ($options, $name, $selected='', $nothing='choose', $script='', $nothingvalue='0', $return=false, $disabled=false) {
ab9f24ad 636
b0ccd3fb 637 if ($nothing == 'choose') {
638 $nothing = get_string('choose') .'...';
618b22c5 639 }
640
48e535bc 641 $attributes = ($script) ? 'onchange="'. $script .'"' : '';
642 if ($disabled) {
643 $attributes .= ' disabled="disabled"';
f9903ed0 644 }
9c9f7d77 645
48e535bc 646 $output = '<select name="'. $name .'" '. $attributes .'>' . "\n";
bda8d43a 647 if ($nothing) {
b0ccd3fb 648 $output .= ' <option value="'. $nothingvalue .'"'. "\n";
cec0a0fc 649 if ($nothingvalue === $selected) {
b0ccd3fb 650 $output .= ' selected="selected"';
bda8d43a 651 }
b0ccd3fb 652 $output .= '>'. $nothing .'</option>' . "\n";
873960de 653 }
607809b3 654 if (!empty($options)) {
655 foreach ($options as $value => $label) {
b0ccd3fb 656 $output .= ' <option value="'. $value .'"';
fdae5b13 657 if ($value == $selected) {
b0ccd3fb 658 $output .= ' selected="selected"';
607809b3 659 }
b0ccd3fb 660 if ($label === '') {
661 $output .= '>'. $value .'</option>' . "\n";
a20c1090 662 } else {
b0ccd3fb 663 $output .= '>'. $label .'</option>' . "\n";
607809b3 664 }
f9903ed0 665 }
666 }
b0ccd3fb 667 $output .= '</select>' . "\n";
08056730 668
669 if ($return) {
670 return $output;
671 } else {
672 echo $output;
673 }
ab9f24ad 674}
f9903ed0 675
d48b00b4 676/**
677 * Implements a complete little popup form
678 *
89dcb99d 679 * @uses $CFG
680 * @param string $common The URL up to the point of the variable that changes
681 * @param array $options Alist of value-label pairs for the popup list
682 * @param string $formname Name must be unique on the page
683 * @param string $selected The option that is already selected
684 * @param string $nothing The label for the "no choice" option
685 * @param string $help The name of a help page if help is required
686 * @param string $helptext The name of the label for the help button
687 * @param boolean $return Indicates whether the function should return the text
688 * as a string or echo it directly to the page being rendered
772e78be 689 * @param string $targetwindow The name of the target page to open the linked page in.
89dcb99d 690 * @return string If $return is true then the entire form is returned as a string.
691 * @todo Finish documenting this function<br>
89dcb99d 692 */
693function popup_form($common, $options, $formname, $selected='', $nothing='choose', $help='', $helptext='', $return=false, $targetwindow='self') {
694
772e78be 695 global $CFG;
b0542a1e 696 static $go, $choose; /// Locally cached, in case there's lots on a page
87180677 697
6f9f3b69 698 if (empty($options)) {
699 return '';
700 }
0d0baabf 701
b0542a1e 702 if (!isset($go)) {
703 $go = get_string('go');
037dcbb6 704 }
705
b0ccd3fb 706 if ($nothing == 'choose') {
037dcbb6 707 if (!isset($choose)) {
708 $choose = get_string('choose');
709 }
710 $nothing = $choose.'...';
618b22c5 711 }
712
037dcbb6 713 $startoutput = '<form action="'.$CFG->wwwroot.'/course/jumpto.php"'.
714 ' method="get"'.
715 ' target="'.$CFG->framename.'"'.
716 ' name="'.$formname.'"'.
430c6392 717 ' class="popupform" style="display: inline;">';
037dcbb6 718
719 $output = '<select name="jump" onchange="'.$targetwindow.'.location=document.'.$formname.
16570a27 720 '.jump.options[document.'.$formname.'.jump.selectedIndex].value;">'."\n";
f9903ed0 721
b0ccd3fb 722 if ($nothing != '') {
dfec7b01 723 $output .= " <option value=\"javascript:void(0)\">$nothing</option>\n";
f9903ed0 724 }
725
72b4e283 726 $inoptgroup = false;
f9903ed0 727 foreach ($options as $value => $label) {
772e78be 728
2a003a90 729 if (substr($label,0,2) == '--') { /// we are starting a new optgroup
772e78be 730
2a003a90 731 /// Check to see if we already have a valid open optgroup
732 /// XHTML demands that there be at least 1 option within an optgroup
733 if ($inoptgroup and (count($optgr) > 1) ) {
734 $output .= implode('', $optgr);
72b4e283 735 $output .= ' </optgroup>';
72b4e283 736 }
2a003a90 737
738 unset($optgr);
739 $optgr = array();
740
741 $optgr[] = ' <optgroup label="'. substr($label,2) .'">'; // Plain labels
772e78be 742
2a003a90 743 $inoptgroup = true; /// everything following will be in an optgroup
3326450b 744 continue;
772e78be 745
d897cae4 746 } else {
2a003a90 747 $optstr = ' <option value="' . $common . $value . '"';
772e78be 748
d897cae4 749 if ($value == $selected) {
2a003a90 750 $optstr .= ' selected="selected"';
751 }
772e78be 752
2a003a90 753 if ($label) {
754 $optstr .= '>'. $label .'</option>' . "\n";
755 } else {
756 $optstr .= '>'. $value .'</option>' . "\n";
757 }
772e78be 758
2a003a90 759 if ($inoptgroup) {
760 $optgr[] = $optstr;
761 } else {
762 $output .= $optstr;
d897cae4 763 }
f9903ed0 764 }
772e78be 765
f9903ed0 766 }
2a003a90 767
768 /// catch the final group if not closed
769 if ($inoptgroup and count($optgr) > 1) {
770 $output .= implode('', $optgr);
72b4e283 771 $output .= ' </optgroup>';
772 }
2a003a90 773
b0ccd3fb 774 $output .= '</select>';
037dcbb6 775 $output .= '<noscript id="noscript'.$formname.'" style="display: inline;">';
b0542a1e 776 $output .= '<input type="submit" value="'.$go.'" /></noscript>';
037dcbb6 777 $output .= '<script type="text/javascript">'.
778 "\n<!--\n".
779 'document.getElementById("noscript'.$formname.'").style.display = "none";'.
780 "\n-->\n".'</script>';
b0ccd3fb 781 $output .= '</form>' . "\n";
d897cae4 782
1f2eec7b 783 if ($help) {
784 $button = helpbutton($help, $helptext, 'moodle', true, false, '', true);
785 } else {
786 $button = '';
787 }
788
d897cae4 789 if ($return) {
1f2eec7b 790 return $startoutput.$button.$output;
d897cae4 791 } else {
1f2eec7b 792 echo $startoutput.$button.$output;
d897cae4 793 }
f9903ed0 794}
795
796
d48b00b4 797/**
798 * Prints some red text
799 *
800 * @param string $error The text to be displayed in red
801 */
f9903ed0 802function formerr($error) {
d48b00b4 803
f9903ed0 804 if (!empty($error)) {
b0ccd3fb 805 echo '<font color="#ff0000">'. $error .'</font>';
f9903ed0 806 }
807}
808
d48b00b4 809/**
810 * Validates an email to make sure it makes sense.
811 *
812 * @param string $address The email address to validate.
813 * @return boolean
814 */
89dcb99d 815function validate_email($address) {
d48b00b4 816
f9903ed0 817 return (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'.
818 '@'.
819 '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.
820 '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$',
821 $address));
822}
823
690f358b 824/**
825 * Extracts file argument either from file parameter or PATH_INFO
826 *
827 * @param string $scriptname name of the calling script
828 * @return string file path (only safe characters)
829 */
830function get_file_argument($scriptname) {
831 global $_SERVER;
832
833 $relativepath = FALSE;
834
835 // first try normal parameter (compatible method == no relative links!)
836 $relativepath = optional_param('file', FALSE, PARAM_PATH);
48283ff6 837 if ($relativepath === '/testslasharguments') {
838 echo 'test -1: Incorrect use - try "file.php/testslasharguments" instead'; //indicate fopen/fread works for health center
839 die;
840 }
690f358b 841
842 // then try extract file from PATH_INFO (slasharguments method)
843 if (!$relativepath and !empty($_SERVER['PATH_INFO'])) {
844 $path_info = $_SERVER['PATH_INFO'];
845 // check that PATH_INFO works == must not contain the script name
846 if (!strpos($path_info, $scriptname)) {
847 $relativepath = clean_param(rawurldecode($path_info), PARAM_PATH);
48283ff6 848 if ($relativepath === '/testslasharguments') {
849 echo 'test 1: Slasharguments test passed.'; //indicate ok for health center
690f358b 850 die;
851 }
852 }
853 }
854
855 // now if both fail try the old way
856 // (for compatibility with misconfigured or older buggy php implementations)
857 if (!$relativepath) {
858 $arr = explode($scriptname, me());
859 if (!empty($arr[1])) {
860 $path_info = strip_querystring($arr[1]);
861 $relativepath = clean_param(rawurldecode($path_info), PARAM_PATH);
48283ff6 862 if ($relativepath === '/testslasharguments') {
863 echo 'test 2:Slasharguments test passed (compatibility hack).'; //indicate ok for health center
690f358b 864 die;
865 }
866 }
867 }
868
869 return $relativepath;
870}
871
d48b00b4 872/**
873 * Check for bad characters ?
874 *
875 * @param string $string ?
89dcb99d 876 * @param int $allowdots ?
877 * @todo Finish documenting this function - more detail needed in description as well as details on arguments
d48b00b4 878 */
80035a89 879function detect_munged_arguments($string, $allowdots=1) {
880 if (substr_count($string, '..') > $allowdots) { // Sometimes we allow dots in references
6c8e8b5e 881 return true;
882 }
393c9b4f 883 if (ereg('[\|\`]', $string)) { // check for other bad characters
6c8e8b5e 884 return true;
885 }
f038d9a3 886 if (empty($string) or $string == '/') {
887 return true;
888 }
889
6c8e8b5e 890 return false;
891}
892
d48b00b4 893/**
894 * Searches the current environment variables for some slash arguments
895 *
896 * @param string $file ?
897 * @todo Finish documenting this function
898 */
b0ccd3fb 899function get_slash_arguments($file='file.php') {
f9903ed0 900
eaa50dbc 901 if (!$string = me()) {
f9903ed0 902 return false;
903 }
eaa50dbc 904
6ed3da1d 905 $pathinfo = explode($file, $string);
ab9f24ad 906
bcdfe14e 907 if (!empty($pathinfo[1])) {
9b74055f 908 return addslashes($pathinfo[1]);
6ed3da1d 909 } else {
910 return false;
911 }
912}
913
d48b00b4 914/**
915 * Extracts arguments from "/foo/bar/something"
916 * eg http://mysite.com/script.php/foo/bar/something
917 *
89dcb99d 918 * @param string $string ?
919 * @param int $i ?
920 * @return array|string
d48b00b4 921 * @todo Finish documenting this function
922 */
6ed3da1d 923function parse_slash_arguments($string, $i=0) {
f9903ed0 924
6c8e8b5e 925 if (detect_munged_arguments($string)) {
780db230 926 return false;
927 }
b0ccd3fb 928 $args = explode('/', $string);
f9903ed0 929
930 if ($i) { // return just the required argument
931 return $args[$i];
932
933 } else { // return the whole array
934 array_shift($args); // get rid of the empty first one
935 return $args;
936 }
937}
938
d48b00b4 939/**
89dcb99d 940 * Just returns an array of text formats suitable for a popup menu
d48b00b4 941 *
89dcb99d 942 * @uses FORMAT_MOODLE
943 * @uses FORMAT_HTML
944 * @uses FORMAT_PLAIN
89dcb99d 945 * @uses FORMAT_MARKDOWN
946 * @return array
d48b00b4 947 */
0095d5cd 948function format_text_menu() {
d48b00b4 949
b0ccd3fb 950 return array (FORMAT_MOODLE => get_string('formattext'),
951 FORMAT_HTML => get_string('formathtml'),
952 FORMAT_PLAIN => get_string('formatplain'),
b0ccd3fb 953 FORMAT_MARKDOWN => get_string('formatmarkdown'));
0095d5cd 954}
955
d48b00b4 956/**
957 * Given text in a variety of format codings, this function returns
772e78be 958 * the text as safe HTML.
d48b00b4 959 *
960 * @uses $CFG
89dcb99d 961 * @uses FORMAT_MOODLE
962 * @uses FORMAT_HTML
963 * @uses FORMAT_PLAIN
964 * @uses FORMAT_WIKI
965 * @uses FORMAT_MARKDOWN
966 * @param string $text The text to be formatted. This is raw text originally from user input.
772e78be 967 * @param int $format Identifier of the text format to be used
89dcb99d 968 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
969 * @param array $options ?
970 * @param int $courseid ?
971 * @return string
d48b00b4 972 * @todo Finish documenting this function
973 */
c4ae4fa1 974function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL ) {
0095d5cd 975
ab9f24ad 976 global $CFG, $course;
c4ae4fa1 977
f0aa2fed 978 if (!empty($CFG->cachetext)) {
979 $time = time() - $CFG->cachetext;
980 $md5key = md5($text);
45121ffb 981 if ($cacheitem = get_record_select('cache_text', "md5key = '$md5key' AND timemodified > '$time'")) {
f0aa2fed 982 return $cacheitem->formattedtext;
983 }
984 }
985
c4ae4fa1 986 if (empty($courseid)) {
8eaa4c61 987 if (!empty($course->id)) { // An ugly hack for better compatibility
c4ae4fa1 988 $courseid = $course->id;
989 }
990 }
a751a4e5 991
8eaa4c61 992 $CFG->currenttextiscacheable = true; // Default status - can be changed by any filter
993
0095d5cd 994 switch ($format) {
73f8658c 995 case FORMAT_HTML:
5f350e8f 996 replace_smilies($text);
9d40806d 997 if (!isset($options->noclean)) {
998 $text = clean_text($text, $format);
999 }
ed5bdd65 1000 $text = filter_text($text, $courseid);
73f8658c 1001 break;
1002
6901fa79 1003 case FORMAT_PLAIN:
1004 $text = htmlentities($text);
ab892a4f 1005 $text = rebuildnolinktag($text);
b0ccd3fb 1006 $text = str_replace(' ', '&nbsp; ', $text);
6901fa79 1007 $text = nl2br($text);
6901fa79 1008 break;
1009
d342c763 1010 case FORMAT_WIKI:
6a6495ff 1011 // this format is deprecated
ce50cc70 1012 $text = '<p>NOTICE: Wiki-like formatting has been removed from Moodle. You should not be seeing
1013 this message as all texts should have been converted to Markdown format instead.
1014 Please post a bug report to http://moodle.org/bugs with information about where you
1015 saw this message.</p>'.$text;
d342c763 1016 break;
1017
e7cdcd18 1018 case FORMAT_MARKDOWN:
1019 $text = markdown_to_html($text);
9d40806d 1020 if (!isset($options->noclean)) {
1021 $text = clean_text($text, $format);
1022 }
7c3aa358 1023 replace_smilies($text);
ed5bdd65 1024 $text = filter_text($text, $courseid);
e7cdcd18 1025 break;
1026
73f8658c 1027 default: // FORMAT_MOODLE or anything else
c9dda990 1028 if (!isset($options->smiley)) {
1029 $options->smiley=true;
1030 }
1031 if (!isset($options->para)) {
1a072208 1032 $options->para=true;
c9dda990 1033 }
b7a3d3b2 1034 if (!isset($options->newlines)) {
1035 $options->newlines=true;
1036 }
1037 $text = text_to_html($text, $options->smiley, $options->para, $options->newlines);
9d40806d 1038 if (!isset($options->noclean)) {
1039 $text = clean_text($text, $format);
1040 }
ed5bdd65 1041 $text = filter_text($text, $courseid);
0095d5cd 1042 break;
0095d5cd 1043 }
f0aa2fed 1044
8eaa4c61 1045 if (!empty($CFG->cachetext) and $CFG->currenttextiscacheable) {
f0aa2fed 1046 $newrecord->md5key = $md5key;
1047 $newrecord->formattedtext = addslashes($text);
1048 $newrecord->timemodified = time();
9d40806d 1049 @insert_record('cache_text', $newrecord);
f0aa2fed 1050 }
1051
1052 return $text;
0095d5cd 1053}
1054
7b2c5e72 1055/** Given a simple string, this function returns the string
1056 * processed by enabled filters if $CFG->filterall is enabled
1057 *
3e6691ee 1058 * @param string $string The string to be filtered.
1059 * @param boolean $striplinks To strip any link in the result text.
1060 * @param int $courseid Current course as filters can, potentially, use it
7b2c5e72 1061 * @return string
1062 */
3e6691ee 1063function format_string ($string, $striplinks = false, $courseid=NULL ) {
7b2c5e72 1064
1065 global $CFG, $course;
1066
2a3affe9 1067 //We'll use a in-memory cache here to speed up repeated strings
1068 static $strcache;
1069
1070 //Calculate md5
1071 $md5 = md5($string.$striplinks);
1072
1073 //Fetch from cache if possible
1074 if(isset($strcache[$md5])) {
1075 return $strcache[$md5];
1076 }
1077
7b2c5e72 1078 if (empty($courseid)) {
1079 if (!empty($course->id)) { // An ugly hack for better compatibility
1080 $courseid = $course->id; // (copied from format_text)
1081 }
1082 }
1083
45daee10 1084 if (!empty($CFG->filterall)) {
7b2c5e72 1085 $string = filter_text($string, $courseid);
1086 }
1087
3e6691ee 1088 if ($striplinks) { //strip links in string
1089 $string = preg_replace('/(<a[^>]+?>)(.+?)(<\/a>)/is','$2',$string);
1090 }
1091
2a3affe9 1092 //Store to cache
1093 $strcache[$md5] = $string;
1094
7b2c5e72 1095 return $string;
1096}
1097
d48b00b4 1098/**
1099 * Given text in a variety of format codings, this function returns
1100 * the text as plain text suitable for plain email.
d48b00b4 1101 *
89dcb99d 1102 * @uses FORMAT_MOODLE
1103 * @uses FORMAT_HTML
1104 * @uses FORMAT_PLAIN
1105 * @uses FORMAT_WIKI
1106 * @uses FORMAT_MARKDOWN
1107 * @param string $text The text to be formatted. This is raw text originally from user input.
772e78be 1108 * @param int $format Identifier of the text format to be used
89dcb99d 1109 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
1110 * @return string
d48b00b4 1111 */
d342c763 1112function format_text_email($text, $format) {
d342c763 1113
1114 switch ($format) {
1115
1116 case FORMAT_PLAIN:
1117 return $text;
1118 break;
1119
1120 case FORMAT_WIKI:
1121 $text = wiki_to_html($text);
5b472756 1122 /// This expression turns links into something nice in a text format. (Russell Jungwirth)
1123 /// From: http://php.net/manual/en/function.eregi-replace.php and simplified
76add072 1124 $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [ \\2 ]', $text);
7c55a29b 1125 return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES)));
d342c763 1126 break;
1127
6ff45b59 1128 case FORMAT_HTML:
1129 return html_to_text($text);
1130 break;
1131
e7cdcd18 1132 case FORMAT_MOODLE:
1133 case FORMAT_MARKDOWN:
67ccec43 1134 default:
76add072 1135 $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [ \\2 ]', $text);
7c55a29b 1136 return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES)));
d342c763 1137 break;
1138 }
1139}
0095d5cd 1140
d48b00b4 1141/**
1142 * Given some text in HTML format, this function will pass it
1143 * through any filters that have been defined in $CFG->textfilterx
1144 * The variable defines a filepath to a file containing the
1145 * filter function. The file must contain a variable called
1146 * $textfilter_function which contains the name of the function
1147 * with $courseid and $text parameters
1148 *
89dcb99d 1149 * @param string $text The text to be passed through format filters
1150 * @param int $courseid ?
d48b00b4 1151 * @return string
1152 * @todo Finish documenting this function
1153 */
c4ae4fa1 1154function filter_text($text, $courseid=NULL) {
e67b9e31 1155
c4ae4fa1 1156 global $CFG;
e67b9e31 1157
01af49bb 1158 require_once($CFG->libdir.'/filterlib.php');
1159
d523d2ea 1160 if (!empty($CFG->textfilters)) {
1161 $textfilters = explode(',', $CFG->textfilters);
1162 foreach ($textfilters as $textfilter) {
b0ccd3fb 1163 if (is_readable($CFG->dirroot .'/'. $textfilter .'/filter.php')) {
1164 include_once($CFG->dirroot .'/'. $textfilter .'/filter.php');
df1c4611 1165 $functionname = basename($textfilter).'_filter';
1166 if (function_exists($functionname)) {
1167 $text = $functionname($courseid, $text);
1168 }
d523d2ea 1169 }
e67b9e31 1170 }
1171 }
d523d2ea 1172
c7444a36 1173 /// <nolink> tags removed for XHTML compatibility
1174 $text = str_replace('<nolink>', '', $text);
1175 $text = str_replace('</nolink>', '', $text);
1176
e67b9e31 1177 return $text;
1178}
1179
d48b00b4 1180/**
1181 * Given raw text (eg typed in by a user), this function cleans it up
1182 * and removes any nasty tags that could mess up Moodle pages.
1183 *
89dcb99d 1184 * @uses FORMAT_MOODLE
1185 * @uses FORMAT_PLAIN
1186 * @uses ALLOWED_TAGS
1187 * @param string $text The text to be cleaned
772e78be 1188 * @param int $format Identifier of the text format to be used
89dcb99d 1189 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
1190 * @return string The cleaned up text
d48b00b4 1191 */
3da47524 1192function clean_text($text, $format=FORMAT_MOODLE) {
b7a3cf49 1193
fc120758 1194 global $ALLOWED_TAGS;
3fe3851d 1195
ab9f24ad 1196 switch ($format) {
e7cdcd18 1197 case FORMAT_PLAIN:
1198 return $text;
1199
1200 default:
1201
09cbeb40 1202 /// Remove tags that are not allowed
3fe3851d 1203 $text = strip_tags($text, $ALLOWED_TAGS);
e7cdcd18 1204
7789ffbf 1205 /// Clean up embedded scripts and , using kses
1206 $text = cleanAttributes($text);
1207
5b472756 1208 /// Remove script events
ab9f24ad 1209 $text = eregi_replace("([^a-z])language([[:space:]]*)=", "\\1Xlanguage=", $text);
1210 $text = eregi_replace("([^a-z])on([a-z]+)([[:space:]]*)=", "\\1Xon\\2=", $text);
6901fa79 1211
6901fa79 1212 return $text;
0095d5cd 1213 }
b7a3cf49 1214}
f9903ed0 1215
d48b00b4 1216/**
89dcb99d 1217 * This function takes a string and examines it for HTML tags.
d48b00b4 1218 * If tags are detected it passes the string to a helper function {@link cleanAttributes2()}
1219 * which checks for attributes and filters them for malicious content
1220 * 17/08/2004 :: Eamon DOT Costello AT dcu DOT ie
1221 *
1222 * @param string $str The string to be examined for html tags
1223 * @return string
1224 */
3bd7ffec 1225function cleanAttributes($str){
3bd7ffec 1226 $result = preg_replace(
1227 '%(<[^>]*(>|$)|>)%me', #search for html tags
67ccec43 1228 "cleanAttributes2('\\1')",
3bd7ffec 1229 $str
67ccec43 1230 );
3bd7ffec 1231 return $result;
67ccec43 1232}
1233
d48b00b4 1234/**
1235 * This function takes a string with an html tag and strips out any unallowed
1236 * protocols e.g. javascript:
1237 * It calls ancillary functions in kses which are prefixed by kses
1238* 17/08/2004 :: Eamon DOT Costello AT dcu DOT ie
1239 *
1240 * @param string $htmlTag An html tag to be examined
1241 * @return string
1242 */
3bd7ffec 1243function cleanAttributes2($htmlTag){
3bd7ffec 1244
037dcbb6 1245 global $CFG, $ALLOWED_PROTOCOLS;
b0ccd3fb 1246 require_once($CFG->libdir .'/kses.php');
3bd7ffec 1247
1248 $htmlTag = kses_stripslashes($htmlTag);
037dcbb6 1249 if (substr($htmlTag, 0, 1) != '<') {
3bd7ffec 1250 return '&gt;'; //a single character ">" detected
1251 }
037dcbb6 1252 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $htmlTag, $matches)) {
67ccec43 1253 return ''; // It's seriously malformed
1254 }
3bd7ffec 1255 $slash = trim($matches[1]); //trailing xhtml slash
67ccec43 1256 $elem = $matches[2]; //the element name
3bd7ffec 1257 $attrlist = $matches[3]; // the list of attributes as a string
1258
037dcbb6 1259 $attrArray = kses_hair($attrlist, $ALLOWED_PROTOCOLS);
3bd7ffec 1260
67ccec43 1261 $attStr = '';
037dcbb6 1262 foreach ($attrArray as $arreach) {
ec51c7fb 1263 $attStr .= ' '.strtolower($arreach['name']).'="'.$arreach['value'].'" ';
3bd7ffec 1264 }
713126cd 1265
1266 // Remove last space from attribute list
1267 $attStr = rtrim($attStr);
1268
3bd7ffec 1269 $xhtml_slash = '';
037dcbb6 1270 if (preg_match('%/\s*$%', $attrlist)) {
67ccec43 1271 $xhtml_slash = ' /';
3bd7ffec 1272 }
b0ccd3fb 1273 return '<'. $slash . $elem . $attStr . $xhtml_slash .'>';
3bd7ffec 1274}
1275
d48b00b4 1276/**
1277 * Replaces all known smileys in the text with image equivalents
1278 *
1279 * @uses $CFG
1280 * @param string $text Passed by reference. The string to search for smily strings.
1281 * @return string
1282 */
5f350e8f 1283function replace_smilies(&$text) {
772e78be 1284///
2ea9027b 1285 global $CFG;
c1d57101 1286
5b472756 1287/// this builds the mapping array only once
617778f2 1288 static $runonce = false;
69081931 1289 static $e = array();
1290 static $img = array();
617778f2 1291 static $emoticons = array(
fbfc2675 1292 ':-)' => 'smiley',
1293 ':)' => 'smiley',
1294 ':-D' => 'biggrin',
1295 ';-)' => 'wink',
1296 ':-/' => 'mixed',
1297 'V-.' => 'thoughtful',
1298 ':-P' => 'tongueout',
1299 'B-)' => 'cool',
1300 '^-)' => 'approve',
1301 '8-)' => 'wideeyes',
1302 ':o)' => 'clown',
1303 ':-(' => 'sad',
1304 ':(' => 'sad',
1305 '8-.' => 'shy',
1306 ':-I' => 'blush',
1307 ':-X' => 'kiss',
1308 '8-o' => 'surprise',
1309 'P-|' => 'blackeye',
1310 '8-[' => 'angry',
1311 'xx-P' => 'dead',
1312 '|-.' => 'sleepy',
1313 '}-]' => 'evil',
2ea9027b 1314 );
1315
fbfc2675 1316 if ($runonce == false) { /// After the first time this is not run again
617778f2 1317 foreach ($emoticons as $emoticon => $image){
fbfc2675 1318 $alttext = get_string($image, 'pix');
1319
69081931 1320 $e[] = $emoticon;
d48b00b4 1321 $img[] = '<img alt="'. $alttext .'" width="15" height="15" src="'. $CFG->pixpath .'/s/'. $image .'.gif" />';
617778f2 1322 }
1323 $runonce = true;
c0f728ba 1324 }
b7a3cf49 1325
8dcd43f3 1326 // Exclude from transformations all the code inside <script> tags
1327 // Needed to solve Bug 1185. Thanks to jouse 2001 detecting it. :-)
1328 // Based on code from glossary fiter by Williams Castillo.
1329 // - Eloy
1330
1331 // Detect all the <script> zones to take out
1332 $excludes = array();
1333 preg_match_all('/<script language(.+?)<\/script>/is',$text,$list_of_excludes);
1334
1335 // Take out all the <script> zones from text
1336 foreach (array_unique($list_of_excludes[0]) as $key=>$value) {
1337 $excludes['<+'.$key.'+>'] = $value;
1338 }
1339 if ($excludes) {
1340 $text = str_replace($excludes,array_keys($excludes),$text);
1341 }
1342
fbfc2675 1343/// this is the meat of the code - this is run every time
5f350e8f 1344 $text = str_replace($e, $img, $text);
8dcd43f3 1345
1346 // Recover all the <script> zones to text
1347 if ($excludes) {
1348 $text = str_replace(array_keys($excludes),$excludes,$text);
1349 }
1a072208 1350}
0095d5cd 1351
89dcb99d 1352/**
1353 * Given plain text, makes it into HTML as nicely as possible.
1354 * May contain HTML tags already
1355 *
1356 * @uses $CFG
1357 * @param string $text The string to convert.
1358 * @param boolean $smiley Convert any smiley characters to smiley images?
1359 * @param boolean $para If true then the returned string will be wrapped in paragraph tags
1360 * @param boolean $newlines If true then lines newline breaks will be converted to HTML newline breaks.
1361 * @return string
1362 */
1363
b7a3d3b2 1364function text_to_html($text, $smiley=true, $para=true, $newlines=true) {
772e78be 1365///
f9903ed0 1366
27326a3e 1367 global $CFG;
1368
c1d57101 1369/// Remove any whitespace that may be between HTML tags
7b3be1b1 1370 $text = eregi_replace(">([[:space:]]+)<", "><", $text);
1371
c1d57101 1372/// Remove any returns that precede or follow HTML tags
0eae8049 1373 $text = eregi_replace("([\n\r])<", " <", $text);
1374 $text = eregi_replace(">([\n\r])", "> ", $text);
7b3be1b1 1375
5f350e8f 1376 convert_urls_into_links($text);
f9903ed0 1377
c1d57101 1378/// Make returns into HTML newlines.
b7a3d3b2 1379 if ($newlines) {
1380 $text = nl2br($text);
1381 }
f9903ed0 1382
c1d57101 1383/// Turn smileys into images.
d69cb7f4 1384 if ($smiley) {
5f350e8f 1385 replace_smilies($text);
d69cb7f4 1386 }
f9903ed0 1387
c1d57101 1388/// Wrap the whole thing in a paragraph tag if required
909f539d 1389 if ($para) {
b0ccd3fb 1390 return '<p>'.$text.'</p>';
909f539d 1391 } else {
1392 return $text;
1393 }
f9903ed0 1394}
1395
d48b00b4 1396/**
1397 * Given Markdown formatted text, make it into XHTML using external function
1398 *
89dcb99d 1399 * @uses $CFG
1400 * @param string $text The markdown formatted text to be converted.
1401 * @return string Converted text
d48b00b4 1402 */
e7cdcd18 1403function markdown_to_html($text) {
e7cdcd18 1404 global $CFG;
1405
b0ccd3fb 1406 require_once($CFG->libdir .'/markdown.php');
e7cdcd18 1407
1408 return Markdown($text);
1409}
1410
d48b00b4 1411/**
89dcb99d 1412 * Given HTML text, make it into plain text using external function
d48b00b4 1413 *
1414 * @uses $CFG
1415 * @param string $html The text to be converted.
1416 * @return string
1417 */
6ff45b59 1418function html_to_text($html) {
89dcb99d 1419
428aaa29 1420 global $CFG;
6ff45b59 1421
b0ccd3fb 1422 require_once($CFG->libdir .'/html2text.php');
6ff45b59 1423
1424 return html2text($html);
1425}
1426
d48b00b4 1427/**
1428 * Given some text this function converts any URLs it finds into HTML links
1429 *
1430 * @param string $text Passed in by reference. The string to be searched for urls.
1431 */
5f350e8f 1432function convert_urls_into_links(&$text) {
5f350e8f 1433/// Make lone URLs into links. eg http://moodle.com/
3405b212 1434 $text = eregi_replace("([[:space:]]|^|\(|\[)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])",
bc01a2b8 1435 "\\1<a href=\"\\2://\\3\\4\" target=\"_blank\">\\2://\\3\\4</a>", $text);
5f350e8f 1436
1437/// eg www.moodle.com
ab9f24ad 1438 $text = eregi_replace("([[:space:]]|^|\(|\[)www\.([^[:space:]]*)([[:alnum:]#?/&=])",
bc01a2b8 1439 "\\1<a href=\"http://www.\\2\\3\" target=\"_blank\">www.\\2\\3</a>", $text);
5f350e8f 1440}
1441
d48b00b4 1442/**
1443 * This function will highlight search words in a given string
1444 * It cares about HTML and will not ruin links. It's best to use
1445 * this function after performing any conversions to HTML.
1446 * Function found here: http://forums.devshed.com/t67822/scdaa2d1c3d4bacb4671d075ad41f0854.html
1447 *
89dcb99d 1448 * @param string $needle The string to search for
1449 * @param string $haystack The string to search for $needle in
1450 * @param int $case ?
1451 * @return string
d48b00b4 1452 * @todo Finish documenting this function
1453 */
ab9f24ad 1454function highlight($needle, $haystack, $case=0,
b0ccd3fb 1455 $left_string='<span class="highlight">', $right_string='</span>') {
69d51d3a 1456 if (empty($needle)) {
1457 return $haystack;
1458 }
1459
9ccdcd97 1460 $list_of_words = eregi_replace("[^-a-zA-Z0-9&.']", " ", $needle);
b0ccd3fb 1461 $list_array = explode(' ', $list_of_words);
88438a58 1462 for ($i=0; $i<sizeof($list_array); $i++) {
1463 if (strlen($list_array[$i]) == 1) {
b0ccd3fb 1464 $list_array[$i] = '';
88438a58 1465 }
1466 }
b0ccd3fb 1467 $list_of_words = implode(' ', $list_array);
88438a58 1468 $list_of_words_cp = $list_of_words;
1469 $final = array();
1470 preg_match_all('/<(.+?)>/is',$haystack,$list_of_words);
1471
1472 foreach (array_unique($list_of_words[0]) as $key=>$value) {
1473 $final['<|'.$key.'|>'] = $value;
1474 }
1475
1476 $haystack = str_replace($final,array_keys($final),$haystack);
b0ccd3fb 1477 $list_of_words_cp = eregi_replace(' +', '|', $list_of_words_cp);
88438a58 1478
b0ccd3fb 1479 if ($list_of_words_cp{0}=='|') {
1480 $list_of_words_cp{0} = '';
88438a58 1481 }
b0ccd3fb 1482 if ($list_of_words_cp{strlen($list_of_words_cp)-1}=='|') {
1483 $list_of_words_cp{strlen($list_of_words_cp)-1}='';
88438a58 1484 }
88438a58 1485
9ccdcd97 1486 $list_of_words_cp = trim($list_of_words_cp);
1487
1488 if ($list_of_words_cp) {
1489
1490 $list_of_words_cp = "(". $list_of_words_cp .")";
1491
1492 if (!$case){
1493 $haystack = eregi_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
1494 } else {
1495 $haystack = ereg_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
1496 }
88438a58 1497 }
1498 $haystack = str_replace(array_keys($final),$final,$haystack);
1499
f60e7cfe 1500 return $haystack;
88438a58 1501}
1502
d48b00b4 1503/**
1504 * This function will highlight instances of $needle in $haystack
1505 * It's faster that the above function and doesn't care about
1506 * HTML or anything.
1507 *
1508 * @param string $needle The string to search for
1509 * @param string $haystack The string to search for $needle in
1510 * @return string
1511 */
88438a58 1512function highlightfast($needle, $haystack) {
5af78ed2 1513
1514 $parts = explode(strtolower($needle), strtolower($haystack));
1515
1516 $pos = 0;
1517
1518 foreach ($parts as $key => $part) {
1519 $parts[$key] = substr($haystack, $pos, strlen($part));
1520 $pos += strlen($part);
1521
b0ccd3fb 1522 $parts[$key] .= '<span class="highlight">'.substr($haystack, $pos, strlen($needle)).'</span>';
5af78ed2 1523 $pos += strlen($needle);
ab9f24ad 1524 }
5af78ed2 1525
1526 return (join('', $parts));
1527}
1528
f9903ed0 1529
9fa49e22 1530/// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
1531
d48b00b4 1532/**
1533 * Print a standard header
1534 *
89dcb99d 1535 * @uses $USER
1536 * @uses $CFG
89dcb99d 1537 * @uses $SESSION
1538 * @param string $title Appears at the top of the window
1539 * @param string $heading Appears at the top of the page
1540 * @param string $navigation Premade navigation string (for use as breadcrumbs links)
1541 * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
1542 * @param string $meta Meta tags to be added to the header
1543 * @param boolean $cache Should this page be cacheable?
1544 * @param string $button HTML code for a button (usually for module editing)
1545 * @param string $menu HTML code for a popup menu
1546 * @param boolean $usexml use XML for this page
1547 * @param string $bodytags This text will be included verbatim in the <body> tag (useful for onload() etc)
d48b00b4 1548 */
b0ccd3fb 1549function print_header ($title='', $heading='', $navigation='', $focus='', $meta='',
1550 $cache=true, $button='&nbsp;', $menu='', $usexml=false, $bodytags='') {
63f3cbbd 1551
c44d5d42 1552 global $USER, $CFG, $THEME, $SESSION, $ME, $SITE;
9fa49e22 1553
e89fb61e 1554/// This is an ugly hack to be replaced later by a proper global $COURSE
1555 global $course;
b3153e4b 1556 if (!empty($course->lang)) {
1557 $CFG->courselang = $course->lang;
1558 }
32e2b302 1559 if (!empty($course->theme)) {
1560 if (!empty($CFG->allowcoursethemes)) {
1561 $CFG->coursetheme = $course->theme;
1562 theme_setup();
1563 }
1564 }
b3153e4b 1565
0d741155 1566
c3f55692 1567/// Add the required stylesheets
d74d4f20 1568 $stylesheetshtml = '';
1569 foreach ($CFG->stylesheets as $stylesheet) {
1570 $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
c3f55692 1571 }
d74d4f20 1572 $meta = $stylesheetshtml.$meta;
e89fb61e 1573
9fa49e22 1574
b0ccd3fb 1575 if ($navigation == 'home') {
9fa49e22 1576 $home = true;
b0ccd3fb 1577 $navigation = '';
9d378732 1578 } else {
1579 $home = false;
9fa49e22 1580 }
1581
0d741155 1582/// This is another ugly hack to make navigation elements available to print_footer later
1583 $THEME->title = $title;
1584 $THEME->heading = $heading;
1585 $THEME->navigation = $navigation;
1586 $THEME->button = $button;
1587 $THEME->menu = $menu;
2507b2f5 1588 $navmenulist = isset($THEME->navmenulist) ? $THEME->navmenulist : '';
0d741155 1589
b0ccd3fb 1590 if ($button == '') {
1591 $button = '&nbsp;';
9fa49e22 1592 }
1593
1594 if (!$menu and $navigation) {
8a33e371 1595 if (empty($CFG->loginhttps)) {
1596 $wwwroot = $CFG->wwwroot;
1597 } else {
1598 $wwwroot = str_replace('http','https',$CFG->wwwroot);
1599 }
0e18f827 1600 if (isset($course->id)) {
009f39be 1601 $menu = user_login_string($course);
9fa49e22 1602 } else {
c44d5d42 1603 $menu = user_login_string($SITE);
9fa49e22 1604 }
1605 }
67ccec43 1606
b4bac9b6 1607 if (isset($SESSION->justloggedin)) {
1608 unset($SESSION->justloggedin);
1609 if (!empty($CFG->displayloginfailures)) {
1610 if (!empty($USER->username) and !isguest()) {
1611 if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) {
1612 $menu .= '&nbsp;<font size="1">';
1613 if (empty($count->accounts)) {
1614 $menu .= get_string('failedloginattempts', '', $count);
1615 } else {
1616 $menu .= get_string('failedloginattemptsall', '', $count);
1617 }
1618 if (isadmin()) {
1619 $menu .= ' (<a href="'.$CFG->wwwroot.'/course/log.php'.
839f2456 1620 '?chooselog=1&amp;id=1&amp;modid=site_errors">'.get_string('logs').'</a>)';
b4bac9b6 1621 }
1622 $menu .= '</font>';
1623 }
1624 }
1625 }
1626 }
9fa49e22 1627
47037513 1628
cec0a0fc 1629 if (!empty($CFG->unicode)) {
b0ccd3fb 1630 $encoding = 'utf-8';
a2fa19d8 1631 } else if (!empty($CFG->courselang)) {
b0ccd3fb 1632 $encoding = get_string('thischarset');
a2fa19d8 1633 moodle_setlocale();
1634 } else {
1635 if (!empty($SESSION->encoding)) {
1636 $encoding = $SESSION->encoding;
1637 } else {
b0ccd3fb 1638 $SESSION->encoding = $encoding = get_string('thischarset');
a2fa19d8 1639 }
9fa49e22 1640 }
b0ccd3fb 1641 $meta = '<meta http-equiv="content-type" content="text/html; charset='. $encoding .'" />'. "\n". $meta ."\n";
03fe48e7 1642 if (!$usexml) {
1643 @header('Content-type: text/html; charset='.$encoding);
1644 }
9fa49e22 1645
b0ccd3fb 1646 if ( get_string('thisdirection') == 'rtl' ) {
1647 $direction = ' dir="rtl"';
9fa49e22 1648 } else {
b0ccd3fb 1649 $direction = ' dir="ltr"';
9fa49e22 1650 }
ab9f24ad 1651
5debee2d 1652 if ($cache) { // Allow caching on "back" (but not on normal clicks)
1653 @header('Cache-Control: private, pre-check=0, post-check=0, max-age=0');
1654 @header('Pragma: no-cache');
772e78be 1655 @header('Expires: ');
5debee2d 1656 } else { // Do everything we can to always prevent clients and proxies caching
03fe48e7 1657 @header('Cache-Control: no-store, no-cache, must-revalidate');
1658 @header('Cache-Control: post-check=0, pre-check=0', false);
1659 @header('Pragma: no-cache');
5debee2d 1660 @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
1661 @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
03fe48e7 1662
5debee2d 1663 $meta .= "\n<meta http-equiv=\"pragma\" content=\"no-cache\" />";
1664 $meta .= "\n<meta http-equiv=\"expires\" content=\"0\" />";
66a51452 1665 }
5debee2d 1666 @header('Accept-Ranges: none');
66a51452 1667
1668 if ($usexml) { // Added by Gustav Delius / Mad Alex for MathML output
8f0cd6ef 1669 // Modified by Julian Sedding
66a51452 1670 $currentlanguage = current_language();
8f0cd6ef 1671 $mathplayer = preg_match("/MathPlayer/i", $_SERVER['HTTP_USER_AGENT']);
1672 if(!$mathplayer) {
1673 header('Content-Type: application/xhtml+xml');
1674 }
b0ccd3fb 1675 echo '<?xml version="1.0" ?>'."\n";
66a51452 1676 if (!empty($CFG->xml_stylesheets)) {
b0ccd3fb 1677 $stylesheets = explode(';', $CFG->xml_stylesheets);
66a51452 1678 foreach ($stylesheets as $stylesheet) {
b0ccd3fb 1679 echo '<?xml-stylesheet type="text/xsl" href="'. $CFG->wwwroot .'/'. $stylesheet .'" ?>' . "\n";
66a51452 1680 }
1681 }
b0ccd3fb 1682 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1';
e4576482 1683 if (!empty($CFG->xml_doctype_extra)) {
b0ccd3fb 1684 echo ' plus '. $CFG->xml_doctype_extra;
e4576482 1685 }
b0ccd3fb 1686 echo '//' . strtoupper($currentlanguage) . '" "'. $CFG->xml_dtd .'">'."\n";
8f0cd6ef 1687 $direction = " xmlns=\"http://www.w3.org/1999/xhtml\"
1688 xmlns:math=\"http://www.w3.org/1998/Math/MathML\"
1689 xml:lang=\"en\"
1690 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1691 $direction";
1692 if($mathplayer) {
1693 $meta .= '<object id="mathplayer" classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">' . "\n";
b0ccd3fb 1694 $meta .= '<!--comment required to prevent this becoming an empty tag-->'."\n";
1695 $meta .= '</object>'."\n";
8f0cd6ef 1696 $meta .= '<?import namespace="math" implementation="#mathplayer" ?>' . "\n";
1697 }
9fa49e22 1698 }
1699
7bb6d80f 1700 // Clean up the title
1701
2eea2cce 1702 $title = str_replace('"', '&quot;', $title);
1d9fc417 1703 $title = strip_tags($title);
2eea2cce 1704
7bb6d80f 1705 // Create class and id for this page
1706
68d5f00a 1707 page_id_and_class($pageid, $pageclass);
7bb6d80f 1708
d6c66e12 1709 if (isset($course->id)) {
1710 $pageclass .= ' course-'.$course->id;
c09e00ba 1711 } else {
1712 $pageclass .= ' course-'.SITEID;
d6c66e12 1713 }
1714
e299f862 1715 if (!empty($USER->editing)) {
1716 $pageclass .= ' editing';
1717 }
1718
7bb6d80f 1719 $bodytags .= ' class="'.$pageclass.'" id="'.$pageid.'"';
772e78be 1720
2d40fc05 1721 include ($CFG->themedir. $CFG->theme .'/header.html');
e608dddd 1722
cdf39255 1723 if (!empty($CFG->messaging)) {
1724 echo message_popup_window();
1725 }
9fa49e22 1726}
1727
d48b00b4 1728/**
1729 * This version of print_header is simpler because the course name does not have to be
1730 * provided explicitly in the strings. It can be used on the site page as in courses
1731 * Eventually all print_header could be replaced by print_header_simple
1732 *
89dcb99d 1733 * @param string $title Appears at the top of the window
1734 * @param string $heading Appears at the top of the page
1735 * @param string $navigation Premade navigation string (for use as breadcrumbs links)
1736 * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
1737 * @param string $meta Meta tags to be added to the header
1738 * @param boolean $cache Should this page be cacheable?
1739 * @param string $button HTML code for a button (usually for module editing)
1740 * @param string $menu HTML code for a popup menu
1741 * @param boolean $usexml use XML for this page
1742 * @param string $bodytags This text will be included verbatim in the <body> tag (useful for onload() etc)
d48b00b4 1743 */
b0ccd3fb 1744function print_header_simple($title='', $heading='', $navigation='', $focus='', $meta='',
1745 $cache=true, $button='&nbsp;', $menu='', $usexml=false, $bodytags='') {
90fcc576 1746
1747 global $course; // The same hack is used in print_header
1748
1749 $shortname ='';
1750 if ($course->category) {
b0ccd3fb 1751 $shortname = '<a href="../../course/view.php?id='. $course->id .'">'. $course->shortname .'</a> ->';
90fcc576 1752 }
1753
b0ccd3fb 1754 print_header($course->shortname .': '. $title, $course->fullname .' '. $heading, $shortname .' '. $navigation, $focus, $meta,
90fcc576 1755 $cache, $button, $menu, $usexml, $bodytags);
1756}
629b5885 1757
1758
d48b00b4 1759/**
1760 * Can provide a course object to make the footer contain a link to
1761 * to the course home page, otherwise the link will go to the site home
1762 *
1763 * @uses $CFG
1764 * @uses $USER
89dcb99d 1765 * @param course $course {@link $COURSE} object containing course information
1766 * @param ? $usercourse ?
d48b00b4 1767 * @todo Finish documenting this function
1768 */
b3a2b9dd 1769function print_footer($course=NULL, $usercourse=NULL) {
0d741155 1770 global $USER, $CFG, $THEME;
9fa49e22 1771
9fa49e22 1772/// Course links
1773 if ($course) {
b3a2b9dd 1774 if ($course == 'none') { // Don't print any links etc
1775 $homelink = '';
1776 $loggedinas = '';
0d741155 1777 $home = false;
b3a2b9dd 1778 } else if ($course == 'home') { // special case for site home page - please do not remove
1779 $course = get_site();
a77ac3dc 1780 $homelink = '<div class="sitelink">'.
1781 '<a title="moodle '. $CFG->release .' ('. $CFG->version .')" href="http://moodle.org/" target="_blank">'.
1782 '<br /><img width="100" height="30" src="pix/moodlelogo.gif" border="0" alt="moodlelogo" /></a></div>';
0d741155 1783 $home = true;
9fa49e22 1784 } else {
a77ac3dc 1785 $homelink = '<div class="homelink"><a target="'.$CFG->framename.'" href="'.$CFG->wwwroot.
1786 '/course/view.php?id='.$course->id.'">'.$course->shortname.'</a></div>';
0d741155 1787 $home = false;
9fa49e22 1788 }
1789 } else {
b3a2b9dd 1790 $course = get_site(); // Set course as site course by default
a77ac3dc 1791 $homelink = '<div class="homelink"><a target="'.$CFG->framename.'" href="'.$CFG->wwwroot.'/">'.get_string('home').'</a></div>';
0d741155 1792 $home = false;
9fa49e22 1793 }
1794
0d741155 1795/// Set up some other navigation links (passed from print_header by ugly hack)
2507b2f5 1796 $menu = isset($THEME->menu) ? str_replace('navmenu', 'navmenufooter', $THEME->menu) : '';
1797 $title = isset($THEME->title) ? $THEME->title : '';
1798 $button = isset($THEME->button) ? $THEME->button : '';
1799 $heading = isset($THEME->heading) ? $THEME->heading : '';
1800 $navigation = isset($THEME->navigation) ? $THEME->navigation : '';
1801 $navmenulist = isset($THEME->navmenulist) ? $THEME->navmenulist : '';
0d741155 1802
f940ee41 1803
b3a2b9dd 1804/// Set the user link if necessary
1805 if (!$usercourse and is_object($course)) {
1f2eec7b 1806 $usercourse = $course;
1807 }
1808
b3a2b9dd 1809 if (!isset($loggedinas)) {
1810 $loggedinas = user_login_string($usercourse, $USER);
1811 }
1812
0d741155 1813 if ($loggedinas == $menu) {
9e0d1983 1814 $menu = '';
0d741155 1815 }
1816
b8cea9b2 1817/// Provide some performance info if required
c2fd9e95 1818 $performanceinfo = '';
853df85e 1819 if (defined('MDL_PERF') || $CFG->debug > 7) {
c2fd9e95 1820 $perf = get_performance_info();
853df85e 1821 if (defined('MDL_PERFTOLOG')) {
1822 error_log("PERF: " . $perf['txt']);
1823 }
1824 if (defined('MDL_PERFTOFOOT') || $CFG->debug > 7) {
c2fd9e95 1825 $performanceinfo = $perf['html'];
1826 }
1827 }
b8cea9b2 1828
0d741155 1829
b3a2b9dd 1830/// Include the actual footer file
a282d0ff 1831
2d40fc05 1832 include ($CFG->themedir.$CFG->theme.'/footer.html');
a9a9bdba 1833
a282d0ff 1834}
1835
c3f55692 1836/**
1837 * Returns the name of the current theme
1838 *
1839 * @uses $CFG
1840 * @param $USER
1841 * @param $SESSION
1842 * @return string
1843 */
1844function current_theme() {
32e2b302 1845 global $CFG, $USER, $SESSION, $course;
c3f55692 1846
1847/// Logic for this will probably change to accomodate local theme rules.
1848
32e2b302 1849 if (!empty($CFG->coursetheme) and !empty($CFG->allowcoursethemes)) { // Course theme can override all others
c3f55692 1850 return $CFG->coursetheme;
1851
1852 } else if (!empty($SESSION->theme)) { // Session theme can override other settings
1853 return $SESSION->theme;
1854
32e2b302 1855 } else if (!empty($USER->theme) and !empty($CFG->allowuserthemes)) { // User theme can override site theme
c3f55692 1856 return $USER->theme;
1857
1858 } else {
1859 return $CFG->theme;
1860 }
1861}
1862
1863
d48b00b4 1864/**
1865 * This function is called by stylesheets to set up the header
1866 * approriately as well as the current path
1867 *
1868 * @uses $CFG
89dcb99d 1869 * @param int $lastmodified ?
1870 * @param int $lifetime ?
1871 * @param string $thename ?
d48b00b4 1872 */
9c4e6e21 1873function style_sheet_setup($lastmodified=0, $lifetime=300, $themename='', $forceconfig='') {
6535be85 1874
9c4e6e21 1875 global $CFG, $THEME;
ab9f24ad 1876
b0ccd3fb 1877 header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastmodified) . ' GMT');
1878 header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $lifetime) . ' GMT');
1879 header('Cache-control: max_age = '. $lifetime);
1880 header('Pragma: ');
1881 header('Content-type: text/css'); // Correct MIME type
6535be85 1882
d45fd4dd 1883 $DEFAULT_SHEET_LIST = array('styles_layout', 'styles_fonts', 'styles_color');
9c4e6e21 1884
1885 if (empty($themename)) {
1886 $themename = current_theme(); // So we have something. Normally not needed.
1887 }
1888
1889 if (!empty($forceconfig)) { // Page wants to use the config from this theme instead
1890 unset($THEME);
2d40fc05 1891 include($CFG->themedir.$forceconfig.'/'.'config.php');
9c4e6e21 1892 }
1893
1894/// If this is the standard theme calling us, then find out what sheets we need
1895
1896 if ($themename == 'standard') {
1897 if (!isset($THEME->standardsheets) or $THEME->standardsheets === true) { // Use all the sheets we have
1898 $THEME->sheets = $DEFAULT_SHEET_LIST;
1899 } else if (empty($THEME->standardsheets)) { // We can stop right now!
1900 echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
1901 exit;
1902 } else { // Use the provided subset only
1903 $THEME->sheets = $THEME->standardsheets;
1904 }
1905
1906/// If we are a parent theme, then check for parent definitions
1907
1908 } else if (!empty($THEME->parent) && $themename == $THEME->parent) {
1909 if (!isset($THEME->parentsheets) or $THEME->parentsheets === true) { // Use all the sheets we have
1910 $THEME->sheets = $DEFAULT_SHEET_LIST;
1911 } else if (empty($THEME->parentsheets)) { // We can stop right now!
1912 echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
1913 exit;
1914 } else { // Use the provided subset only
1915 $THEME->sheets = $THEME->parentsheets;
1916 }
1917 }
1918
1919/// Work out the last modified date for this theme
1920
1921 foreach ($THEME->sheets as $sheet) {
2d40fc05 1922 if (file_exists($CFG->themedir.$themename.'/'.$sheet.'.css')) {
1923 $sheetmodified = filemtime($CFG->themedir.$themename.'/'.$sheet.'.css');
9c4e6e21 1924 if ($sheetmodified > $lastmodified) {
1925 $lastmodified = $sheetmodified;
1926 }
1927 }
6535be85 1928 }
1929
6535be85 1930
6ba172fb 1931/// Get a list of all the files we want to include
1932 $files = array();
1933
1934 foreach ($THEME->sheets as $sheet) {
1935 $files[] = array($CFG->themedir, $themename.'/'.$sheet.'.css');
1936 }
1937
1938 if ($themename == 'standard') { // Add any standard styles included in any modules
1939 if (!empty($THEME->modsheets)) { // Search for styles.php within activity modules
1940 if ($mods = get_list_of_plugins('mod')) {
1941 foreach ($mods as $mod) {
1942 if (file_exists($CFG->dirroot.'/mod/'.$mod.'/styles.php')) {
1943 $files[] = array($CFG->dirroot, '/mod/'.$mod.'/styles.php');
1944 }
08396bb2 1945 }
1946 }
1947 }
a2b3f884 1948
6ba172fb 1949 if (!empty($THEME->blocksheets)) { // Search for styles.php within block modules
1950 if ($mods = get_list_of_plugins('blocks')) {
1951 foreach ($mods as $mod) {
1952 if (file_exists($CFG->dirroot.'/blocks/'.$mod.'/styles.php')) {
1953 $files[] = array($CFG->dirroot, '/blocks/'.$mod.'/styles.php');
1954 }
08396bb2 1955 }
1956 }
1957 }
a2b3f884 1958
6ba172fb 1959 if (!empty($THEME->langsheets)) { // Search for styles.php within the current language
1960 $lang = current_language();
1961 if (file_exists($CFG->dirroot.'/lang/'.$lang.'/styles.php')) {
1962 $files[] = array($CFG->dirroot, '/lang/'.$lang.'/styles.php');
1963 }
1964 }
08396bb2 1965 }
1966
6ba172fb 1967
1968 if ($files) {
1969 /// Produce a list of all the files first
1970 echo '/**************************************'."\n";
1971 echo ' * THEME NAME: '.$themename."\n *\n";
1972 echo ' * Files included in this sheet:'."\n *\n";
1973 foreach ($files as $file) {
1974 echo ' * '.$file[1]."\n";
08396bb2 1975 }
6ba172fb 1976 echo ' **************************************/'."\n\n";
08396bb2 1977
6ba172fb 1978
1979 /// Actually output all the files in order.
1980 foreach ($files as $file) {
1981 echo '/***** '.$file[1].' start *****/'."\n\n";
1982 @include_once($file[0].$file[1]);
1983 echo '/***** '.$file[1].' end *****/'."\n\n";
1984 }
9c4e6e21 1985 }
1986
2d40fc05 1987 return $CFG->themewww.$themename; // Only to help old themes (1.4 and earlier)
6535be85 1988}
1989
9c4e6e21 1990
1991function theme_setup($theme = '', $params=NULL) {
d74d4f20 1992/// Sets up global variables related to themes
1993
56766f85 1994 global $CFG, $THEME, $SESSION, $USER;
d74d4f20 1995
1996 if (empty($theme)) {
1997 $theme = current_theme();
1998 }
9c4e6e21 1999
2000/// Put together the parameters
2001 if (!$params) {
2002 $params = array();
2003 }
56766f85 2004 if ($theme != $CFG->theme) {
2005 $params[] = 'forceconfig='.$theme;
9c4e6e21 2006 }
2007 if ($params) {
2008 $paramstring = '?'.implode('&amp;', $params);
d74d4f20 2009 } else {
9c4e6e21 2010 $paramstring = '';
d74d4f20 2011 }
2012
9c4e6e21 2013/// Load up the theme config
2014 $THEME = NULL; // Just to be sure
2d40fc05 2015 include($CFG->themedir. $theme .'/config.php'); // Main config for current theme
d74d4f20 2016
9c4e6e21 2017/// Set up image paths
d74d4f20 2018 if (empty($CFG->custompix)) { // Could be set in the above file
2019 $CFG->pixpath = $CFG->wwwroot .'/pix';
2020 $CFG->modpixpath = $CFG->wwwroot .'/mod';
2021 } else {
2d40fc05 2022 $CFG->pixpath = $CFG->themewww . $theme .'/pix';
2023 $CFG->modpixpath = $CFG->themewww . $theme .'/pix/mod';
d74d4f20 2024 }
2025
9c4e6e21 2026/// Header and footer paths
2d40fc05 2027 $CFG->header = $CFG->themedir . $theme .'/header.html';
2028 $CFG->footer = $CFG->themedir . $theme .'/footer.html';
d74d4f20 2029
9c4e6e21 2030/// Define stylesheet loading order
d74d4f20 2031 $CFG->stylesheets = array();
2032 if ($theme != 'standard') { /// The standard sheet is always loaded first
2d40fc05 2033 $CFG->stylesheets[] = $CFG->themewww.'standard/styles.php'.$paramstring;
d74d4f20 2034 }
2035 if (!empty($THEME->parent)) { /// Parent stylesheets are loaded next
2d40fc05 2036 $CFG->stylesheets[] = $CFG->themewww.$THEME->parent.'/styles.php'.$paramstring;
d74d4f20 2037 }
2d40fc05 2038 $CFG->stylesheets[] = $CFG->themewww.$theme.'/styles.php'.$paramstring;
d74d4f20 2039
2040}
2041
c3f55692 2042
d48b00b4 2043/**
2044 * Returns text to be displayed to the user which reflects their login status
2045 *
2046 * @uses $CFG
2047 * @uses $USER
89dcb99d 2048 * @param course $course {@link $COURSE} object containing course information
2049 * @param user $user {@link $USER} object containing user information
2050 * @return string
d48b00b4 2051 */
c44d5d42 2052function user_login_string($course=NULL, $user=NULL) {
2053 global $USER, $CFG, $SITE;
a282d0ff 2054
0e18f827 2055 if (empty($user) and isset($USER->id)) {
a282d0ff 2056 $user = $USER;
2057 }
2058
c44d5d42 2059 if (empty($course)) {
2060 $course = $SITE;
2061 }
2062
a282d0ff 2063 if (isset($user->realuser)) {
b0ccd3fb 2064 if ($realuser = get_record('user', 'id', $user->realuser)) {
2d71e8ee 2065 $fullname = fullname($realuser, true);
2066 $realuserinfo = " [<a target=\"{$CFG->framename}\"
2067 href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&amp;return=$realuser->id\">$fullname</a>] ";
9fa49e22 2068 }
9d378732 2069 } else {
b0ccd3fb 2070 $realuserinfo = '';
9fa49e22 2071 }
2072
87180677 2073 if (empty($CFG->loginhttps)) {
2074 $wwwroot = $CFG->wwwroot;
2075 } else {
2076 $wwwroot = str_replace('http','https',$CFG->wwwroot);
2077 }
2078
a282d0ff 2079 if (isset($user->id) and $user->id) {
2d71e8ee 2080 $fullname = fullname($user, true);
2081 $username = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id\">$fullname</a>";
0ae7e6f4 2082 if (isguest($user->id)) {
b0ccd3fb 2083 $loggedinas = $realuserinfo.get_string('loggedinas', 'moodle', $username).
2084 " (<a target=\"{$CFG->framename}\" href=\"$wwwroot/login/index.php\">".get_string('login').'</a>)';
0ae7e6f4 2085 } else {
b0ccd3fb 2086 $loggedinas = $realuserinfo.get_string('loggedinas', 'moodle', $username).
2087 " (<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/login/logout.php\">".get_string('logout').'</a>)';
0ae7e6f4 2088 }
9fa49e22 2089 } else {
b0ccd3fb 2090 $loggedinas = get_string('loggedinnot', 'moodle').
2091 " (<a target=\"{$CFG->framename}\" href=\"$wwwroot/login/index.php\">".get_string('login').'</a>)';
9fa49e22 2092 }
d3593a67 2093 return '<div class="logininfo">'.$loggedinas.'</div>';
9fa49e22 2094}
2095
d48b00b4 2096/**
2097 * Prints breadcrumbs links
2098 *
2099 * @uses $CFG
89dcb99d 2100 * @param string $navigation The breadcrumbs string to be printed
d48b00b4 2101 */
9fa49e22 2102function print_navigation ($navigation) {
2103 global $CFG;
2104
2105 if ($navigation) {
2106 if (! $site = get_site()) {
b0ccd3fb 2107 $site->shortname = get_string('home');;
9fa49e22 2108 }
50e4a15e 2109 $navigation = str_replace('->', '&raquo;', $navigation);
89dcb99d 2110 echo '<a target="'. $CFG->framename .'" href="'. $CFG->wwwroot .'/">'. $site->shortname .'</a> &raquo; '. $navigation;
9fa49e22 2111 }
2112}
2113
d48b00b4 2114/**
bfca0094 2115 * Prints a string in a specified size (retained for backward compatibility)
d48b00b4 2116 *
89dcb99d 2117 * @param string $text The text to be displayed
2118 * @param int $size The size to set the font for text display.
d48b00b4 2119 */
d4df9200 2120function print_headline($text, $size=2) {
bfca0094 2121 print_heading($text, 'left', $size);
d4df9200 2122}
2123
d48b00b4 2124/**
2125 * Prints text in a format for use in headings.
2126 *
89dcb99d 2127 * @param string $text The text to be displayed
2128 * @param string $align The alignment of the printed paragraph of text
2129 * @param int $size The size to set the font for text display.
d48b00b4 2130 */
4419aa80 2131function print_heading($text, $align='', $size=2, $class='main') {
bfca0094 2132 if ($align) {
2133 $align = ' align="'.$align.'"';
2134 }
4419aa80 2135 if ($class) {
2136 $class = ' class="'.$class.'"';
2137 }
2138 echo "<h$size $align $class>".stripslashes_safe($text)."</h$size>";
9fa49e22 2139}
2140
d48b00b4 2141/**
2142 * Centered heading with attached help button (same title text)
2143 * and optional icon attached
2144 *
89dcb99d 2145 * @param string $text The text to be displayed
2146 * @param string $helppage The help page to link to
2147 * @param string $module The module whose help should be linked to
2148 * @param string $icon Image to display if needed
d48b00b4 2149 */
b0ccd3fb 2150function print_heading_with_help($text, $helppage, $module='moodle', $icon='') {
4419aa80 2151 echo '<h2 class="main help">'.$icon.stripslashes_safe($text);
9fa49e22 2152 helpbutton($helppage, $text, $module);
26ecdc5b 2153 echo '</h2>';
9fa49e22 2154}
ab9f24ad 2155
6ee8277f 2156
2157function print_heading_block($heading, $class='') {
3f1f367d 2158 echo '<div class="headingblock header '.$class.'">'.stripslashes($heading).'</div>';
6ee8277f 2159}
2160
2161
d48b00b4 2162/**
2163 * Print a link to continue on to another page.
2164 *
2165 * @uses $CFG
2166 * @param string $link The url to create a link to.
2167 */
9fa49e22 2168function print_continue($link) {
9fa49e22 2169
51a96819 2170 global $CFG;
2171
9fa49e22 2172 if (!$link) {
b0ccd3fb 2173 $link = $_SERVER['HTTP_REFERER'];
9fa49e22 2174 }
2175
a8f68426 2176 echo '<div class="continuebutton">';
2177 print_single_button($link, NULL, get_string('continue'), 'post', $CFG->framename);
2178 echo '</div>'."\n";
9fa49e22 2179}
2180
d48b00b4 2181/**
2182 * Print a message in a standard themed box.
2183 *
89dcb99d 2184 * @param string $message ?
2185 * @param string $align ?
2186 * @param string $width ?
2187 * @param string $color ?
2188 * @param int $padding ?
2189 * @param string $class ?
d48b00b4 2190 * @todo Finish documenting this function
2191 */
da17a899 2192function print_simple_box($message, $align='', $width='', $color='', $padding=5, $class='generalbox', $id='') {
2193 print_simple_box_start($align, $width, $color, $padding, $class, $id);
7d8f674d 2194 echo stripslashes_safe($message);
9fa49e22 2195 print_simple_box_end();
2196}
2197
d48b00b4 2198/**
2199 * Print the top portion of a standard themed box.
2200 *
89dcb99d 2201 * @param string $align ?
2202 * @param string $width ?
2203 * @param string $color ?
2204 * @param int $padding ?
2205 * @param string $class ?
d48b00b4 2206 * @todo Finish documenting this function
2207 */
da17a899 2208function print_simple_box_start($align='', $width='', $color='', $padding=5, $class='generalbox', $id='') {
9fa49e22 2209
c147b8ab 2210 if ($color) {
2211 $color = 'bgcolor="'. $color .'"';
2212 }
9fa49e22 2213 if ($align) {
b0ccd3fb 2214 $align = 'align="'. $align .'"';
9fa49e22 2215 }
2216 if ($width) {
b0ccd3fb 2217 $width = 'width="'. $width .'"';
9fa49e22 2218 }
da17a899 2219 if ($id) {
2220 $id = 'id="'. $id .'"';
2221 }
2222 echo "<table $align $width $id class=\"$class\" border=\"0\" cellpadding=\"$padding\" cellspacing=\"0\">".
c147b8ab 2223 "<tr><td $color class=\"$class"."content\">";
9fa49e22 2224}
2225
d48b00b4 2226/**
2227 * Print the end portion of a standard themed box.
d48b00b4 2228 */
9fa49e22 2229function print_simple_box_end() {
b0ccd3fb 2230 echo '</td></tr></table>';
9fa49e22 2231}
2232
d48b00b4 2233/**
2234 * Print a self contained form with a single submit button.
2235 *
89dcb99d 2236 * @param string $link ?
2237 * @param array $options ?
2238 * @param string $label ?
2239 * @param string $method ?
d48b00b4 2240 * @todo Finish documenting this function
2241 */
4c6c0e01 2242function print_single_button($link, $options, $label='OK', $method='get', $target='_self') {
6ba172fb 2243 echo '<div class="singlebutton">';
4c6c0e01 2244 echo '<form action="'. $link .'" method="'. $method .'" target="'.$target.'">';
9fa49e22 2245 if ($options) {
2246 foreach ($options as $name => $value) {
b0ccd3fb 2247 echo '<input type="hidden" name="'. $name .'" value="'. $value .'" />';
9fa49e22 2248 }
2249 }
6ba172fb 2250 echo '<input type="submit" value="'. $label .'" /></form></div>';
9fa49e22 2251}
2252
d48b00b4 2253/**
2254 * Print a spacer image with the option of including a line break.
2255 *
89dcb99d 2256 * @param int $height ?
2257 * @param int $width ?
2258 * @param boolean $br ?
d48b00b4 2259 * @todo Finish documenting this function
2260 */
9fa49e22 2261function print_spacer($height=1, $width=1, $br=true) {
2262 global $CFG;
ed3136ff 2263 echo '<img class="spacer" height="'. $height .'" width="'. $width .'" src="'. $CFG->wwwroot .'/pix/spacer.gif" alt="" />';
9fa49e22 2264 if ($br) {
b0ccd3fb 2265 echo '<br />'."\n";
9fa49e22 2266 }
2267}
2268
d48b00b4 2269/**
2270 * Given the path to a picture file in a course, or a URL,
2271 * this function includes the picture in the page.
2272 *
89dcb99d 2273 * @param string $path ?
2274 * @param int $courseid ?
2275 * @param int $height ?
2276 * @param int $width ?
2277 * @param string $link ?
d48b00b4 2278 * @todo Finish documenting this function
2279 */
b0ccd3fb 2280function print_file_picture($path, $courseid=0, $height='', $width='', $link='') {
9fa49e22 2281 global $CFG;
2282
2283 if ($height) {
b0ccd3fb 2284 $height = 'height="'. $height .'"';
9fa49e22 2285 }
2286 if ($width) {
b0ccd3fb 2287 $width = 'width="'. $width .'"';
9fa49e22 2288 }
2289 if ($link) {
b0ccd3fb 2290 echo '<a href="'. $link .'">';
9fa49e22 2291 }
b0ccd3fb 2292 if (substr(strtolower($path), 0, 7) == 'http://') {
2293 echo '<img border="0" '.$height . $width .' src="'. $path .'" />';
9fa49e22 2294
2295 } else if ($courseid) {
b0ccd3fb 2296 echo '<img border="0" '. $height . $width .' src="';
9fa49e22 2297 if ($CFG->slasharguments) { // Use this method if possible for better caching
b0ccd3fb 2298 echo $CFG->wwwroot .'/file.php/'. $courseid .'/'. $path;
9fa49e22 2299 } else {
b0ccd3fb 2300 echo $CFG->wwwroot .'/file.php?file=/'. $courseid .'/'. $path;
9fa49e22 2301 }
b0ccd3fb 2302 echo '" />';
9fa49e22 2303 } else {
b0ccd3fb 2304 echo 'Error: must pass URL or course';
9fa49e22 2305 }
2306 if ($link) {
b0ccd3fb 2307 echo '</a>';
9fa49e22 2308 }
2309}
2310
d48b00b4 2311/**
2312 * Print the specified user's avatar.
2313 *
89dcb99d 2314 * @param int $userid ?
2315 * @param int $courseid ?
2316 * @param boolean $picture Print the user picture?
4c6c0e01 2317 * @param int $size Size in pixels. Special values are (true/1 = 100px) and (false/0 = 35px) for backward compatability
89dcb99d 2318 * @param boolean $returnstring If false print picture to current page, otherwise return the output as string
2319 * @param boolean $link Enclose printed image in a link to view specified course?
2320 * return string
d48b00b4 2321 * @todo Finish documenting this function
2322 */
f66e1977 2323function print_user_picture($userid, $courseid, $picture, $size=0, $returnstring=false, $link=true, $target='') {
f374fb10 2324 global $CFG;
9fa49e22 2325
2326 if ($link) {
f66e1977 2327 if ($target) {
2328 $target=' target="_blank"';
2329 }
2330 $output = '<a '.$target.' href="'. $CFG->wwwroot .'/user/view.php?id='. $userid .'&amp;course='. $courseid .'">';
9fa49e22 2331 } else {
b0ccd3fb 2332 $output = '';
9fa49e22 2333 }
4c6c0e01 2334 if (empty($size)) {
2335 $file = 'f2';
2336 $size = 35;
2337 } else if ($size === true or $size == 1) {
b0ccd3fb 2338 $file = 'f1';
9fa49e22 2339 $size = 100;
4c6c0e01 2340 } else if ($size >= 50) {
2341 $file = 'f1';
9fa49e22 2342 } else {
b0ccd3fb 2343 $file = 'f2';
9fa49e22 2344 }
67a63a30 2345 if ($picture) { // Print custom user picture
9fa49e22 2346 if ($CFG->slasharguments) { // Use this method if possible for better caching
ed3136ff 2347 $output .= '<img class="userpicture" align="middle" src="'. $CFG->wwwroot .'/user/pix.php/'. $userid .'/'. $file .'.jpg"'.
b0ccd3fb 2348 ' border="0" width="'. $size .'" height="'. $size .'" alt="" />';
9fa49e22 2349 } else {
ed3136ff 2350 $output .= '<img class="userpicture" align="middle" src="'. $CFG->wwwroot .'/user/pix.php?file=/'. $userid .'/'. $file .'.jpg"'.
b0ccd3fb 2351 ' border="0" width="'. $size .'" height="'. $size .'" alt="" />';
9fa49e22 2352 }
67a63a30 2353 } else { // Print default user pictures (use theme version if available)
839f2456 2354 $output .= "<img align=\"middle\" src=\"$CFG->pixpath/u/$file.png\"".
66a51452 2355 " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" />";
9fa49e22 2356 }
2357 if ($link) {
b0ccd3fb 2358 $output .= '</a>';
9fa49e22 2359 }
2360
2361 if ($returnstring) {
2362 return $output;
2363 } else {
2364 echo $output;
2365 }
2366}
2367
d48b00b4 2368/**
2369 * Prints a summary of a user in a nice little box.
2370 *
89dcb99d 2371 * @uses $CFG
2372 * @uses $USER
2373 * @param user $user A {@link $USER} object representing a user
2374 * @param course $course A {@link $COURSE} object representing a course
d48b00b4 2375 */
951b22a8 2376function print_user($user, $course) {
951b22a8 2377
89dcb99d 2378 global $CFG, $USER;
499795e8 2379
951b22a8 2380 static $string;
2381 static $datestring;
2382 static $countries;
2383 static $isteacher;
37d83d99 2384 static $isadmin;
951b22a8 2385
2386 if (empty($string)) { // Cache all the strings for the rest of the page
2387
b0ccd3fb 2388 $string->email = get_string('email');
2389 $string->location = get_string('location');
2390 $string->lastaccess = get_string('lastaccess');
2391 $string->activity = get_string('activity');
2392 $string->unenrol = get_string('unenrol');
2393 $string->loginas = get_string('loginas');
2394 $string->fullprofile = get_string('fullprofile');
2395 $string->role = get_string('role');
2396 $string->name = get_string('name');
2397 $string->never = get_string('never');
2398
2399 $datestring->day = get_string('day');
2400 $datestring->days = get_string('days');
2401 $datestring->hour = get_string('hour');
2402 $datestring->hours = get_string('hours');
2403 $datestring->min = get_string('min');
2404 $datestring->mins = get_string('mins');
2405 $datestring->sec = get_string('sec');
2406 $datestring->secs = get_string('secs');
951b22a8 2407
2408 $countries = get_list_of_countries();
2409
2410 $isteacher = isteacher($course->id);
37d83d99 2411 $isadmin = isadmin();
951b22a8 2412 }
2413
ed3136ff 2414 echo '<table class="userinfobox">';
951b22a8 2415 echo '<tr>';
ed3136ff 2416 echo '<td class="left side">';
951b22a8 2417 print_user_picture($user->id, $course->id, $user->picture, true);
2418 echo '</td>';
ed3136ff 2419 echo '<td class="content">';
2420 echo '<div class="username">'.fullname($user, $isteacher).'</div>';
2421 echo '<div class="info">';
951b22a8 2422 if (!empty($user->role) and ($user->role <> $course->teacher)) {
b0ccd3fb 2423 echo $string->role .': '. $user->role .'<br />';
951b22a8 2424 }
d0ec93fb 2425 if ($user->maildisplay == 1 or ($user->maildisplay == 2 and $course->category and !isguest()) or $isteacher) {
b0ccd3fb 2426 echo $string->email .': <a href="mailto:'. $user->email .'">'. $user->email .'</a><br />';
951b22a8 2427 }
2428 if ($user->city or $user->country) {
b0ccd3fb 2429 echo $string->location .': ';
b40bc478 2430 if ($user->city) {
2431 echo $user->city;
2432 }
2433 if (!empty($countries[$user->country])) {
2434 if ($user->city) {
2435 echo ', ';
2436 }
2437 echo $countries[$user->country];
2438 }
b0ccd3fb 2439 echo '<br />';
951b22a8 2440 }
2441 if ($user->lastaccess) {
b0ccd3fb 2442 echo $string->lastaccess .': '. userdate($user->lastaccess);
2443 echo '&nbsp ('. format_time(time() - $user->lastaccess, $datestring) .')';
951b22a8 2444 } else {
b0ccd3fb 2445 echo $string->lastaccess .': '. $string->never;
951b22a8 2446 }
ed3136ff 2447 echo '</div></td><td class="links">';
951b22a8 2448
951b22a8 2449 if ($isteacher) {
2450 $timemidnight = usergetmidnight(time());
b0ccd3fb 2451 echo '<a href="'. $CFG->wwwroot .'/course/user.php?id='. $course->id .'&amp;user='. $user->id .'">'. $string->activity .'</a><br />';
37d83d99 2452 if (!iscreator($user->id) or ($isadmin and !isadmin($user->id))) { // Includes admins
f29667f6 2453 if ($course->category and isteacheredit($course->id) and isstudent($course->id, $user->id)) { // Includes admins
b0ccd3fb 2454 echo '<a href="'. $CFG->wwwroot .'/course/unenrol.php?id='. $course->id .'&amp;user='. $user->id .'">'. $string->unenrol .'</a><br />';
4e3a6092 2455 }
2456 if ($USER->id != $user->id) {
b0ccd3fb 2457 echo '<a href="'. $CFG->wwwroot .'/course/loginas.php?id='. $course->id .'&amp;user='. $user->id .'">'. $string->loginas .'</a><br />';
4e3a6092 2458 }
951b22a8 2459 }
ab9f24ad 2460 }
b0ccd3fb 2461 echo '<a href="'. $CFG->wwwroot .'/user/view.php?id='. $user->id .'&amp;course='. $course->id .'">'. $string->fullprofile .'...</a>';
951b22a8 2462
2463 echo '</td></tr></table>';
2464}
2465
d48b00b4 2466/**
2467 * Print a specified group's avatar.
2468 *
89dcb99d 2469 * @param group $group A {@link group} object representing a group
2470 * @param int $courseid ?
2471 * @param boolean $large ?
2472 * @param boolean $returnstring ?
2473 * @param boolean $link ?
2474 * @return string
d48b00b4 2475 * @todo Finish documenting this function
2476 */
f2c80965 2477function print_group_picture($group, $courseid, $large=false, $returnstring=false, $link=true) {
f374fb10 2478 global $CFG;
2479
97ea4833 2480 static $isteacheredit;
2481
2482 if (!isset($isteacheredit)) {
2483 $isteacheredit = isteacheredit($courseid);
2484 }
2485
2486 if ($group->hidepicture and !$isteacheredit) {
3c0561cf 2487 return '';
2488 }
c3cbfe7f 2489
97ea4833 2490 if ($link or $isteacheredit) {
b0ccd3fb 2491 $output = '<a href="'. $CFG->wwwroot .'/course/group.php?id='. $courseid .'&amp;group='. $group->id .'">';
3c0561cf 2492 } else {
2493 $output = '';
2494 }
2495 if ($large) {
b0ccd3fb 2496 $file = 'f1';
3c0561cf 2497 $size = 100;
2498 } else {
b0ccd3fb 2499 $file = 'f2';
3c0561cf 2500 $size = 35;
2501 }
2502 if ($group->picture) { // Print custom group picture
2503 if ($CFG->slasharguments) { // Use this method if possible for better caching
ed3136ff 2504 $output .= '<img class="grouppicture" align="middle" src="'.$CFG->wwwroot.'/user/pixgroup.php/'.$group->id.'/'.$file.'.jpg"'.
2505 ' border="0" width="'.$size.'" height="'.$size.'" alt="" title="'.s($group->name).'"/>';
f2c80965 2506 } else {
ed3136ff 2507 $output .= '<img class="grouppicture" align="middle" src="'.$CFG->wwwroot.'/user/pixgroup.php?file=/'.$group->id.'/'.$file.'.jpg"'.
2508 ' border="0" width="'.$size.'" height="'.$size.'" alt="" title="'.s($group->name).'"/>';
f2c80965 2509 }
f374fb10 2510 }
97ea4833 2511 if ($link or $isteacheredit) {
b0ccd3fb 2512 $output .= '</a>';
3c0561cf 2513 }
f374fb10 2514
2515 if ($returnstring) {
2516 return $output;
2517 } else {
2518 echo $output;
2519 }
2520}
2521
d48b00b4 2522/**
2523 * Print a png image.
2524 *
89dcb99d 2525 * @param string $url ?
2526 * @param int $sizex ?
2527 * @param int $sizey ?
2528 * @param boolean $returnstring ?
2529 * @param string $parameters ?
d48b00b4 2530 * @todo Finish documenting this function
2531 */
35067c43 2532function print_png($url, $sizex, $sizey, $returnstring, $parameters='alt=""') {
2533 global $CFG;
2534 static $recentIE;
2535
2536 if (!isset($recentIE)) {
2537 $recentIE = check_browser_version('MSIE', '5.0');
2538 }
2539
2540 if ($recentIE) { // work around the HORRIBLE bug IE has with alpha transparencies
89dcb99d 2541 $output .= '<img src="'. $CFG->pixpath .'/spacer.gif" width="'. $sizex .'" height="'. $sizey .'"'.
430c6392 2542 ' border="0" class="png" style="width: '. $sizex .'px; height: '. $sizey .'px; '.
89dcb99d 2543 ' filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='.
2544 "'$url', sizingMethod='scale') ".
2545 ' '. $parameters .' />';
35067c43 2546 } else {
89dcb99d 2547 $output .= '<img src="'. $url .'" border="0" width="'. $sizex .'" height="'. $sizey .'" '.
2548 ' '. $parameters .' />';
35067c43 2549 }
2550
2551 if ($returnstring) {
2552 return $output;
2553 } else {
2554 echo $output;
2555 }
2556}
2557
d48b00b4 2558/**
2559 * Print a nicely formatted table.
2560 *
89dcb99d 2561 * @param array $table is an object with several properties.
2562 * <ul<li>$table->head - An array of heading names.
2563 * <li>$table->align - An array of column alignments
2564 * <li>$table->size - An array of column sizes
2565 * <li>$table->wrap - An array of "nowrap"s or nothing
2566 * <li>$table->data[] - An array of arrays containing the data.
2567 * <li>$table->width - A percentage of the page
2568 * <li>$table->cellpadding - Padding on each cell
2569 * <li>$table->cellspacing - Spacing between cells
2570 * </ul>
2571 * @return boolean
d48b00b4 2572 * @todo Finish documenting this function
2573 */
9fa49e22 2574function print_table($table) {
9fa49e22 2575
2576 if (isset($table->align)) {
2577 foreach ($table->align as $key => $aa) {
2578 if ($aa) {
b0ccd3fb 2579 $align[$key] = ' align="'. $aa .'"';
9fa49e22 2580 } else {
b0ccd3fb 2581 $align[$key] = '';
9fa49e22 2582 }
2583 }
2584 }
2585 if (isset($table->size)) {
2586 foreach ($table->size as $key => $ss) {
2587 if ($ss) {
b0ccd3fb 2588 $size[$key] = ' width="'. $ss .'"';
9fa49e22 2589 } else {
b0ccd3fb 2590 $size[$key] = '';
9fa49e22 2591 }
2592 }
2593 }
5867bfb5 2594 if (isset($table->wrap)) {
2595 foreach ($table->wrap as $key => $ww) {
2596 if ($ww) {
b0ccd3fb 2597 $wrap[$key] = ' nowrap="nowrap" ';
5867bfb5 2598 } else {
b0ccd3fb 2599 $wrap[$key] = '';
5867bfb5 2600 }
2601 }
2602 }
9fa49e22 2603
9d378732 2604 if (empty($table->width)) {
b0ccd3fb 2605 $table->width = '80%';
9fa49e22 2606 }
2607
9d378732 2608 if (empty($table->cellpadding)) {
b0ccd3fb 2609 $table->cellpadding = '5';
9fa49e22 2610 }
2611
9d378732 2612 if (empty($table->cellspacing)) {
b0ccd3fb 2613 $table->cellspacing = '1';
9fa49e22 2614 }
2615
da17a899 2616 if (empty($table->class)) {
2617 $table->class = 'generaltable';
2618 }
2619
2620 $tableid = empty($table->id) ? '' : 'id="'.$table->id.'"';
2621
b0ccd3fb 2622 print_simple_box_start('center', $table->width, '#ffffff', 0);
2623 echo '<table width="100%" border="0" align="center" ';
da17a899 2624 echo " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\" class=\"$table->class\" $tableid>\n";
9fa49e22 2625
e21e20cf 2626 $countcols = 0;
2627
b79f41cd 2628 if (!empty($table->head)) {
e21e20cf 2629 $countcols = count($table->head);;
b0ccd3fb 2630 echo '<tr>';
9fa49e22 2631 foreach ($table->head as $key => $heading) {
ab9f24ad 2632
9d378732 2633 if (!isset($size[$key])) {
b0ccd3fb 2634 $size[$key] = '';
ab9f24ad 2635 }
9d378732 2636 if (!isset($align[$key])) {
b0ccd3fb 2637 $align[$key] = '';
ab9f24ad 2638 }
591052a4 2639 echo '<th valign="top" '. $align[$key].$size[$key] .' nowrap="nowrap" class="header c'.$key.'">'. $heading .'</th>';
9fa49e22 2640 }
b0ccd3fb 2641 echo '</tr>'."\n";
9fa49e22 2642 }
2643
a1f8ff87 2644 if (!empty($table->data)) {
19505667 2645 $oddeven = 1;
2646 foreach ($table->data as $key => $row) {
2647 $oddeven = $oddeven ? 0 : 1;
2648 echo '<tr class="r'.$oddeven.'">'."\n";
b0ccd3fb 2649 if ($row == 'hr' and $countcols) {
2650 echo '<td colspan="'. $countcols .'"><div class="tabledivider"></div></td>';
e21e20cf 2651 } else { /// it's a normal row of data
2652 foreach ($row as $key => $item) {
2653 if (!isset($size[$key])) {
b0ccd3fb 2654 $size[$key] = '';
ab9f24ad 2655 }
e21e20cf 2656 if (!isset($align[$key])) {
b0ccd3fb 2657 $align[$key] = '';
ab9f24ad 2658 }
e21e20cf 2659 if (!isset($wrap[$key])) {
b0ccd3fb 2660 $wrap[$key] = '';
ab9f24ad 2661 }
591052a4 2662 echo '<td '. $align[$key].$size[$key].$wrap[$key] .' class="cell c'.$key.'">'. $item .'</td>';
e21e20cf 2663 }
a1f8ff87 2664 }
b0ccd3fb 2665 echo '</tr>'."\n";
9fa49e22 2666 }
9fa49e22 2667 }
b0ccd3fb 2668 echo '</table>'."\n";
9fa49e22 2669 print_simple_box_end();
2670
2671 return true;
2672}
2673
d48b00b4 2674/**
2675 * Creates a nicely formatted table and returns it.
2676 *
89dcb99d 2677 * @param array $table is an object with several properties.
2678 * <ul<li>$table->head - An array of heading names.
2679 * <li>$table->align - An array of column alignments
2680 * <li>$table->size - An array of column sizes
2681 * <li>$table->wrap - An array of "nowrap"s or nothing
2682 * <li>$table->data[] - An array of arrays containing the data.
2683 * <li>$table->class - A css class name
2684 * <li>$table->fontsize - Is the size of all the text
2685 * <li>$table->tablealign - Align the whole table
2686 * <li>$table->width - A percentage of the page
2687 * <li>$table->cellpadding - Padding on each cell
2688 * <li>$table->cellspacing - Spacing between cells
2689 * </ul>
2690 * @return string
d48b00b4 2691 * @todo Finish documenting this function
2692 */
2f4d324b 2693function make_table($table) {
2f4d324b 2694
2695 if (isset($table->align)) {
2696 foreach ($table->align as $key => $aa) {
2697 if ($aa) {
b0ccd3fb 2698 $align[$key] = ' align="'. $aa .'"';
2f4d324b 2699 } else {
b0ccd3fb 2700 $align[$key] = '';
2f4d324b 2701 }
2702 }
2703 }
2704 if (isset($table->size)) {
2705 foreach ($table->size as $key => $ss) {
2706 if ($ss) {
b0ccd3fb 2707 $size[$key] = ' width="'. $ss .'"';
2f4d324b 2708 } else {
b0ccd3fb 2709 $size[$key] = '';
2f4d324b 2710 }
2711 }
2712 }
2713 if (isset($table->wrap)) {
2714 foreach ($table->wrap as $key => $ww) {
2715 if ($ww) {
b0ccd3fb 2716 $wrap[$key] = ' nowrap="nowrap" ';
2f4d324b 2717 } else {
b0ccd3fb 2718 $wrap[$key] = '';
2f4d324b 2719 }
2720 }
2721 }
2722
2723 if (empty($table->width)) {
b0ccd3fb 2724 $table->width = '80%';
2f4d324b 2725 }
2726
2727 if (empty($table->tablealign)) {
b0ccd3fb 2728 $table->tablealign = 'center';
2f4d324b 2729 }
2730
2731 if (empty($table->cellpadding)) {
b0ccd3fb 2732 $table->cellpadding = '5';
2f4d324b 2733 }
2734
2735 if (empty($table->cellspacing)) {
b0ccd3fb 2736 $table->cellspacing = '1';
2f4d324b 2737 }
2738
2739 if (empty($table->class)) {
b0ccd3fb 2740 $table->class = 'generaltable';
2f4d324b 2741 }
2742
2743 if (empty($table->fontsize)) {
b0ccd3fb 2744 $fontsize = '';
2f4d324b 2745 } else {
b0ccd3fb 2746 $fontsize = '<font size="'. $table->fontsize .'">';
2f4d324b 2747 }
2748
5aeaeb57 2749 $output = '<table width="'. $table->width .'" align="'. $table->tablealign .'" ';
b0ccd3fb 2750 $output .= ' cellpadding="'. $table->cellpadding .'" cellspacing="'. $table->cellspacing .'" class="'. $table->class .'">'."\n";
2f4d324b 2751
2752 if (!empty($table->head)) {
5aeaeb57 2753 $output .= '<tr valign="top">';
2f4d324b 2754 foreach ($table->head as $key => $heading) {
2755 if (!isset($size[$key])) {
b0ccd3fb 2756 $size[$key] = '';
ab9f24ad 2757 }
2f4d324b 2758 if (!isset($align[$key])) {
b0ccd3fb 2759 $align[$key] = '';
ab9f24ad 2760 }
b0ccd3fb 2761 $output .= '<th valign="top" '. $align[$key].$size[$key] .' nowrap="nowrap" class="'. $table->class .'header">'.$fontsize.$heading.'</th>';
2f4d324b 2762 }
b0ccd3fb 2763 $output .= '</tr>'."\n";
2f4d324b 2764 }
2765
2766 foreach ($table->data as $row) {
b0ccd3fb 2767 $output .= '<tr valign="top">';
2f4d324b 2768 foreach ($row as $key => $item) {
2769 if (!isset($size[$key])) {
b0ccd3fb 2770 $size[$key] = '';
ab9f24ad 2771 }
2f4d324b 2772 if (!isset($align[$key])) {
b0ccd3fb 2773 $align[$key] = '';
ab9f24ad 2774 }
2f4d324b 2775 if (!isset($wrap[$key])) {
b0ccd3fb 2776 $wrap[$key] = '';
ab9f24ad 2777 }
b0ccd3fb 2778 $output .= '<td '. $align[$key].$size[$key].$wrap[$key] .' class="'. $table->class .'cell">'. $fontsize . $item .'</td>';
2f4d324b 2779 }
b0ccd3fb 2780 $output .= '</tr>'."\n";
2f4d324b 2781 }
b0ccd3fb 2782 $output .= '</table>'."\n";
2f4d324b 2783
2784 return $output;
2785}
2786
8f7dc7f1 2787function print_recent_activity_note($time, $user, $isteacher, $text, $link) {
2788 static $strftimerecent;
2789
2790 if (empty($strftimerecent)) {
2791 $strftimerecent = get_string('strftimerecent');
2792 }
2793
2794 $date = userdate($time, $strftimerecent);
2795 $name = fullname($user, $isteacher);
2796
2797 echo '<div class="head">';
2798 echo '<span class="date">'.$date.'</span> - '.
2799 '<span class="name">'.fullname($user, $isteacher).'</span>';
2800 echo '</div>';
188e4dd9 2801 echo '<div class="info"><a href="'.$link.'">'.format_string($text,true).'</a></div>';
8f7dc7f1 2802}
2803
2804
d48b00b4 2805/**
2806 * Prints a basic textarea field.
2807 *
89dcb99d 2808 * @uses $CFG
2809 * @param boolean $usehtmleditor ?
2810 * @param int $rows ?
2811 * @param int $cols ?
ed3136ff 2812 * @param null $width <b>Legacy field no longer used!</b> Set to zero to get control over mincols
2813 * @param null $height <b>Legacy field no longer used!</b> Set to zero to get control over minrows
89dcb99d 2814 * @param string $name ?
2815 * @param string $value ?
2816 * @param int $courseid ?
d48b00b4 2817 * @todo Finish documenting this function
2818 */
b0ccd3fb 2819function print_textarea($usehtmleditor, $rows, $cols, $width, $height, $name, $value='', $courseid=0) {
bc01a2b8 2820/// $width and height are legacy fields and no longer used as pixels like they used to be.
2821/// However, you can set them to zero to override the mincols and minrows values below.
4c46c425 2822
47037513 2823 global $CFG, $course;
50bdc74d 2824
bc01a2b8 2825 $mincols = 65;
2826 $minrows = 10;
2827
408e62f8 2828 if (empty($courseid)) {
50bdc74d 2829 if (!empty($course->id)) { // search for it in global context
2830 $courseid = $course->id;
2831 }
2832 }
9fa49e22 2833
47037513 2834 if ($usehtmleditor) {
2835 if (!empty($courseid) and isteacher($courseid)) {
b0ccd3fb 2836 echo '<script type="text/javascript" src="'. $CFG->wwwroot .'/lib/editor/htmlarea.php?id='. $courseid .'"></script>'."\n";
47037513 2837 } else {
b0ccd3fb 2838 echo '<script type="text/javascript" src="'. $CFG->wwwroot .'/lib/editor/htmlarea.php"></script>'."\n";
47037513 2839 }
b0ccd3fb 2840 echo '<script type="text/javascript" src="'. $CFG->wwwroot .'/lib/editor/dialog.js"></script>'."\n";
2841 echo '<script type="text/javascript" src="'. $CFG->wwwroot .'/lib/editor/lang/en.php"></script>'."\n";
2842 echo '<script type="text/javascript" src="'. $CFG->wwwroot .'/lib/editor/popupwin.js"></script>'."\n";
50bdc74d 2843
ed3136ff 2844 if ($height) { // Usually with legacy calls
bc01a2b8 2845 if ($rows < $minrows) {
2846 $rows = $minrows;
ed3136ff 2847 }
47037513 2848 }
ed3136ff 2849 if ($width) { // Usually with legacy calls
bc01a2b8 2850 if ($cols < $mincols) {
2851 $cols = $mincols;
ed3136ff 2852 }
4c46c425 2853 }
9fa49e22 2854 }
47037513 2855
fd9d1ff3 2856 echo '<textarea id="edit-'. $name .'" name="'. $name .'" rows="'. $rows .'" cols="'. $cols .'">';
47037513 2857 p($value);
b0ccd3fb 2858 echo '</textarea>'."\n";
9fa49e22 2859}
2860
d48b00b4 2861/**
772e78be 2862 * Legacy function, provided for backward compatability.
d48b00b4 2863 * This method now simply calls {@link use_html_editor()}
2864 *
89dcb99d 2865 * @deprecated Use {@link use_html_editor()} instead.
2866 * @param string $name Form element to replace with HTMl editor by name
d48b00b4 2867 * @todo Finish documenting this function
2868 */
b0ccd3fb 2869function print_richedit_javascript($form, $name, $source='no') {
47037513 2870 use_html_editor($name);
2871}
2872
d48b00b4 2873/**
2874 * Sets up the HTML editor on textareas in the current page.
2875 * If a field name is provided, then it will only be
2876 * applied to that field - otherwise it will be used
2877 * on every textarea in the page.
2878 *
2879 * In most cases no arguments need to be supplied
2880 *
89dcb99d 2881 * @param string $name Form element to replace with HTMl editor by name
d48b00b4 2882 */
ed3136ff 2883function use_html_editor($name='', $editorhidebuttons='') {
b0ccd3fb 2884 echo '<script language="javascript" type="text/javascript" defer="defer">'."\n";
ed3136ff 2885 print_editor_config($editorhidebuttons);
47037513 2886 if (empty($name)) {
b0ccd3fb 2887 echo "\n".'HTMLArea.replaceAll(config);'."\n";
47037513 2888 } else {
a2b3f884 2889 echo "\nHTMLArea.replace('edit-$name', config);\n";
4c46c425 2890 }
b0ccd3fb 2891 echo '</script>'."\n";
9fa49e22 2892}
2893
d48b00b4 2894/**
2895 * Returns a turn edit on/off button for course in a self contained form.
2896 * Used to be an icon, but it's now a simple form button
2897 *
89dcb99d 2898 * @uses $CFG
2899 * @uses $USER
2900 * @param int $courseid The course to update by id as found in 'course' table
2901 * @return string
d48b00b4 2902 */
9fa49e22 2903function update_course_icon($courseid) {
772e78be 2904
9fa49e22 2905 global $CFG, $USER;
2906
b6c12732 2907 if (isteacheredit($courseid)) {
9c9f7d77 2908 if (!empty($USER->editing)) {
b0ccd3fb 2909 $string = get_string('turneditingoff');
2910 $edit = 'off';
9fa49e22 2911 } else {
b0ccd3fb 2912 $string = get_string('turneditingon');
2913 $edit = 'on';
9fa49e22 2914 }
60b9a565 2915 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/view.php\">".
66a51452 2916 "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
2917 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
2918 "<input type=\"submit\" value=\"$string\" /></form>";
9fa49e22 2919 }
2920}
2921
d48b00b4 2922/**
2923 * Prints the editing button on a module "view" page
2924 *
2925 * @uses $CFG
2926 * @param type description
2927 * @todo Finish documenting this function
2928 */
9fa49e22 2929function update_module_button($moduleid, $courseid, $string) {
bfce67a1 2930 global $CFG, $USER;
9fa49e22 2931
b6c12732 2932 if (isteacheredit($courseid)) {
b0ccd3fb 2933 $string = get_string('updatethis', '', $string);
60b9a565 2934 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/mod.php\">".
66a51452 2935 "<input type=\"hidden\" name=\"update\" value=\"$moduleid\" />".
2936 "<input type=\"hidden\" name=\"return\" value=\"true\" />".
6bdd02e4 2937 "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />".
66a51452 2938 "<input type=\"submit\" value=\"$string\" /></form>";
b6c12732 2939 } else {
b0ccd3fb 2940 return '';
9fa49e22 2941 }
2942}
2943
d48b00b4 2944/**
2945 * Prints the editing button on a category page
2946 *
2947 * @uses $CFG
2948 * @uses $USER
89dcb99d 2949 * @param int $categoryid ?
2950 * @return string
d48b00b4 2951 * @todo Finish documenting this function
2952 */
c2cb4545 2953function update_category_button($categoryid) {
d2b6ba70 2954 global $CFG, $USER;
c2cb4545 2955
d2b6ba70 2956 if (iscreator()) {
f374fb10 2957 if (!empty($USER->categoryediting)) {
b0ccd3fb 2958 $string = get_string('turneditingoff');
2959 $edit = 'off';
d2b6ba70 2960 } else {
b0ccd3fb 2961 $string = get_string('turneditingon');
2962 $edit = 'on';
ab9f24ad 2963 }
60b9a565 2964 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/category.php\">".
66a51452 2965 "<input type=\"hidden\" name=\"id\" value=\"$categoryid\" />".
2966 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
abf45bed 2967 "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />".
66a51452 2968 "<input type=\"submit\" value=\"$string\" /></form>";
d2b6ba70 2969 }
2970}
2971
d48b00b4 2972/**
2973 * Prints the editing button on categories listing
2974 *
89dcb99d 2975 * @uses $CFG
2976 * @uses $USER
2977 * @return string
d48b00b4 2978 */
d2b6ba70 2979function update_categories_button() {
d2b6ba70 2980 global $CFG, $USER;
2981
2982 if (isadmin()) {
f374fb10 2983 if (!empty($USER->categoriesediting)) {
b0ccd3fb 2984 $string = get_string('turneditingoff');
2985 $edit = 'off';
d2b6ba70 2986 } else {
b0ccd3fb 2987 $string = get_string('turneditingon');
2988 $edit = 'on';
d2b6ba70 2989 }
60b9a565 2990 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/index.php\">".
89dcb99d 2991 '<input type="hidden" name="edit" value="'. $edit .'" />'.
d99ceac2 2992 '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />'.
89dcb99d 2993 '<input type="submit" value="'. $string .'" /></form>';
c2cb4545 2994 }
2995}
9fa49e22 2996
d48b00b4 2997/**
2998 * Prints the editing button on group page
2999 *
89dcb99d 3000 * @uses $CFG
3001 * @uses $USER
3002 * @param int $courseid The course group is associated with
3003 * @param int $groupid The group to update
3004 * @return string
d48b00b4 3005 */
b3153e4b 3006function update_group_button($courseid, $groupid) {
f374fb10 3007 global $CFG, $USER;
3008
3009 if (isteacheredit($courseid)) {
b3153e4b 3010 $string = get_string('editgroupprofile');
f374fb10 3011 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/group.php\">".
89dcb99d 3012 '<input type="hidden" name="id" value="'. $courseid .'" />'.
3013 '<input type="hidden" name="group" value="'. $groupid .'" />'.
3014 '<input type="hidden" name="edit" value="on" />'.
3015 '<input type="submit" value="'. $string .'" /></form>';
f374fb10 3016 }
3017}
3018
d48b00b4 3019/**
3020 * Prints the editing button on groups page
3021 *
89dcb99d 3022 * @uses $CFG
3023 * @uses $USER
3024 * @param int $courseid The id of the course to be edited
3025 * @return string
d48b00b4 3026 * @todo Finish documenting this function
3027 */
f374fb10 3028function update_groups_button($courseid) {
f374fb10 3029 global $CFG, $USER;
3030
3031 if (isteacheredit($courseid)) {
3032 if (!empty($USER->groupsediting)) {
b0ccd3fb 3033 $string = get_string('turneditingoff');
3034 $edit = 'off';
f374fb10 3035 } else {
b0ccd3fb 3036 $string = get_string('turneditingon');
3037 $edit = 'on';
f374fb10 3038 }
3039 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/groups.php\">".
3040 "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
3041 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3042 "<input type=\"submit\" value=\"$string\" /></form>";
3043 }
3044}
3045
d48b00b4 3046/**
3047 * Prints an appropriate group selection menu
3048 *
89dcb99d 3049 * @uses VISIBLEGROUPS
3050 * @param array $groups ?
3051 * @param int $groupmode ?
3052 * @param string $currentgroup ?
3053 * @param string $urlroot ?
d48b00b4 3054 * @todo Finish documenting this function
3055 */
c3cbfe7f 3056function print_group_menu($groups, $groupmode, $currentgroup, $urlroot) {
c3cbfe7f 3057
1d9fc417 3058/// Add an "All groups" to the start of the menu
b0ccd3fb 3059 $groupsmenu[0] = get_string('allparticipants');
1d9fc417 3060 foreach ($groups as $key => $groupname) {
3061 $groupsmenu[$key] = $groupname;
3062 }
3063
e9a551b3 3064 echo '<table><tr><td align="right">';
c3cbfe7f 3065 if ($groupmode == VISIBLEGROUPS) {
3066 print_string('groupsvisible');
3067 } else {
3068 print_string('groupsseparate');
3069 }
3070 echo ':';
e9a551b3 3071 echo '</td><td nowrap="nowrap" align="left">';
b0ccd3fb 3072 popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $currentgroup, '', '', '', false, 'self');
f685bf2e 3073 echo '</td></tr></table>';
c3cbfe7f 3074
3075}
3076
d48b00b4 3077/**
3078 * Given a course and a (current) coursemodule
3079 * This function returns a small popup menu with all the
3080 * course activity modules in it, as a navigation menu
3081 * The data is taken from the serialised array stored in
3082 * the course record
3083 *
89dcb99d 3084 * @param course $course A {@link $COURSE} object.
3085 * @param course $cm A {@link $COURSE} object.
3086 * @param string $targetwindow ?
3087 * @return string
d48b00b4 3088 * @todo Finish documenting this function
3089 */
b0ccd3fb 3090function navmenu($course, $cm=NULL, $targetwindow='self') {
9fa49e22 3091
2507b2f5 3092 global $CFG, $THEME;
3093
3094 if (empty($THEME->navmenuwidth)) {
3095 $width = 50;
3096 } else {
3097 $width = $THEME->navmenuwidth;
3098 }
9fa49e22 3099
3100 if ($cm) {
f2d91421 3101 $cm = $cm->id;
9fa49e22 3102 }
3103
3104 if ($course->format == 'weeks') {
b0ccd3fb 3105 $strsection = get_string('week');
9fa49e22 3106 } else {
b0ccd3fb 3107 $strsection = get_string('topic');
9fa49e22 3108 }
cc7cd917 3109 $strjumpto = get_string('jumpto');
9fa49e22 3110
3111 if (!$modinfo = unserialize($course->modinfo)) {
b0ccd3fb 3112 return '';
9fa49e22 3113 }
f2d91421 3114 $isteacher = isteacher($course->id);
9fa49e22 3115 $section = -1;
b0ccd3fb 3116 $selected = '';
3117 $url = '';
f2d91421 3118 $previousmod = NULL;
3119 $backmod = NULL;
3120 $nextmod = NULL;
4866a367 3121 $selectmod = NULL;
3da47524 3122 $logslink = NULL;
f2d91421 3123 $flag = false;
6f9f3b69 3124 $menu = array();
f2d91421 3125
b0ccd3fb 3126 $sections = get_records('course_sections','course',$course->id,'section','section,visible,summary');
ca189cec 3127
2507b2f5 3128 if (!empty($THEME->makenavmenulist)) { /// A hack to produce an XHTML navmenu list for use in themes
a2b3f884 3129 $THEME->navmenulist = navmenulist($course, $sections, $modinfo,
cc7cd917 3130 $isteacher, $strsection, $strjumpto, $width, $cm);
2507b2f5 3131 }
3132
9fa49e22 3133 foreach ($modinfo as $mod) {
b0ccd3fb 3134 if ($mod->mod == 'label') {
ab2df10c 3135 continue;
3136 }
ca189cec 3137
72b9f333 3138 if ($mod->section > $course->numsections) { /// Don't show excess hidden sections
3139 break;
3140 }
3141
9fa49e22 3142 if ($mod->section > 0 and $section <> $mod->section) {
f2b9b6ea 3143 $thissection = $sections[$mod->section];
3144
3145 if ($thissection->visible or !$course->hiddensections or $isteacher) {
9870dbe5 3146 $thissection->summary = strip_tags(format_string($thissection->summary,true));
f2b9b6ea 3147 if ($course->format == 'weeks' or empty($thissection->summary)) {
b0ccd3fb 3148 $menu[] = '-------------- '. $strsection ." ". $mod->section .' --------------';
f2b9b6ea 3149 } else {
2507b2f5 3150 if (strlen($thissection->summary) < ($width-3)) {
f2b9b6ea 3151 $menu[] = '-- '.$thissection->summary;
3152 } else {
2507b2f5 3153 $menu[] = '-- '.substr($thissection->summary, 0, $width).'...';
f2b9b6ea 3154 }
3155 }
ca189cec 3156 }
9fa49e22 3157 }
ca189cec 3158
9fa49e22 3159 $section = $mod->section;
ca189cec 3160
cf055081 3161 //Only add visible or teacher mods to jumpmenu
f2d91421 3162 if ($mod->visible or $isteacher) {
b0ccd3fb 3163 $url = $mod->mod .'/view.php?id='. $mod->cm;
f2d91421 3164 if ($flag) { // the current mod is the "next" mod
3165 $nextmod = $mod;
3166 $flag = false;
3167 }
cf055081 3168 if ($cm == $mod->cm) {
3169 $selected = $url;
3da47524 3170 $selectmod = $mod;
f2d91421 3171 $backmod = $previousmod;
3172 $flag = true; // set flag so we know to use next mod for "next"
a2fa19d8 3173 $mod->name = $strjumpto;
5bff6751 3174 $strjumpto = '';
cb648037 3175 } else {
9870dbe5 3176 $mod->name = strip_tags(format_string(urldecode($mod->name),true));
2507b2f5 3177 if (strlen($mod->name) > ($width+5)) {
3178 $mod->name = substr($mod->name, 0, $width).'...';
cb648037 3179 }
3180 if (!$mod->visible) {
b0ccd3fb 3181 $mod->name = '('.$mod->name.')';
cb648037 3182 }
2a409368