3 ///////////////////////////////////////////////////////////////////////////
5 // NOTICE OF COPYRIGHT //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
8 // http://moodle.com //
10 // Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
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. //
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: //
22 // http://www.gnu.org/copyleft/gpl.html //
24 ///////////////////////////////////////////////////////////////////////////
27 * Library of functions for web output
29 * Library of all general-purpose Moodle PHP functions and constants
30 * that produce HTML output
32 * Other main libraries:
33 * - datalib.php - functions that access the database.
34 * - moodlelib.php - general-purpose Moodle functions.
35 * @author Martin Dougiamas
37 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
41 /// We are going to uses filterlib functions here
42 require_once("$CFG->libdir/filterlib.php");
46 /// Define text formatting types ... eventually we can add Wiki, BBcode etc
49 * Does all sorts of transformations and filtering
51 define('FORMAT_MOODLE', '0'); // Does all sorts of transformations and filtering
54 * Plain HTML (with some tags stripped)
56 define('FORMAT_HTML', '1'); // Plain HTML (with some tags stripped)
59 * Plain text (even tags are printed in full)
61 define('FORMAT_PLAIN', '2'); // Plain text (even tags are printed in full)
65 * Deprecated: left here just to note that '3' is not used (at the moment)
66 * and to catch any latent wiki-like text (which generates an error)
68 define('FORMAT_WIKI', '3'); // Wiki-formatted text
71 * Markdown-formatted text http://daringfireball.net/projects/markdown/
73 define('FORMAT_MARKDOWN', '4'); // Markdown-formatted text http://daringfireball.net/projects/markdown/
77 * Allowed tags - string of html tags that can be tested against for safe html tags
78 * @global string $ALLOWED_TAGS
81 '<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><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>';
84 * Allowed protocols - array of protocols that are safe to use in links and so on
85 * @global string $ALLOWED_PROTOCOLS
87 $ALLOWED_PROTOCOLS = array('http', 'https', 'ftp', 'news', 'mailto', 'rtsp', 'teamspeak', 'gopher', 'mms',
88 'color', 'callto', 'cursor', 'text-align', 'font-size', 'font-weight', 'font-style',
89 'border', 'margin', 'padding', 'background'); // CSS as well to get through kses
95 * Add quotes to HTML characters
97 * Returns $var with HTML characters (like "<", ">", etc.) properly quoted.
98 * This function is very similar to {@link p()}
100 * @param string $var the string potentially containing HTML characters
101 * @param boolean $strip to decide if we want to strip slashes or no. Default to false.
102 * true should be used to print data from forms and false for data from DB.
105 function s($var, $strip=false) {
107 if ($var == '0') { // for integer 0, boolean false, string '0'
112 return preg_replace("/&(#\d+);/i", "&$1;", htmlspecialchars(stripslashes_safe($var)));
114 return preg_replace("/&(#\d+);/i", "&$1;", htmlspecialchars($var));
119 * Add quotes to HTML characters
121 * Prints $var with HTML characters (like "<", ">", etc.) properly quoted.
122 * This function is very similar to {@link s()}
124 * @param string $var the string potentially containing HTML characters
125 * @param boolean $strip to decide if we want to strip slashes or no. Default to false.
126 * true should be used to print data from forms and false for data from DB.
129 function p($var, $strip=false) {
130 echo s($var, $strip);
135 * Ensure that a variable is set
137 * Return $var if it is defined, otherwise return $default,
138 * This function is very similar to {@link optional_variable()}
140 * @param mixed $var the variable which may be unset
141 * @param mixed $default the value to return if $var is unset
144 function nvl(&$var, $default='') {
147 if (!empty($CFG->disableglobalshack
)) {
148 error( "The nvl() function is deprecated ($var, $default)." );
150 return isset($var) ?
$var : $default;
154 * Remove query string from url
156 * Takes in a URL and returns it without the querystring portion
158 * @param string $url the url which may have a query string attached
161 function strip_querystring($url) {
163 if ($commapos = strpos($url, '?')) {
164 return substr($url, 0, $commapos);
171 * Returns the URL of the HTTP_REFERER, less the querystring portion
174 function get_referer() {
176 return strip_querystring(nvl($_SERVER['HTTP_REFERER']));
181 * Returns the name of the current script, WITH the querystring portion.
182 * this function is necessary because PHP_SELF and REQUEST_URI and SCRIPT_NAME
183 * return different things depending on a lot of things like your OS, Web
184 * server, and the way PHP is compiled (ie. as a CGI, module, ISAPI, etc.)
185 * <b>NOTE:</b> This function returns false if the global variables needed are not set.
191 if (!empty($_SERVER['REQUEST_URI'])) {
192 return $_SERVER['REQUEST_URI'];
194 } else if (!empty($_SERVER['PHP_SELF'])) {
195 if (!empty($_SERVER['QUERY_STRING'])) {
196 return $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING'];
198 return $_SERVER['PHP_SELF'];
200 } else if (!empty($_SERVER['SCRIPT_NAME'])) {
201 if (!empty($_SERVER['QUERY_STRING'])) {
202 return $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING'];
204 return $_SERVER['SCRIPT_NAME'];
206 } else if (!empty($_SERVER['URL'])) { // May help IIS (not well tested)
207 if (!empty($_SERVER['QUERY_STRING'])) {
208 return $_SERVER['URL'] .'?'. $_SERVER['QUERY_STRING'];
210 return $_SERVER['URL'];
213 notify('Warning: Could not find any of these web server variables: $REQUEST_URI, $PHP_SELF, $SCRIPT_NAME or $URL');
219 * Like {@link me()} but returns a full URL
223 function qualified_me() {
227 if (!empty($CFG->wwwroot
)) {
228 $url = parse_url($CFG->wwwroot
);
231 if (!empty($url['host'])) {
232 $hostname = $url['host'];
233 } else if (!empty($_SERVER['SERVER_NAME'])) {
234 $hostname = $_SERVER['SERVER_NAME'];
235 } else if (!empty($_ENV['SERVER_NAME'])) {
236 $hostname = $_ENV['SERVER_NAME'];
237 } else if (!empty($_SERVER['HTTP_HOST'])) {
238 $hostname = $_SERVER['HTTP_HOST'];
239 } else if (!empty($_ENV['HTTP_HOST'])) {
240 $hostname = $_ENV['HTTP_HOST'];
242 notify('Warning: could not find the name of this server!');
246 if (!empty($url['port'])) {
247 $hostname .= ':'.$url['port'];
248 } else if (!empty($_SERVER['SERVER_PORT'])) {
249 if ($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
250 $hostname .= ':'.$_SERVER['SERVER_PORT'];
254 if (isset($_SERVER['HTTPS'])) {
255 $protocol = ($_SERVER['HTTPS'] == 'on') ?
'https://' : 'http://';
256 } else if (isset($_SERVER['SERVER_PORT'])) { # Apache2 does not export $_SERVER['HTTPS']
257 $protocol = ($_SERVER['SERVER_PORT'] == '443') ?
'https://' : 'http://';
259 $protocol = 'http://';
262 $url_prefix = $protocol.$hostname;
263 return $url_prefix . me();
267 * Determine if a web referer is valid
269 * Returns true if the referer is the same as the goodreferer. If
270 * the referer to test is not specified, use {@link qualified_me()}.
271 * If the admin has not set secure forms ($CFG->secureforms) then
272 * this function returns true regardless of a match.
275 * @param string $goodreferer the url to compare to referer
278 function match_referer($goodreferer = '') {
281 if (empty($CFG->secureforms
)) { // Don't bother checking referer
285 if ($goodreferer == 'nomatch') { // Don't bother checking referer
289 if (empty($goodreferer)) {
290 $goodreferer = qualified_me();
291 // try to remove everything after ? because POST url may contain GET parameters (SID rewrite, etc.)
292 $pos = strpos($goodreferer, '?');
293 if ($pos !== FALSE) {
294 $goodreferer = substr($goodreferer, 0, $pos);
298 $referer = get_referer();
300 return (($referer == $goodreferer) or ($referer == $CFG->wwwroot
.'/') or ($referer == $CFG->wwwroot
.'/index.php'));
304 * Determine if there is data waiting to be processed from a form
306 * Used on most forms in Moodle to check for data
307 * Returns the data as an object, if it's found.
308 * This object can be used in foreach loops without
309 * casting because it's cast to (array) automatically
311 * Checks that submitted POST data exists, and also
312 * checks the referer against the given url (it uses
313 * the current page if none was specified.
316 * @param string $url the url to compare to referer for secure forms
319 function data_submitted($url='') {
328 if (match_referer($url)) {
329 return (object)$_POST;
331 if ($CFG->debug
> 10) {
332 notice('The form did not come from this page! (referer = '. get_referer() .')');
340 * Moodle replacement for php stripslashes() function,
341 * works also for objects and arrays.
343 * The standard php stripslashes() removes ALL backslashes
344 * even from strings - so C:\temp becomes C:temp - this isn't good.
345 * This function should work as a fairly safe replacement
346 * to be called on quoted AND unquoted strings (to be sure)
348 * @param mixed something to remove unsafe slashes from
351 function stripslashes_safe($mixed) {
352 // there is no need to remove slashes from int, float and bool types
355 } else if (is_string($mixed)) {
356 $mixed = str_replace("\\'", "'", $mixed);
357 $mixed = str_replace('\\"', '"', $mixed);
358 $mixed = str_replace('\\\\', '\\', $mixed);
359 } else if (is_array($mixed)) {
360 foreach ($mixed as $key => $value) {
361 $mixed[$key] = stripslashes_safe($value);
363 } else if (is_object($mixed)) {
364 $vars = get_object_vars($mixed);
365 foreach ($vars as $key => $value) {
366 $mixed->$key = stripslashes_safe($value);
374 * Recursive implementation of stripslashes()
376 * This function will allow you to strip the slashes from a variable.
377 * If the variable is an array or object, slashes will be stripped
378 * from the items (or properties) it contains, even if they are arrays
379 * or objects themselves.
381 * @param mixed the variable to remove slashes from
384 function stripslashes_recursive($var) {
385 if(is_object($var)) {
386 $properties = get_object_vars($var);
387 foreach($properties as $property => $value) {
388 $var->$property = stripslashes_recursive($value);
391 else if(is_array($var)) {
392 foreach($var as $property => $value) {
393 $var[$property] = stripslashes_recursive($value);
396 else if(is_string($var)) {
397 $var = stripslashes($var);
403 * Given some normal text this function will break up any
404 * long words to a given size by inserting the given character
406 * It's multibyte savvy and doesn't change anything inside html tags.
408 * @param string $string the string to be modified
409 * @param int $maxsize maximum length of the string to be returned
410 * @param string $cutchar the string used to represent word breaks
413 function break_up_long_words($string, $maxsize=20, $cutchar=' ') {
415 /// Loading the textlib singleton instance. We are going to need it.
416 $textlib = textlib_get_instance();
418 /// First of all, save all the tags inside the text to skip them
420 filter_save_tags($string,$tags);
422 /// Process the string adding the cut when necessary
424 $length = $textlib->strlen($string, current_charset());
427 for ($i=0; $i<$length; $i++
) {
428 $char = $textlib->substr($string, $i, 1, current_charset());
429 if ($char == ' ' or $char == "\t" or $char == "\n" or $char == "\r" or $char == "<" or $char == ">") {
433 if ($wordlength > $maxsize) {
441 /// Finally load the tags back again
443 $output = str_replace(array_keys($tags), $tags, $output);
450 * This does a search and replace, ignoring case
451 * This function is only used for versions of PHP older than version 5
452 * which do not have a native version of this function.
453 * Taken from the PHP manual, by bradhuizenga @ softhome.net
455 * @param string $find the string to search for
456 * @param string $replace the string to replace $find with
457 * @param string $string the string to search through
460 if (!function_exists('str_ireplace')) { /// Only exists in PHP 5
461 function str_ireplace($find, $replace, $string) {
463 if (!is_array($find)) {
464 $find = array($find);
467 if(!is_array($replace)) {
468 if (!is_array($find)) {
469 $replace = array($replace);
471 // this will duplicate the string into an array the size of $find
475 for ($i = 0; $i < $c; $i++
) {
476 $replace[$i] = $rString;
481 foreach ($find as $fKey => $fItem) {
482 $between = explode(strtolower($fItem),strtolower($string));
484 foreach($between as $bKey => $bItem) {
485 $between[$bKey] = substr($string,$pos,strlen($bItem));
486 $pos +
= strlen($bItem) +
strlen($fItem);
488 $string = implode($replace[$fKey],$between);
495 * Locate the position of a string in another string
497 * This function is only used for versions of PHP older than version 5
498 * which do not have a native version of this function.
499 * Taken from the PHP manual, by dmarsh @ spscc.ctc.edu
501 * @param string $haystack The string to be searched
502 * @param string $needle The string to search for
503 * @param int $offset The position in $haystack where the search should begin.
505 if (!function_exists('stripos')) { /// Only exists in PHP 5
506 function stripos($haystack, $needle, $offset=0) {
508 return strpos(strtoupper($haystack), strtoupper($needle), $offset);
513 * Load a template from file
515 * Returns a (big) string containing the contents of a template file with all
516 * the variables interpolated. all the variables must be in the $var[] array or
517 * object (whatever you decide to use).
519 * <b>WARNING: do not use this on big files!!</b>
521 * @param string $filename Location on the server's filesystem where template can be found.
522 * @param mixed $var Passed in by reference. An array or object which will be loaded with data from the template file.
524 function read_template($filename, &$var) {
526 $temp = str_replace("\\", "\\\\", implode(file($filename), ''));
527 $temp = str_replace('"', '\"', $temp);
528 eval("\$template = \"$temp\";");
533 * Set a variable's value depending on whether or not it already has a value.
535 * If variable is set, set it to the set_value otherwise set it to the
536 * unset_value. used to handle checkboxes when you are expecting them from
539 * @param mixed $var Passed in by reference. The variable to check.
540 * @param mixed $set_value The value to set $var to if $var already has a value.
541 * @param mixed $unset_value The value to set $var to if $var does not already have a value.
543 function checked(&$var, $set_value = 1, $unset_value = 0) {
553 * Prints the word "checked" if a variable is true, otherwise prints nothing,
554 * used for printing the word "checked" in a checkbox form element.
556 * @param boolean $var Variable to be checked for true value
557 * @param string $true_value Value to be printed if $var is true
558 * @param string $false_value Value to be printed if $var is false
560 function frmchecked(&$var, $true_value = 'checked', $false_value = '') {
570 * This function will create a HTML link that will work on both
571 * Javascript and non-javascript browsers.
572 * Relies on the Javascript function openpopup in javascript.php
574 * $url must be relative to home page eg /mod/survey/stuff.php
575 * @param string $url Web link relative to home page
576 * @param string $name Name to be assigned to the popup window
577 * @param string $linkname Text to be displayed as web link
578 * @param int $height Height to assign to popup window
579 * @param int $width Height to assign to popup window
580 * @param string $title Text to be displayed as popup page title
581 * @param string $options List of additional options for popup window
582 * @todo Add code examples and list of some options that might be used.
583 * @param boolean $return Should the link to the popup window be returned as a string (true) or printed immediately (false)?
587 function link_to_popup_window ($url, $name='popup', $linkname='click here',
588 $height=400, $width=500, $title='Popup window', $options='none', $return=false) {
592 if ($options == 'none') {
593 $options = 'menubar=0,location=0,scrollbars,resizable,width='. $width .',height='. $height;
597 if (!(strpos($url,$CFG->wwwroot
) === false)) { // some log url entries contain _SERVER[HTTP_REFERRER] in which case wwwroot is already there.
598 $url = substr($url, strlen($CFG->wwwroot
));
601 $link = '<a target="'. $name .'" title="'. $title .'" href="'. $CFG->wwwroot
. $url .'" '.
602 "onclick=\"return openpopup('$url', '$name', '$options', $fullscreen);\">$linkname</a>";
611 * This function will print a button submit form element
612 * that will work on both Javascript and non-javascript browsers.
613 * Relies on the Javascript function openpopup in javascript.php
615 * $url must be relative to home page eg /mod/survey/stuff.php
616 * @param string $url Web link relative to home page
617 * @param string $name Name to be assigned to the popup window
618 * @param string $linkname Text to be displayed as web link
619 * @param int $height Height to assign to popup window
620 * @param int $width Height to assign to popup window
621 * @param string $title Text to be displayed as popup page title
622 * @param string $options List of additional options for popup window
623 * @param string $return If true, return as a string, otherwise print
627 function button_to_popup_window ($url, $name='popup', $linkname='click here',
628 $height=400, $width=500, $title='Popup window', $options='none', $return=false,
633 if ($options == 'none') {
634 $options = 'menubar=0,location=0,scrollbars,resizable,width='. $width .',height='. $height;
638 $id = ' id="'.$id.'" ';
641 $class = ' class="'.$class.'" ';
645 $button = '<input type="button" name="'.$name.'" title="'. $title .'" value="'. $linkname .' ..." '.$id.$class.
646 "onclick=\"return openpopup('$url', '$name', '$options', $fullscreen);\" />\n";
656 * Prints a simple button to close a window
658 function close_window_button($name='closewindow') {
660 echo '<center>' . "\n";
661 echo '<script type="text/javascript">' . "\n";
663 echo "document.write('<form>');\n";
664 echo "document.write('<input type=\"button\" onclick=\"self.close();\" value=\"".get_string("closewindow")."\" />');\n";
665 echo "document.write('<\/form>');\n";
667 echo '</script>' . "\n";
668 echo '<noscript>' . "\n";
670 echo '</noscript>' . "\n";
671 echo '</center>' . "\n";
675 * Try and close the current window immediately using Javascript
677 function close_window($delay=0) {
679 <script type
="text/javascript">
681 function close_this_window() {
684 setTimeout("close_this_window()", <?php
echo $delay * 1000 ?
>);
688 <?php
print_string('pleaseclose') ?
>
696 * Given an array of value, creates a popup menu to be part of a form
697 * $options["value"]["label"]
699 * @param type description
700 * @todo Finish documenting this function
702 function choose_from_menu ($options, $name, $selected='', $nothing='choose', $script='',
703 $nothingvalue='0', $return=false, $disabled=false, $tabindex=0) {
705 if ($nothing == 'choose') {
706 $nothing = get_string('choose') .'...';
709 $attributes = ($script) ?
'onchange="'. $script .'"' : '';
711 $attributes .= ' disabled="disabled"';
715 $attributes .= ' tabindex="'.$tabindex.'"';
718 $output = '<select id="menu'.$name.'" name="'. $name .'" '. $attributes .'>' . "\n";
720 $output .= ' <option value="'. $nothingvalue .'"'. "\n";
721 if ($nothingvalue === $selected) {
722 $output .= ' selected="selected"';
724 $output .= '>'. $nothing .'</option>' . "\n";
726 if (!empty($options)) {
727 foreach ($options as $value => $label) {
728 $output .= ' <option value="'. $value .'"';
729 if ((string)$value == (string)$selected) {
730 $output .= ' selected="selected"';
733 $output .= '>'. $value .'</option>' . "\n";
735 $output .= '>'. $label .'</option>' . "\n";
739 $output .= '</select>' . "\n";
749 * Just like choose_from_menu, but takes a nested array (2 levels) and makes a dropdown menu
750 * including option headings with the first level.
752 function choose_from_menu_nested($options,$name,$selected='',$nothing='choose',$script = '',
753 $nothingvalue=0,$return=false,$disabled=false,$tabindex=0) {
755 if ($nothing == 'choose') {
756 $nothing = get_string('choose') .'...';
759 $attributes = ($script) ?
'onchange="'. $script .'"' : '';
761 $attributes .= ' disabled="disabled"';
765 $attributes .= ' tabindex="'.$tabindex.'"';
768 $output = '<select id="menu'.$name.'" name="'. $name .'" '. $attributes .'>' . "\n";
770 $output .= ' <option value="'. $nothingvalue .'"'. "\n";
771 if ($nothingvalue === $selected) {
772 $output .= ' selected="selected"';
774 $output .= '>'. $nothing .'</option>' . "\n";
776 if (!empty($options)) {
777 foreach ($options as $section => $values) {
778 $output .= ' <optgroup label="'.$section.'">'."\n";
779 foreach ($values as $value => $label) {
780 $output .= ' <option value="'. $value .'"';
781 if ((string)$value == (string)$selected) {
782 $output .= ' selected="selected"';
785 $output .= '>'. $value .'</option>' . "\n";
787 $output .= '>'. $label .'</option>' . "\n";
790 $output .= ' </optgroup>'."\n";
793 $output .= '</select>' . "\n";
804 * Given an array of values, creates a group of radio buttons to be part of a form
806 * @param array $options An array of value-label pairs for the radio group (values as keys)
807 * @param string $name Name of the radiogroup (unique in the form)
808 * @param string $checked The value that is already checked
810 function choose_from_radio ($options, $name, $checked='') {
812 static $idcounter = 0;
818 $output = '<span class="radiogroup '.$name."\">\n";
820 if (!empty($options)) {
822 foreach ($options as $value => $label) {
823 $htmlid = 'auto-rb'.sprintf('%04d', ++
$idcounter);
824 $output .= ' <span class="radioelement '.$name.' rb'.$currentradio."\">";
825 $output .= '<input name="'.$name.'" id="'.$htmlid.'" type="radio" value="'.$value.'"';
826 if ($value == $checked) {
827 $output .= ' checked="checked"';
830 $output .= ' /> <label for="'.$htmlid.'">'. $value .'</label></span>' . "\n";
832 $output .= ' /> <label for="'.$htmlid.'">'. $label .'</label></span>' . "\n";
834 $currentradio = ($currentradio +
1) %
2;
838 $output .= '</span>' . "\n";
843 /** Display an standard html checkbox with an optional label
845 * @param string $name The name of the checkbox
846 * @param string $value The valus that the checkbox will pass when checked
847 * @param boolean $checked The flag to tell the checkbox initial state
848 * @param string $label The label to be showed near the checkbox
849 * @param string $alt The info to be inserted in the alt tag
851 function print_checkbox ($name, $value, $checked = true, $label = '', $alt = '', $script='',$return=false) {
853 static $idcounter = 0;
864 $strchecked = ' checked="checked"';
869 $htmlid = 'auto-cb'.sprintf('%04d', ++
$idcounter);
870 $output = '<span class="checkbox '.$name."\">";
871 $output .= '<input name="'.$name.'" id="'.$htmlid.'" type="checkbox" value="'.$value.'" alt="'.$alt.'"'.$strchecked.' '.((!empty($script)) ?
' onClick="'.$script.'" ' : '').' />';
873 $output .= ' <label for="'.$htmlid.'">'.$label.'</label>';
875 $output .= '</span>'."\n";
877 if (empty($return)) {
885 /** Display an standard html text field with an optional label
887 * @param string $name The name of the text field
888 * @param string $value The value of the text field
889 * @param string $label The label to be showed near the text field
890 * @param string $alt The info to be inserted in the alt tag
892 function print_textfield ($name, $value, $alt = '',$size=50,$maxlength= 0,$return=false) {
894 static $idcounter = 0;
904 if (!empty($maxlength)) {
905 $maxlength = ' maxlength="'.$maxlength.'" ';
908 $htmlid = 'auto-tf'.sprintf('%04d', ++
$idcounter);
909 $output = '<span class="textfield '.$name."\">";
910 $output .= '<input name="'.$name.'" id="'.$htmlid.'" type="text" value="'.$value.'" size="'.$size.'" '.$maxlength.' alt="'.$alt.'" />';
912 $output .= '</span>'."\n";
914 if (empty($return)) {
924 * Implements a complete little popup form
927 * @param string $common The URL up to the point of the variable that changes
928 * @param array $options Alist of value-label pairs for the popup list
929 * @param string $formname Name must be unique on the page
930 * @param string $selected The option that is already selected
931 * @param string $nothing The label for the "no choice" option
932 * @param string $help The name of a help page if help is required
933 * @param string $helptext The name of the label for the help button
934 * @param boolean $return Indicates whether the function should return the text
935 * as a string or echo it directly to the page being rendered
936 * @param string $targetwindow The name of the target page to open the linked page in.
937 * @return string If $return is true then the entire form is returned as a string.
938 * @todo Finish documenting this function<br>
940 function popup_form($common, $options, $formname, $selected='', $nothing='choose', $help='', $helptext='', $return=false, $targetwindow='self') {
943 static $go, $choose; /// Locally cached, in case there's lots on a page
945 if (empty($options)) {
950 $go = get_string('go');
953 if ($nothing == 'choose') {
954 if (!isset($choose)) {
955 $choose = get_string('choose');
957 $nothing = $choose.'...';
960 $startoutput = '<form action="'.$CFG->wwwroot
.'/course/jumpto.php"'.
962 ' target="'.$CFG->framename
.'"'.
963 ' name="'.$formname.'"'.
964 ' class="popupform">';
966 $output = '<select name="jump" onchange="'.$targetwindow.'.location=document.'.$formname.
967 '.jump.options[document.'.$formname.'.jump.selectedIndex].value;">'."\n";
969 if ($nothing != '') {
970 $output .= " <option value=\"javascript:void(0)\">$nothing</option>\n";
974 foreach ($options as $value => $label) {
976 if (substr($label,0,2) == '--') { /// we are starting a new optgroup
978 /// Check to see if we already have a valid open optgroup
979 /// XHTML demands that there be at least 1 option within an optgroup
980 if ($inoptgroup and (count($optgr) > 1) ) {
981 $output .= implode('', $optgr);
982 $output .= ' </optgroup>';
988 $optgr[] = ' <optgroup label="'. substr($label,2) .'">'; // Plain labels
990 $inoptgroup = true; /// everything following will be in an optgroup
994 if (!empty($CFG->usesid
) && !isset($_COOKIE[session_name()]))
996 $url=sid_process_url( $common . $value );
999 $url=$common . $value;
1001 $optstr = ' <option value="' . $url . '"';
1003 if ($value == $selected) {
1004 $optstr .= ' selected="selected"';
1008 $optstr .= '>'. $label .'</option>' . "\n";
1010 $optstr .= '>'. $value .'</option>' . "\n";
1022 /// catch the final group if not closed
1023 if ($inoptgroup and count($optgr) > 1) {
1024 $output .= implode('', $optgr);
1025 $output .= ' </optgroup>';
1028 $output .= '</select>';
1029 $output .= '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1030 $output .= '<noscript id="noscript'.$formname.'" style="display: inline;">';
1031 $output .= '<input type="submit" value="'.$go.'" /></noscript>';
1032 $output .= '<script type="text/javascript">'.
1034 'document.getElementById("noscript'.$formname.'").style.display = "none";'.
1035 "\n-->\n".'</script>';
1036 $output .= '</form>' . "\n";
1039 $button = helpbutton($help, $helptext, 'moodle', true, false, '', true);
1045 return $startoutput.$button.$output;
1047 echo $startoutput.$button.$output;
1053 * Prints some red text
1055 * @param string $error The text to be displayed in red
1057 function formerr($error) {
1059 if (!empty($error)) {
1060 echo '<font color="#ff0000">'. $error .'</font>';
1065 * Validates an email to make sure it makes sense.
1067 * @param string $address The email address to validate.
1070 function validate_email($address) {
1072 return (ereg('^[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+'.
1073 '(\.[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+)*'.
1075 '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.
1076 '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$',
1081 * Extracts file argument either from file parameter or PATH_INFO
1083 * @param string $scriptname name of the calling script
1084 * @return string file path (only safe characters)
1086 function get_file_argument($scriptname) {
1089 $relativepath = FALSE;
1091 // first try normal parameter (compatible method == no relative links!)
1092 $relativepath = optional_param('file', FALSE, PARAM_PATH
);
1093 if ($relativepath === '/testslasharguments') {
1094 echo 'test -1 : Incorrect use - try "file.php/testslasharguments" instead'; //indicate fopen/fread works for health center
1098 // then try extract file from PATH_INFO (slasharguments method)
1099 if (!$relativepath and !empty($_SERVER['PATH_INFO'])) {
1100 $path_info = $_SERVER['PATH_INFO'];
1101 // check that PATH_INFO works == must not contain the script name
1102 if (!strpos($path_info, $scriptname)) {
1103 $relativepath = clean_param(rawurldecode($path_info), PARAM_PATH
);
1104 if ($relativepath === '/testslasharguments') {
1105 echo 'test 1 : Slasharguments test passed. Server confguration is compatible with file.php/1/pic.jpg slashargument setting.'; //indicate ok for health center
1111 // now if both fail try the old way
1112 // (for compatibility with misconfigured or older buggy php implementations)
1113 if (!$relativepath) {
1114 $arr = explode($scriptname, me());
1115 if (!empty($arr[1])) {
1116 $path_info = strip_querystring($arr[1]);
1117 $relativepath = clean_param(rawurldecode($path_info), PARAM_PATH
);
1118 if ($relativepath === '/testslasharguments') {
1119 echo 'test 2 : Slasharguments test passed (compatibility hack). Server confguration may be compatible with file.php/1/pic.jpg slashargument setting'; //indicate ok for health center
1125 return $relativepath;
1129 * Check for bad characters ?
1131 * @param string $string ?
1132 * @param int $allowdots ?
1133 * @todo Finish documenting this function - more detail needed in description as well as details on arguments
1135 function detect_munged_arguments($string, $allowdots=1) {
1136 if (substr_count($string, '..') > $allowdots) { // Sometimes we allow dots in references
1139 if (ereg('[\|\`]', $string)) { // check for other bad characters
1142 if (empty($string) or $string == '/') {
1150 * Searches the current environment variables for some slash arguments
1152 * @param string $file ?
1153 * @todo Finish documenting this function
1155 function get_slash_arguments($file='file.php') {
1157 if (!$string = me()) {
1161 $pathinfo = explode($file, $string);
1163 if (!empty($pathinfo[1])) {
1164 return addslashes($pathinfo[1]);
1171 * Extracts arguments from "/foo/bar/something"
1172 * eg http://mysite.com/script.php/foo/bar/something
1174 * @param string $string ?
1176 * @return array|string
1177 * @todo Finish documenting this function
1179 function parse_slash_arguments($string, $i=0) {
1181 if (detect_munged_arguments($string)) {
1184 $args = explode('/', $string);
1186 if ($i) { // return just the required argument
1189 } else { // return the whole array
1190 array_shift($args); // get rid of the empty first one
1196 * Just returns an array of text formats suitable for a popup menu
1198 * @uses FORMAT_MOODLE
1200 * @uses FORMAT_PLAIN
1201 * @uses FORMAT_MARKDOWN
1204 function format_text_menu() {
1206 return array (FORMAT_MOODLE
=> get_string('formattext'),
1207 FORMAT_HTML
=> get_string('formathtml'),
1208 FORMAT_PLAIN
=> get_string('formatplain'),
1209 FORMAT_MARKDOWN
=> get_string('formatmarkdown'));
1213 * Given text in a variety of format codings, this function returns
1214 * the text as safe HTML.
1217 * @uses FORMAT_MOODLE
1219 * @uses FORMAT_PLAIN
1221 * @uses FORMAT_MARKDOWN
1222 * @param string $text The text to be formatted. This is raw text originally from user input.
1223 * @param int $format Identifier of the text format to be used
1224 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
1225 * @param array $options ?
1226 * @param int $courseid ?
1228 * @todo Finish documenting this function
1230 function format_text($text, $format=FORMAT_MOODLE
, $options=NULL, $courseid=NULL ) {
1232 global $CFG, $course;
1234 if (!isset($options->noclean
)) {
1235 $options->noclean
=false;
1237 if (!isset($options->smiley
)) {
1238 $options->smiley
=true;
1240 if (!isset($options->filter
)) {
1241 $options->filter
=true;
1243 if (!isset($options->para
)) {
1244 $options->para
=true;
1246 if (!isset($options->newlines
)) {
1247 $options->newlines
=true;
1250 if (empty($courseid)) {
1251 if (!empty($course->id
)) { // An ugly hack for better compatibility
1252 $courseid = $course->id
;
1256 if (!empty($CFG->cachetext
)) {
1257 $time = time() - $CFG->cachetext
;
1258 $md5key = md5($text.'-'.$courseid.$options->noclean
.$options->smiley
.$options->filter
.$options->para
.$options->newlines
.$format.current_language().$courseid);
1259 if ($oldcacheitem = get_record_sql('SELECT * FROM '.$CFG->prefix
.'cache_text WHERE md5key = \''.$md5key.'\'', true)) {
1260 if ($oldcacheitem->timemodified
>= $time) {
1261 return $oldcacheitem->formattedtext
;
1266 $CFG->currenttextiscacheable
= true; // Default status - can be changed by any filter
1270 if (!empty($options->smiley
)) {
1271 replace_smilies($text);
1273 if (empty($options->noclean
)) {
1274 $text = clean_text($text, $format);
1276 if (!empty($options->filter
)) {
1277 $text = filter_text($text, $courseid);
1283 $text = rebuildnolinktag($text);
1284 $text = str_replace(' ', ' ', $text);
1285 $text = nl2br($text);
1289 // this format is deprecated
1290 $text = '<p>NOTICE: Wiki-like formatting has been removed from Moodle. You should not be seeing
1291 this message as all texts should have been converted to Markdown format instead.
1292 Please post a bug report to http://moodle.org/bugs with information about where you
1293 saw this message.</p>'.s($text);
1296 case FORMAT_MARKDOWN
:
1297 $text = markdown_to_html($text);
1298 if (!empty($options->smiley
)) {
1299 replace_smilies($text);
1301 if (empty($options->noclean
)) {
1302 $text = clean_text($text, $format);
1305 if (!empty($options->filter
)) {
1306 $text = filter_text($text, $courseid);
1310 default: // FORMAT_MOODLE or anything else
1311 $text = text_to_html($text, $options->smiley
, $options->para
, $options->newlines
);
1312 if (empty($options->noclean
)) {
1313 $text = clean_text($text, $format);
1316 if (!empty($options->filter
)) {
1317 $text = filter_text($text, $courseid);
1322 if (!empty($CFG->cachetext
) and $CFG->currenttextiscacheable
) {
1323 $newcacheitem->md5key
= $md5key;
1324 $newcacheitem->formattedtext
= addslashes($text);
1325 $newcacheitem->timemodified
= time();
1326 if ($oldcacheitem) { // See bug 4677 for discussion
1327 $newcacheitem->id
= $oldcacheitem->id
;
1328 @update_record
('cache_text', $newcacheitem); // Update existing record in the cache table
1329 // It's unlikely that the cron cache cleaner could have
1330 // deleted this entry in the meantime, as it allows
1331 // some extra time to cover these cases.
1333 @insert_record
('cache_text', $newcacheitem); // Insert a new record in the cache table
1334 // Again, it's possible that another user has caused this
1335 // record to be created already in the time that it took
1336 // to traverse this function. That's OK too, as the
1337 // call above handles duplicate entries, and eventually
1338 // the cron cleaner will delete them.
1345 /** Converts the text format from the value to the 'internal'
1346 * name or vice versa. $key can either be the value or the name
1347 * and you get the other back.
1349 * @param mixed int 0-4 or string one of 'moodle','html','plain','markdown'
1350 * @return mixed as above but the other way around!
1352 function text_format_name( $key ) {
1354 $lookup[FORMAT_MOODLE
] = 'moodle';
1355 $lookup[FORMAT_HTML
] = 'html';
1356 $lookup[FORMAT_PLAIN
] = 'plain';
1357 $lookup[FORMAT_MARKDOWN
] = 'markdown';
1359 if (!is_numeric($key)) {
1360 $key = strtolower( $key );
1361 $value = array_search( $key, $lookup );
1364 if (isset( $lookup[$key] )) {
1365 $value = $lookup[ $key ];
1371 /** Given a simple string, this function returns the string
1372 * processed by enabled filters if $CFG->filterall is enabled
1374 * @param string $string The string to be filtered.
1375 * @param boolean $striplinks To strip any link in the result text.
1376 * @param int $courseid Current course as filters can, potentially, use it
1379 function format_string ($string, $striplinks = false, $courseid=NULL ) {
1381 global $CFG, $course;
1383 //We'll use a in-memory cache here to speed up repeated strings
1387 $md5 = md5($string.'<+>'.$striplinks);
1389 //Fetch from cache if possible
1390 if(isset($strcache[$md5])) {
1391 return $strcache[$md5];
1394 if (empty($courseid)) {
1395 if (!empty($course->id
)) { // An ugly hack for better compatibility
1396 $courseid = $course->id
; // (copied from format_text)
1400 if (!empty($CFG->filterall
)) {
1401 $string = filter_text($string, $courseid);
1404 if ($striplinks) { //strip links in string
1405 $string = preg_replace('/(<a[^>]+?>)(.+?)(<\/a>)/is','$2',$string);
1409 $strcache[$md5] = $string;
1415 * Given text in a variety of format codings, this function returns
1416 * the text as plain text suitable for plain email.
1418 * @uses FORMAT_MOODLE
1420 * @uses FORMAT_PLAIN
1422 * @uses FORMAT_MARKDOWN
1423 * @param string $text The text to be formatted. This is raw text originally from user input.
1424 * @param int $format Identifier of the text format to be used
1425 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
1428 function format_text_email($text, $format) {
1437 $text = wiki_to_html($text);
1438 /// This expression turns links into something nice in a text format. (Russell Jungwirth)
1439 /// From: http://php.net/manual/en/function.eregi-replace.php and simplified
1440 $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [ \\2 ]', $text);
1441 return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES
)));
1445 return html_to_text($text);
1449 case FORMAT_MARKDOWN
:
1451 $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [ \\2 ]', $text);
1452 return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES
)));
1458 * Given some text in HTML format, this function will pass it
1459 * through any filters that have been defined in $CFG->textfilterx
1460 * The variable defines a filepath to a file containing the
1461 * filter function. The file must contain a variable called
1462 * $textfilter_function which contains the name of the function
1463 * with $courseid and $text parameters
1465 * @param string $text The text to be passed through format filters
1466 * @param int $courseid ?
1468 * @todo Finish documenting this function
1470 function filter_text($text, $courseid=NULL) {
1474 require_once($CFG->libdir
.'/filterlib.php');
1475 if (!empty($CFG->textfilters
)) {
1476 $textfilters = explode(',', $CFG->textfilters
);
1477 foreach ($textfilters as $textfilter) {
1478 if (is_readable($CFG->dirroot
.'/'. $textfilter .'/filter.php')) {
1479 include_once($CFG->dirroot
.'/'. $textfilter .'/filter.php');
1480 $functionname = basename($textfilter).'_filter';
1481 if (function_exists($functionname)) {
1482 $text = $functionname($courseid, $text);
1488 /// <nolink> tags removed for XHTML compatibility
1489 $text = str_replace('<nolink>', '', $text);
1490 $text = str_replace('</nolink>', '', $text);
1496 * Given raw text (eg typed in by a user), this function cleans it up
1497 * and removes any nasty tags that could mess up Moodle pages.
1499 * @uses FORMAT_MOODLE
1500 * @uses FORMAT_PLAIN
1501 * @uses ALLOWED_TAGS
1502 * @param string $text The text to be cleaned
1503 * @param int $format Identifier of the text format to be used
1504 * (FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_WIKI, FORMAT_MARKDOWN)
1505 * @return string The cleaned up text
1507 function clean_text($text, $format=FORMAT_MOODLE
) {
1509 global $ALLOWED_TAGS;
1517 /// Fix non standard entity notations
1518 $text = preg_replace('/(&#[0-9]+)(;?)/', "\\1;", $text);
1519 $text = preg_replace('/(&#x[0-9a-fA-F]+)(;?)/', "\\1;", $text);
1521 /// Remove tags that are not allowed
1522 $text = strip_tags($text, $ALLOWED_TAGS);
1524 /// Clean up embedded scripts and , using kses
1525 $text = cleanAttributes($text);
1527 /// Remove script events
1528 $text = eregi_replace("([^a-z])language([[:space:]]*)=", "\\1Xlanguage=", $text);
1529 $text = eregi_replace("([^a-z])on([a-z]+)([[:space:]]*)=", "\\1Xon\\2=", $text);
1536 * This function takes a string and examines it for HTML tags.
1537 * If tags are detected it passes the string to a helper function {@link cleanAttributes2()}
1538 * which checks for attributes and filters them for malicious content
1539 * 17/08/2004 :: Eamon DOT Costello AT dcu DOT ie
1541 * @param string $str The string to be examined for html tags
1544 function cleanAttributes($str){
1545 $result = preg_replace_callback(
1546 '%(<[^>]*(>|$)|>)%m', #search for html tags
1554 * This function takes a string with an html tag and strips out any unallowed
1555 * protocols e.g. javascript:
1556 * It calls ancillary functions in kses which are prefixed by kses
1557 * 17/08/2004 :: Eamon DOT Costello AT dcu DOT ie
1559 * @param array $htmlArray An array from {@link cleanAttributes()}, containing in its 1st
1560 * element the html to be cleared
1563 function cleanAttributes2($htmlArray){
1565 global $CFG, $ALLOWED_PROTOCOLS;
1566 require_once($CFG->libdir
.'/kses.php');
1568 $htmlTag = $htmlArray[1];
1569 if (substr($htmlTag, 0, 1) != '<') {
1570 return '>'; //a single character ">" detected
1572 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $htmlTag, $matches)) {
1573 return ''; // It's seriously malformed
1575 $slash = trim($matches[1]); //trailing xhtml slash
1576 $elem = $matches[2]; //the element name
1577 $attrlist = $matches[3]; // the list of attributes as a string
1579 $attrArray = kses_hair($attrlist, $ALLOWED_PROTOCOLS);
1582 foreach ($attrArray as $arreach) {
1583 $arreach['name'] = strtolower($arreach['name']);
1584 if ($arreach['name'] == 'style') {
1585 $value = $arreach['value'];
1587 $prevvalue = $value;
1588 $value = kses_no_null($value);
1589 $value = preg_replace("/\/\*.*\*\//Us", '', $value);
1590 $value = kses_decode_entities($value);
1591 $value = preg_replace('/(&#[0-9]+)(;?)/', "\\1;", $value);
1592 $value = preg_replace('/(&#x[0-9a-fA-F]+)(;?)/', "\\1;", $value);
1593 if ($value === $prevvalue) {
1594 $arreach['value'] = $value;
1598 $arreach['value'] = preg_replace("/j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t/i", "Xjavascript", $arreach['value']);
1599 $arreach['value'] = preg_replace("/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n/i", "Xexpression", $arreach['value']);
1600 } else if ($arreach['name'] == 'href') {
1601 //Adobe Acrobat Reader XSS protection
1602 $arreach['value'] = preg_replace('/(\.(pdf|fdf|xfdf|xdp|xfd))[^a-z0-9_\.\-].*$/i', '$1', $arreach['value']);
1604 $attStr .= ' '.$arreach['name'].'="'.$arreach['value'].'" ';
1607 // Remove last space from attribute list
1608 $attStr = rtrim($attStr);
1611 if (preg_match('%/\s*$%', $attrlist)) {
1612 $xhtml_slash = ' /';
1614 return '<'. $slash . $elem . $attStr . $xhtml_slash .'>';
1618 * Replaces all known smileys in the text with image equivalents
1621 * @param string $text Passed by reference. The string to search for smily strings.
1624 function replace_smilies(&$text) {
1628 /// this builds the mapping array only once
1629 static $runonce = false;
1630 static $e = array();
1631 static $img = array();
1632 static $emoticons = array(
1638 'V-.' => 'thoughtful',
1639 ':-P' => 'tongueout',
1642 '8-)' => 'wideeyes',
1649 '8-o' => 'surprise',
1650 'P-|' => 'blackeye',
1657 if ($runonce == false) { /// After the first time this is not run again
1658 foreach ($emoticons as $emoticon => $image){
1659 $alttext = get_string($image, 'pix');
1662 $img[] = '<img alt="'. $alttext .'" width="15" height="15" src="'. $CFG->pixpath
.'/s/'. $image .'.gif" />';
1667 // Exclude from transformations all the code inside <script> tags
1668 // Needed to solve Bug 1185. Thanks to jouse 2001 detecting it. :-)
1669 // Based on code from glossary fiter by Williams Castillo.
1672 // Detect all the <script> zones to take out
1673 $excludes = array();
1674 preg_match_all('/<script language(.+?)<\/script>/is',$text,$list_of_excludes);
1676 // Take out all the <script> zones from text
1677 foreach (array_unique($list_of_excludes[0]) as $key=>$value) {
1678 $excludes['<+'.$key.'+>'] = $value;
1681 $text = str_replace($excludes,array_keys($excludes),$text);
1684 /// this is the meat of the code - this is run every time
1685 $text = str_replace($e, $img, $text);
1687 // Recover all the <script> zones to text
1689 $text = str_replace(array_keys($excludes),$excludes,$text);
1694 * Given plain text, makes it into HTML as nicely as possible.
1695 * May contain HTML tags already
1698 * @param string $text The string to convert.
1699 * @param boolean $smiley Convert any smiley characters to smiley images?
1700 * @param boolean $para If true then the returned string will be wrapped in paragraph tags
1701 * @param boolean $newlines If true then lines newline breaks will be converted to HTML newline breaks.
1705 function text_to_html($text, $smiley=true, $para=true, $newlines=true) {
1710 /// Remove any whitespace that may be between HTML tags
1711 $text = eregi_replace(">([[:space:]]+)<", "><", $text);
1713 /// Remove any returns that precede or follow HTML tags
1714 $text = eregi_replace("([\n\r])<", " <", $text);
1715 $text = eregi_replace(">([\n\r])", "> ", $text);
1717 convert_urls_into_links($text);
1719 /// Make returns into HTML newlines.
1721 $text = nl2br($text);
1724 /// Turn smileys into images.
1726 replace_smilies($text);
1729 /// Wrap the whole thing in a paragraph tag if required
1731 return '<p>'.$text.'</p>';
1738 * Given Markdown formatted text, make it into XHTML using external function
1741 * @param string $text The markdown formatted text to be converted.
1742 * @return string Converted text
1744 function markdown_to_html($text) {
1747 require_once($CFG->libdir
.'/markdown.php');
1749 return Markdown($text);
1753 * Given HTML text, make it into plain text using external function
1756 * @param string $html The text to be converted.
1759 function html_to_text($html) {
1763 require_once($CFG->libdir
.'/html2text.php');
1765 return html2text($html);
1769 * Given some text this function converts any URLs it finds into HTML links
1771 * @param string $text Passed in by reference. The string to be searched for urls.
1773 function convert_urls_into_links(&$text) {
1774 /// Make lone URLs into links. eg http://moodle.com/
1775 $text = eregi_replace("([[:space:]]|^|\(|\[)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])",
1776 "\\1<a href=\"\\2://\\3\\4\" target=\"_blank\">\\2://\\3\\4</a>", $text);
1778 /// eg www.moodle.com
1779 $text = eregi_replace("([[:space:]]|^|\(|\[)www\.([^[:space:]]*)([[:alnum:]#?/&=])",
1780 "\\1<a href=\"http://www.\\2\\3\" target=\"_blank\">www.\\2\\3</a>", $text);
1784 * This function will highlight search words in a given string
1785 * It cares about HTML and will not ruin links. It's best to use
1786 * this function after performing any conversions to HTML.
1787 * Function found here: http://forums.devshed.com/t67822/scdaa2d1c3d4bacb4671d075ad41f0854.html
1789 * @param string $needle The string to search for
1790 * @param string $haystack The string to search for $needle in
1791 * @param int $case ?
1793 * @todo Finish documenting this function
1795 function highlight($needle, $haystack, $case=0,
1796 $left_string='<span class="highlight">', $right_string='</span>') {
1797 if (empty($needle)) {
1801 //$list_of_words = eregi_replace("[^-a-zA-Z0-9&.']", " ", $needle); // bug 3101
1802 $list_of_words = $needle;
1803 $list_array = explode(' ', $list_of_words);
1804 for ($i=0; $i<sizeof($list_array); $i++
) {
1805 if (strlen($list_array[$i]) == 1) {
1806 $list_array[$i] = '';
1809 $list_of_words = implode(' ', $list_array);
1810 $list_of_words_cp = $list_of_words;
1812 preg_match_all('/<(.+?)>/is',$haystack,$list_of_words);
1814 foreach (array_unique($list_of_words[0]) as $key=>$value) {
1815 $final['<|'.$key.'|>'] = $value;
1818 $haystack = str_replace($final,array_keys($final),$haystack);
1819 $list_of_words_cp = eregi_replace(' +', '|', $list_of_words_cp);
1821 if ($list_of_words_cp{0}=='|') {
1822 $list_of_words_cp{0} = '';
1824 if ($list_of_words_cp{strlen($list_of_words_cp)-1}=='|') {
1825 $list_of_words_cp{strlen($list_of_words_cp)-1}='';
1828 $list_of_words_cp = trim($list_of_words_cp);
1830 if ($list_of_words_cp) {
1832 $list_of_words_cp = "(". $list_of_words_cp .")";
1835 $haystack = eregi_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
1837 $haystack = ereg_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
1840 $haystack = str_replace(array_keys($final),$final,$haystack);
1846 * This function will highlight instances of $needle in $haystack
1847 * It's faster that the above function and doesn't care about
1850 * @param string $needle The string to search for
1851 * @param string $haystack The string to search for $needle in
1854 function highlightfast($needle, $haystack) {
1856 $parts = explode(strtolower($needle), strtolower($haystack));
1860 foreach ($parts as $key => $part) {
1861 $parts[$key] = substr($haystack, $pos, strlen($part));
1862 $pos +
= strlen($part);
1864 $parts[$key] .= '<span class="highlight">'.substr($haystack, $pos, strlen($needle)).'</span>';
1865 $pos +
= strlen($needle);
1868 return (join('', $parts));
1872 /// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
1875 * Print a standard header
1880 * @param string $title Appears at the top of the window
1881 * @param string $heading Appears at the top of the page
1882 * @param string $navigation Premade navigation string (for use as breadcrumbs links)
1883 * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
1884 * @param string $meta Meta tags to be added to the header
1885 * @param boolean $cache Should this page be cacheable?
1886 * @param string $button HTML code for a button (usually for module editing)
1887 * @param string $menu HTML code for a popup menu
1888 * @param boolean $usexml use XML for this page
1889 * @param string $bodytags This text will be included verbatim in the <body> tag (useful for onload() etc)
1891 function print_header ($title='', $heading='', $navigation='', $focus='', $meta='',
1892 $cache=true, $button=' ', $menu='', $usexml=false, $bodytags='') {
1894 global $USER, $CFG, $THEME, $SESSION, $ME, $SITE, $HTTPSPAGEREQUIRED;
1896 /// This makes sure that the header is never repeated twice on a page
1897 if (defined('HEADER_PRINTED')) {
1898 if ($CFG->debug
> 7) {
1899 notify('print_header() was called more than once - this should not happen. Please check the code for this page closely. Note: error() and redirect() are now safe to call after print_header().');
1903 define('HEADER_PRINTED', 'true');
1906 global $course, $COURSE;
1907 if (!empty($COURSE->lang
)) {
1908 $CFG->courselang
= $COURSE->lang
;
1910 } else if (!empty($course->lang
)) { // ugly backwards compatibility hack
1911 $CFG->courselang
= $course->lang
;
1914 if (!empty($COURSE->theme
)) {
1915 if (!empty($CFG->allowcoursethemes
)) {
1916 $CFG->coursetheme
= $COURSE->theme
;
1919 } else if (!empty($course->theme
)) { // ugly backwards compatibility hack
1920 if (!empty($CFG->allowcoursethemes
)) {
1921 $CFG->coursetheme
= $course->theme
;
1926 /// We have to change some URLs in styles if we are in a $HTTPSPAGEREQUIRED page
1927 if (!empty($HTTPSPAGEREQUIRED)) {
1928 $CFG->themewww
= str_replace('http:', 'https:', $CFG->themewww
);
1929 $CFG->pixpath
= str_replace('http:', 'https:', $CFG->pixpath
);
1930 $CFG->modpixpath
= str_replace('http:', 'https:', $CFG->modpixpath
);
1931 foreach ($CFG->stylesheets
as $key => $stylesheet) {
1932 $CFG->stylesheets
[$key] = str_replace('http:', 'https:', $stylesheet);
1936 /// Add the required stylesheets
1937 $stylesheetshtml = '';
1938 foreach ($CFG->stylesheets
as $stylesheet) {
1939 $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
1941 $meta = $stylesheetshtml.$meta;
1944 if ($navigation == 'home') {
1951 /// This is another ugly hack to make navigation elements available to print_footer later
1952 $THEME->title
= $title;
1953 $THEME->heading
= $heading;
1954 $THEME->navigation
= $navigation;
1955 $THEME->button
= $button;
1956 $THEME->menu
= $menu;
1957 $navmenulist = isset($THEME->navmenulist
) ?
$THEME->navmenulist
: '';
1959 if ($button == '') {
1963 if (!$menu and $navigation) {
1964 if (empty($CFG->loginhttps
)) {
1965 $wwwroot = $CFG->wwwroot
;
1967 $wwwroot = str_replace('http:','https:',$CFG->wwwroot
);
1969 if (isset($course->id
)) {
1970 $menu = user_login_string($course);
1972 $menu = user_login_string($SITE);
1976 if (isset($SESSION->justloggedin
)) {
1977 unset($SESSION->justloggedin
);
1978 if (!empty($CFG->displayloginfailures
)) {
1979 if (!empty($USER->username
) and !isguest()) {
1980 if ($count = count_login_failures($CFG->displayloginfailures
, $USER->username
, $USER->lastlogin
)) {
1981 $menu .= ' <font size="1">';
1982 if (empty($count->accounts
)) {
1983 $menu .= get_string('failedloginattempts', '', $count);
1985 $menu .= get_string('failedloginattemptsall', '', $count);
1988 $menu .= ' (<a href="'.$CFG->wwwroot
.'/course/report/log/index.php'.
1989 '?chooselog=1&id=1&modid=site_errors">'.get_string('logs').'</a>)';
1998 $encoding = current_charset();
2000 $meta = '<meta http-equiv="content-type" content="text/html; charset='. $encoding .'" />'. "\n". $meta ."\n";
2002 @header
('Content-type: text/html; charset='.$encoding);
2005 if ( get_string('thisdirection') == 'rtl' ) {
2006 $direction = ' dir="rtl"';
2008 $direction = ' dir="ltr"';
2010 //Accessibility: added the 'lang' attribute to $direction, used in theme <html> tag.
2011 $language = str_replace('_utf8','',$CFG->lang
);
2012 $direction .= ' lang="'.$language.'" xml:lang="'.$language.'"';
2014 if ($cache) { // Allow caching on "back" (but not on normal clicks)
2015 @header
('Cache-Control: private, pre-check=0, post-check=0, max-age=0');
2016 @header
('Pragma: no-cache');
2017 @header
('Expires: ');
2018 } else { // Do everything we can to always prevent clients and proxies caching
2019 @header
('Cache-Control: no-store, no-cache, must-revalidate');
2020 @header
('Cache-Control: post-check=0, pre-check=0', false);
2021 @header
('Pragma: no-cache');
2022 @header
('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
2023 @header
('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
2025 $meta .= "\n<meta http-equiv=\"pragma\" content=\"no-cache\" />";
2026 $meta .= "\n<meta http-equiv=\"expires\" content=\"0\" />";
2028 @header
('Accept-Ranges: none');
2030 if ($usexml) { // Added by Gustav Delius / Mad Alex for MathML output
2031 // Modified by Julian Sedding
2032 $currentlanguage = current_language();
2033 $mathplayer = preg_match("/MathPlayer/i", $_SERVER['HTTP_USER_AGENT']);
2035 header('Content-Type: application/xhtml+xml');
2037 echo '<?xml version="1.0" ?>'."\n";
2038 if (!empty($CFG->xml_stylesheets
)) {
2039 $stylesheets = explode(';', $CFG->xml_stylesheets
);
2040 foreach ($stylesheets as $stylesheet) {
2041 echo '<?xml-stylesheet type="text/xsl" href="'. $CFG->wwwroot
.'/'. $stylesheet .'" ?>' . "\n";
2044 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1';
2045 if (!empty($CFG->xml_doctype_extra
)) {
2046 echo ' plus '. $CFG->xml_doctype_extra
;
2048 echo '//' . strtoupper($currentlanguage) . '" "'. $CFG->xml_dtd
.'">'."\n";
2049 $direction = " xmlns=\"http://www.w3.org/1999/xhtml\"
2050 xmlns:math=\"http://www.w3.org/1998/Math/MathML\"
2051 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
2054 $meta .= '<object id="mathplayer" classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">' . "\n";
2055 $meta .= '<!--comment required to prevent this becoming an empty tag-->'."\n";
2056 $meta .= '</object>'."\n";
2057 $meta .= '<?import namespace="math" implementation="#mathplayer" ?>' . "\n";
2061 // Clean up the title
2063 $title = str_replace('"', '"', $title);
2064 $title = strip_tags($title);
2066 // Create class and id for this page
2068 page_id_and_class($pageid, $pageclass);
2070 if (isset($course->id
)) {
2071 $pageclass .= ' course-'.$course->id
;
2073 $pageclass .= ' course-'.SITEID
;
2076 if (!empty($USER->editing
)) {
2077 $pageclass .= ' editing';
2080 $bodytags .= ' class="'.$pageclass.'" id="'.$pageid.'"';
2082 include ($CFG->themedir
.current_theme().'/header.html');
2084 if (!empty($CFG->messaging
)) {
2085 echo message_popup_window();
2090 * This version of print_header is simpler because the course name does not have to be
2091 * provided explicitly in the strings. It can be used on the site page as in courses
2092 * Eventually all print_header could be replaced by print_header_simple
2094 * @param string $title Appears at the top of the window
2095 * @param string $heading Appears at the top of the page
2096 * @param string $navigation Premade navigation string (for use as breadcrumbs links)
2097 * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
2098 * @param string $meta Meta tags to be added to the header
2099 * @param boolean $cache Should this page be cacheable?
2100 * @param string $button HTML code for a button (usually for module editing)
2101 * @param string $menu HTML code for a popup menu
2102 * @param boolean $usexml use XML for this page
2103 * @param string $bodytags This text will be included verbatim in the <body> tag (useful for onload() etc)
2105 function print_header_simple($title='', $heading='', $navigation='', $focus='', $meta='',
2106 $cache=true, $button=' ', $menu='', $usexml=false, $bodytags='') {
2108 global $course,$CFG; // The same hack is used in print_header
2111 if ($course->category
) {
2112 $shortname = '<a href="'.$CFG->wwwroot
.'/course/view.php?id='. $course->id
.'">'. $course->shortname
.'</a> ->';
2115 print_header($course->shortname
.': '. $title, $course->fullname
.' '. $heading, $shortname .' '. $navigation, $focus, $meta,
2116 $cache, $button, $menu, $usexml, $bodytags);
2121 * Can provide a course object to make the footer contain a link to
2122 * to the course home page, otherwise the link will go to the site home
2126 * @param course $course {@link $COURSE} object containing course information
2127 * @param ? $usercourse ?
2128 * @todo Finish documenting this function
2130 function print_footer($course=NULL, $usercourse=NULL) {
2131 global $USER, $CFG, $THEME;
2135 if (is_string($course) && $course == 'none') { // Don't print any links etc
2139 } else if (is_string($course) && $course == 'home') { // special case for site home page - please do not remove
2140 $course = get_site();
2141 $homelink = '<div class="sitelink">'.
2142 '<a title="moodle '. $CFG->release
.' ('. $CFG->version
.')" href="http://moodle.org/" target="_blank">'.
2143 '<br /><img width="100" height="30" src="pix/moodlelogo.gif" border="0" alt="moodlelogo" /></a></div>';
2146 $homelink = '<div class="homelink"><a target="'.$CFG->framename
.'" href="'.$CFG->wwwroot
.
2147 '/course/view.php?id='.$course->id
.'">'.$course->shortname
.'</a></div>';
2151 $course = get_site(); // Set course as site course by default
2152 $homelink = '<div class="homelink"><a target="'.$CFG->framename
.'" href="'.$CFG->wwwroot
.'/">'.get_string('home').'</a></div>';
2156 /// Set up some other navigation links (passed from print_header by ugly hack)
2157 $menu = isset($THEME->menu
) ?
str_replace('navmenu', 'navmenufooter', $THEME->menu
) : '';
2158 $title = isset($THEME->title
) ?
$THEME->title
: '';
2159 $button = isset($THEME->button
) ?
$THEME->button
: '';
2160 $heading = isset($THEME->heading
) ?
$THEME->heading
: '';
2161 $navigation = isset($THEME->navigation
) ?
$THEME->navigation
: '';
2162 $navmenulist = isset($THEME->navmenulist
) ?
$THEME->navmenulist
: '';
2165 /// Set the user link if necessary
2166 if (!$usercourse and is_object($course)) {
2167 $usercourse = $course;
2170 if (!isset($loggedinas)) {
2171 $loggedinas = user_login_string($usercourse, $USER);
2174 if ($loggedinas == $menu) {
2178 /// Provide some performance info if required
2179 $performanceinfo = '';
2180 if (defined('MDL_PERF') ||
$CFG->perfdebug
> 7) {
2181 $perf = get_performance_info();
2182 if (defined('MDL_PERFTOLOG')) {
2183 error_log("PERF: " . $perf['txt']);
2185 if (defined('MDL_PERFTOFOOT') ||
$CFG->debug
> 7 ||
$CFG->perfdebug
> 7) {
2186 $performanceinfo = $perf['html'];
2191 /// Include the actual footer file
2193 include ($CFG->themedir
.current_theme().'/footer.html');
2198 * Returns the name of the current theme
2205 function current_theme() {
2206 global $CFG, $USER, $SESSION, $course;
2208 if (!empty($CFG->pagetheme
)) { // Page theme is for special page-only themes set by code
2209 return $CFG->pagetheme
;
2211 } else if (!empty($CFG->coursetheme
) and !empty($CFG->allowcoursethemes
)) { // Course themes override others
2212 return $CFG->coursetheme
;
2214 } else if (!empty($SESSION->theme
)) { // Session theme can override other settings
2215 return $SESSION->theme
;
2217 } else if (!empty($USER->theme
) and !empty($CFG->allowuserthemes
)) { // User theme can override site theme
2218 return $USER->theme
;
2227 * This function is called by stylesheets to set up the header
2228 * approriately as well as the current path
2231 * @param int $lastmodified ?
2232 * @param int $lifetime ?
2233 * @param string $thename ?
2235 function style_sheet_setup($lastmodified=0, $lifetime=300, $themename='', $forceconfig='', $lang='') {
2237 global $CFG, $THEME;
2239 // Fix for IE6 caching - we don't want the filemtime('styles.php'), instead use now.
2240 $lastmodified = time();
2242 header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastmodified) . ' GMT');
2243 header('Expires: ' . gmdate("D, d M Y H:i:s", time() +
$lifetime) . ' GMT');
2244 header('Cache-Control: max-age='. $lifetime);
2246 header('Content-type: text/css'); // Correct MIME type
2248 $DEFAULT_SHEET_LIST = array('styles_layout', 'styles_fonts', 'styles_color');
2250 if (empty($themename)) {
2251 $themename = current_theme(); // So we have something. Normally not needed.
2253 $themename = clean_param($themename, PARAM_SAFEDIR
);
2256 if (!empty($forceconfig)) { // Page wants to use the config from this theme instead
2258 include($CFG->themedir
.$forceconfig.'/'.'config.php');
2261 /// If this is the standard theme calling us, then find out what sheets we need
2263 if ($themename == 'standard') {
2264 if (!isset($THEME->standardsheets
) or $THEME->standardsheets
=== true) { // Use all the sheets we have
2265 $THEME->sheets
= $DEFAULT_SHEET_LIST;
2266 } else if (empty($THEME->standardsheets
)) { // We can stop right now!
2267 echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
2269 } else { // Use the provided subset only
2270 $THEME->sheets
= $THEME->standardsheets
;
2273 /// If we are a parent theme, then check for parent definitions
2275 } else if (!empty($THEME->parent
) && $themename == $THEME->parent
) {
2276 if (!isset($THEME->parentsheets
) or $THEME->parentsheets
=== true) { // Use all the sheets we have
2277 $THEME->sheets
= $DEFAULT_SHEET_LIST;
2278 } else if (empty($THEME->parentsheets
)) { // We can stop right now!
2279 echo "/***** Nothing required from this stylesheet by main theme *****/\n\n";
2281 } else { // Use the provided subset only
2282 $THEME->sheets
= $THEME->parentsheets
;
2286 /// Work out the last modified date for this theme
2288 foreach ($THEME->sheets
as $sheet) {
2289 if (file_exists($CFG->themedir
.$themename.'/'.$sheet.'.css')) {
2290 $sheetmodified = filemtime($CFG->themedir
.$themename.'/'.$sheet.'.css');
2291 if ($sheetmodified > $lastmodified) {
2292 $lastmodified = $sheetmodified;
2298 /// Get a list of all the files we want to include
2301 foreach ($THEME->sheets
as $sheet) {
2302 $files[] = array($CFG->themedir
, $themename.'/'.$sheet.'.css');
2305 if ($themename == 'standard') { // Add any standard styles included in any modules
2306 if (!empty($THEME->modsheets
)) { // Search for styles.php within activity modules
2307 if ($mods = get_list_of_plugins('mod')) {
2308 foreach ($mods as $mod) {
2309 if (file_exists($CFG->dirroot
.'/mod/'.$mod.'/styles.php')) {
2310 $files[] = array($CFG->dirroot
, '/mod/'.$mod.'/styles.php');
2316 if (!empty($THEME->blocksheets
)) { // Search for styles.php within block modules
2317 if ($mods = get_list_of_plugins('blocks')) {
2318 foreach ($mods as $mod) {
2319 if (file_exists($CFG->dirroot
.'/blocks/'.$mod.'/styles.php')) {
2320 $files[] = array($CFG->dirroot
, '/blocks/'.$mod.'/styles.php');
2326 if (!empty($THEME->langsheets
)) { // Search for styles.php within the current language
2327 if (file_exists($CFG->dirroot
.'/lang/'.$lang.'/styles.php')) {
2328 $files[] = array($CFG->dirroot
, '/lang/'.$lang.'/styles.php');
2335 /// Produce a list of all the files first
2336 echo '/**************************************'."\n";
2337 echo ' * THEME NAME: '.$themename."\n *\n";
2338 echo ' * Files included in this sheet:'."\n *\n";
2339 foreach ($files as $file) {
2340 echo ' * '.$file[1]."\n";
2342 echo ' **************************************/'."\n\n";
2345 /// Actually output all the files in order.
2346 foreach ($files as $file) {
2347 echo '/***** '.$file[1].' start *****/'."\n\n";
2348 @include_once
($file[0].$file[1]);
2349 echo '/***** '.$file[1].' end *****/'."\n\n";
2353 return $CFG->themewww
.$themename; // Only to help old themes (1.4 and earlier)
2357 function theme_setup($theme = '', $params=NULL) {
2358 /// Sets up global variables related to themes
2360 global $CFG, $THEME, $SESSION, $USER;
2362 if (empty($theme)) {
2363 $theme = current_theme();
2366 /// If the theme doesn't exist for some reason then revert to standardwhite
2367 if (!file_exists($CFG->themedir
. $theme .'/config.php')) {
2368 $CFG->theme
= $theme = 'standardwhite';
2371 /// Load up the theme config
2372 $THEME = NULL; // Just to be sure
2373 include($CFG->themedir
. $theme .'/config.php'); // Main config for current theme
2375 /// Put together the parameters
2379 if ($theme != $CFG->theme
) {
2380 $params[] = 'forceconfig='.$theme;
2383 /// Force language too if required
2384 if (!empty($THEME->langsheets
)) {
2385 $params[] = 'lang='.current_language();
2388 /// Convert params to string
2390 $paramstring = '?'.implode('&', $params);
2395 /// Set up image paths
2396 if (empty($THEME->custompix
)) { // Could be set in the above file
2397 $CFG->pixpath
= $CFG->wwwroot
.'/pix';
2398 $CFG->modpixpath
= $CFG->wwwroot
.'/mod';
2400 $CFG->pixpath
= $CFG->themewww
. $theme .'/pix';
2401 $CFG->modpixpath
= $CFG->themewww
. $theme .'/pix/mod';
2404 /// Header and footer paths
2405 $CFG->header
= $CFG->themedir
. $theme .'/header.html';
2406 $CFG->footer
= $CFG->themedir
. $theme .'/footer.html';
2408 /// Define stylesheet loading order
2409 $CFG->stylesheets
= array();
2410 if ($theme != 'standard') { /// The standard sheet is always loaded first
2411 $CFG->stylesheets
[] = $CFG->themewww
.'standard/styles.php'.$paramstring;
2413 if (!empty($THEME->parent
)) { /// Parent stylesheets are loaded next
2414 $CFG->stylesheets
[] = $CFG->themewww
.$THEME->parent
.'/styles.php'.$paramstring;
2416 $CFG->stylesheets
[] = $CFG->themewww
.$theme.'/styles.php'.$paramstring;
2422 * Returns text to be displayed to the user which reflects their login status
2426 * @param course $course {@link $COURSE} object containing course information
2427 * @param user $user {@link $USER} object containing user information
2430 function user_login_string($course=NULL, $user=NULL) {
2431 global $USER, $CFG, $SITE;
2433 if (empty($user) and isset($USER->id
)) {
2437 if (empty($course)) {
2441 if (isset($user->realuser
)) {
2442 if ($realuser = get_record('user', 'id', $user->realuser
)) {
2443 $fullname = fullname($realuser, true);
2444 $realuserinfo = " [<a target=\"{$CFG->framename}\"
2445 href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&return=1\">$fullname</a>] ";
2451 if (empty($CFG->loginhttps
)) {
2452 $wwwroot = $CFG->wwwroot
;
2454 $wwwroot = str_replace('http:','https:',$CFG->wwwroot
);
2457 if (isset($user->id
) and $user->id
) {
2458 $fullname = fullname($user, true);
2459 $username = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$fullname</a>";
2460 $instudentview = (!empty($USER->studentview
)) ?
get_string('instudentview') : '';
2461 if (isguest($user->id
)) {
2462 $loggedinas = $realuserinfo.get_string('loggedinasguest').
2463 " (<a target=\"{$CFG->framename}\" href=\"$wwwroot/login/index.php\">".get_string('login').'</a>)';
2465 $loggedinas = $realuserinfo.get_string('loggedinas', 'moodle', $username).' '.$instudentview.
2466 " (<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/login/logout.php\">".get_string('logout').'</a>)';
2469 $loggedinas = get_string('loggedinnot', 'moodle').
2470 " (<a target=\"{$CFG->framename}\" href=\"$wwwroot/login/index.php\">".get_string('login').'</a>)';
2472 return '<div class="logininfo">'.$loggedinas.'</div>';
2476 * Prints breadcrumbs links
2479 * @param string $navigation The breadcrumbs string to be printed
2481 function print_navigation ($navigation) {
2485 //Accessibility: breadcrumb links now in a list, » replaced with image.
2486 $nav_text = get_string('youarehere','access');
2487 echo '<h2 class="accesshide">'.$nav_text.",</h2><ul>\n";
2488 if (! $site = get_site()) {
2489 $site->shortname
= get_string('home');
2491 $navigation = '<li title="'.$nav_text.'"><img src="'.$CFG->pixpath
.'/a/r_breadcrumb.gif" class="resize" alt="" /> '
2492 .str_replace('->', '</li><li title="'.$nav_text.'"><img src="'.$CFG->pixpath
.'/a/r_breadcrumb.gif" class="resize" alt="" /> ', $navigation)."</li>\n";
2493 echo '<li class="first"><a target="'. $CFG->framename
.'" href="'. $CFG->wwwroot
.((!isadmin() && !empty($USER->id
) && !empty($CFG->mymoodleredirect
) && !isguest())
2494 ?
'/my' : '') .'/">'. $site->shortname
."</a></li>\n". $navigation;
2500 * Prints a string in a specified size (retained for backward compatibility)
2502 * @param string $text The text to be displayed
2503 * @param int $size The size to set the font for text display.
2505 function print_headline($text, $size=2) {
2506 print_heading($text, 'left', $size);
2510 * Prints text in a format for use in headings.
2512 * @param string $text The text to be displayed
2513 * @param string $align The alignment of the printed paragraph of text
2514 * @param int $size The size to set the font for text display.
2516 function print_heading($text, $align='', $size=2, $class='main') {
2518 $align = ' align="'.$align.'"';
2521 $class = ' class="'.$class.'"';
2523 echo "<h$size $align $class>".stripslashes_safe($text)."</h$size>";
2527 * Centered heading with attached help button (same title text)
2528 * and optional icon attached
2530 * @param string $text The text to be displayed
2531 * @param string $helppage The help page to link to
2532 * @param string $module The module whose help should be linked to
2533 * @param string $icon Image to display if needed
2535 function print_heading_with_help($text, $helppage, $module='moodle', $icon='') {
2536 echo '<h2 class="main help">'.$icon.stripslashes_safe($text);
2537 helpbutton($helppage, $text, $module);
2542 function print_heading_block($heading, $class='') {
2543 //Accessibility: 'headingblock' is now H1, see theme/standard/styles_*.css: ??
2544 echo '<h2 class="headingblock header '.$class.'">'.stripslashes($heading).'</h2>';
2549 * Print a link to continue on to another page.
2552 * @param string $link The url to create a link to.
2554 function print_continue($link) {
2559 $link = $_SERVER['HTTP_REFERER'];
2562 echo '<div class="continuebutton">';
2563 print_single_button($link, NULL, get_string('continue'), 'post', $CFG->framename
);
2568 * Print a message in a standard themed box.
2569 * See, {@link print_simple_box_start}.
2571 * @param string $align string, alignment of the box, not the text (default center, left, right).
2572 * @param string $width string, width of the box, including units %, for example '100%'.
2573 * @param string $color string, background colour of the box, for example '#eee'.
2574 * @param int $padding integer, padding in pixels, specified without units.
2575 * @param string $class string, space-separated class names.
2576 * @todo Finish documenting this function
2578 function print_simple_box($message, $align='', $width='', $color='', $padding=5, $class='generalbox', $id='') {
2579 print_simple_box_start($align, $width, $color, $padding, $class, $id);
2580 echo stripslashes_safe($message);
2581 print_simple_box_end();
2585 * Print the top portion of a standard themed box using a TABLE. Yes, we know.
2586 * See bug 4943 for details on some accessibility work regarding this that didn't make it into 1.6.
2588 * @param string $align string, alignment of the box, not the text (default center, left, right).
2589 * @param string $width string, width of the box, including % units, for example '100%'.
2590 * @param string $color string, background colour of the box, for example '#eee'.
2591 * @param int $padding integer, padding in pixels, specified without units.
2592 * @param string $class string, space-separated class names.
2594 function print_simple_box_start($align='', $width='', $color='', $padding=5, $class='generalbox', $id='') {
2597 $color = 'bgcolor="'. $color .'"';
2600 $align = 'align="'. $align .'"';
2603 $width = 'width="'. $width .'"';
2606 $id = 'id="'. $id .'"';
2608 echo "<table $align $width $id class=\"$class\" border=\"0\" cellpadding=\"$padding\" cellspacing=\"0\">".
2609 "<tr><td $color class=\"$class"."content\">";
2613 * Print the end portion of a standard themed box.
2615 function print_simple_box_end() {
2616 echo '</td></tr></table>';
2621 * Print a self contained form with a single submit button.
2623 * @param string $link ?
2624 * @param array $options ?
2625 * @param string $label ?
2626 * @param string $method ?
2627 * @todo Finish documenting this function
2629 function print_single_button($link, $options, $label='OK', $method='get', $target='_self') {
2630 echo '<div class="singlebutton">';
2631 echo '<form action="'. $link .'" method="'. $method .'" target="'.$target.'">';
2633 foreach ($options as $name => $value) {
2634 echo '<input type="hidden" name="'. $name .'" value="'. $value .'" />';
2637 echo '<input type="submit" value="'. $label .'" /></form></div>';
2641 * Print a spacer image with the option of including a line break.
2643 * @param int $height ?
2644 * @param int $width ?
2645 * @param boolean $br ?
2646 * @todo Finish documenting this function
2648 function print_spacer($height=1, $width=1, $br=true) {
2650 echo '<img class="spacer" height="'. $height .'" width="'. $width .'" src="'. $CFG->wwwroot
.'/pix/spacer.gif" alt="" />';
2657 * Given the path to a picture file in a course, or a URL,
2658 * this function includes the picture in the page.
2660 * @param string $path ?
2661 * @param int $courseid ?
2662 * @param int $height ?
2663 * @param int $width ?
2664 * @param string $link ?
2665 * @todo Finish documenting this function
2667 function print_file_picture($path, $courseid=0, $height='', $width='', $link='') {
2671 $height = 'height="'. $height .'"';
2674 $width = 'width="'. $width .'"';
2677 echo '<a href="'. $link .'">';
2679 if (substr(strtolower($path), 0, 7) == 'http://') {
2680 echo '<img border="0" '.$height . $width .' src="'. $path .'" />';
2682 } else if ($courseid) {
2683 echo '<img border="0" '. $height . $width .' src="';
2684 if ($CFG->slasharguments
) { // Use this method if possible for better caching
2685 echo $CFG->wwwroot
.'/file.php/'. $courseid .'/'. $path;
2687 echo $CFG->wwwroot
.'/file.php?file=/'. $courseid .'/'. $path;
2691 echo 'Error: must pass URL or course';
2699 * Print the specified user's avatar.
2701 * @param int $userid ?
2702 * @param int $courseid ?
2703 * @param boolean $picture Print the user picture?
2704 * @param int $size Size in pixels. Special values are (true/1 = 100px) and (false/0 = 35px) for backward compatability
2705 * @param boolean $returnstring If false print picture to current page, otherwise return the output as string
2706 * @param boolean $link Enclose printed image in a link to view specified course?
2708 * @todo Finish documenting this function
2710 function print_user_picture($userid, $courseid, $picture, $size=0, $returnstring=false, $link=true, $target='') {
2715 $target=' target="_blank"';
2717 $output = '<a '.$target.' href="'. $CFG->wwwroot
.'/user/view.php?id='. $userid .'&course='. $courseid .'">';
2724 } else if ($size === true or $size == 1) {
2727 } else if ($size >= 50) {
2732 $class = "userpicture";
2733 if ($picture) { // Print custom user picture
2734 if ($CFG->slasharguments
) { // Use this method if possible for better caching
2735 $src = $CFG->wwwroot
.'/user/pix.php/'. $userid .'/'. $file .'.jpg"';
2737 $src = $CFG->wwwroot
.'/user/pix.php?file=/'. $userid .'/'. $file .'.jpg"';
2739 } else { // Print default user pictures (use theme version if available)
2740 $class .= " defaultuserpic";
2741 $src = "$CFG->pixpath/u/$file.png\"";
2743 $output .= "<img class=\"$class\" align=\"middle\" src=\"$src".
2744 " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" />";
2749 if ($returnstring) {
2757 * Prints a summary of a user in a nice little box.
2761 * @param user $user A {@link $USER} object representing a user
2762 * @param course $course A {@link $COURSE} object representing a course
2764 function print_user($user, $course, $messageselect=false) {
2774 if (empty($string)) { // Cache all the strings for the rest of the page
2776 $string->email
= get_string('email');
2777 $string->location
= get_string('location');
2778 $string->lastaccess
= get_string('lastaccess');
2779 $string->activity
= get_string('activity');
2780 $string->unenrol
= get_string('unenrol');
2781 $string->loginas
= get_string('loginas');
2782 $string->fullprofile
= get_string('fullprofile');
2783 $string->role
= get_string('role');
2784 $string->name
= get_string('name');
2785 $string->never
= get_string('never');
2787 $datestring->day
= get_string('day');
2788 $datestring->days
= get_string('days');
2789 $datestring->hour
= get_string('hour');
2790 $datestring->hours
= get_string('hours');
2791 $datestring->min
= get_string('min');
2792 $datestring->mins
= get_string('mins');
2793 $datestring->sec
= get_string('sec');
2794 $datestring->secs
= get_string('secs');
2796 $countries = get_list_of_countries();
2798 $isteacher = isteacher($course->id
);
2799 $isadmin = isadmin();
2802 /// Get the hidden field list
2803 if ($isteacher ||
$isadmin) {
2804 $hiddenfields = array();
2806 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields
));
2809 echo '<table class="userinfobox">';
2811 echo '<td class="left side">';
2812 print_user_picture($user->id
, $course->id
, $user->picture
, true);
2814 echo '<td class="content">';
2815 echo '<div class="username">'.fullname($user, $isteacher).'</div>';
2816 echo '<div class="info">';
2817 if (!empty($user->role
) and ($user->role
<> $course->teacher
)) {
2818 echo $string->role
.': '. $user->role
.'<br />';
2820 if ($user->maildisplay
== 1 or ($user->maildisplay
== 2 and $course->category
and !isguest()) or $isteacher) {
2821 echo $string->email
.': <a href="mailto:'. $user->email
.'">'. $user->email
.'</a><br />';
2823 if (($user->city
or $user->country
) and (!isset($hiddenfields['city']) or !isset($hiddenfields['country']))) {
2824 echo $string->location
.': ';
2825 if ($user->city
&& !isset($hiddenfields['city'])) {
2828 if (!empty($countries[$user->country
]) && !isset($hiddenfields['country'])) {
2829 if ($user->city
&& !isset($hiddenfields['city'])) {
2832 echo $countries[$user->country
];
2837 if (!isset($hiddenfields['lastaccess'])) {
2838 if ($user->lastaccess
) {
2839 echo $string->lastaccess
.': '. userdate($user->lastaccess
);
2840 echo '  ('. format_time(time() - $user->lastaccess
, $datestring) .')';
2842 echo $string->lastaccess
.': '. $string->never
;
2845 echo '</div></td><td class="links">';
2847 if ($CFG->bloglevel
> 0) {
2848 echo '<a href="'.$CFG->wwwroot
.'/blog/index.php?userid='.$user->id
.'">'.get_string('blogs','blog').'</a><br />';
2852 $timemidnight = usergetmidnight(time());
2853 echo '<a href="'. $CFG->wwwroot
.'/course/user.php?id='. $course->id
.'&user='. $user->id
.'">'. $string->activity
.'</a><br />';
2854 if (!iscreator($user->id
) or ($isadmin and !isadmin($user->id
))) { // Includes admins
2855 if ($course->category
and isteacheredit($course->id
) and isstudent($course->id
, $user->id
)) { // Includes admins
2856 echo '<a href="'. $CFG->wwwroot
.'/course/unenrol.php?id='. $course->id
.'&user='. $user->id
.'">'. $string->unenrol
.'</a><br />';
2858 if ($USER->id
!= $user->id
) {
2859 echo '<a href="'. $CFG->wwwroot
.'/course/loginas.php?id='. $course->id
.'&user='. $user->id
.'">'. $string->loginas
.'</a><br />';
2863 echo '<a href="'. $CFG->wwwroot
.'/user/view.php?id='. $user->id
.'&course='. $course->id
.'">'. $string->fullprofile
.'...</a>';
2865 if (!empty($messageselect) && $isteacher) {
2866 echo '<br /><input type="checkbox" name="';
2867 if (isteacher($course->id
, $user->id
)) {
2872 echo $user->id
.'" /> ';
2875 echo '</td></tr></table>';
2879 * Print a specified group's avatar.
2881 * @param group $group A {@link group} object representing a group or array of groups
2882 * @param int $courseid ?
2883 * @param boolean $large ?
2884 * @param boolean $returnstring ?
2885 * @param boolean $link ?
2887 * @todo Finish documenting this function
2889 function print_group_picture($group, $courseid, $large=false, $returnstring=false, $link=true) {
2892 if (is_array($group)) {
2894 foreach($group as $g) {
2895 $output .= print_group_picture($g, $courseid, $large, true, $link);
2897 if ($returnstring) {
2905 static $isteacheredit;
2907 if (!isset($isteacheredit)) {
2908 $isteacheredit = isteacheredit($courseid);
2911 if ($group->hidepicture
and !$isteacheredit) {
2915 if ($link or $isteacheredit) {
2916 $output = '<a href="'. $CFG->wwwroot
.'/user/index.php?id='. $courseid .'&group='. $group->id
.'">';
2927 if ($group->picture
) { // Print custom group picture
2928 if ($CFG->slasharguments
) { // Use this method if possible for better caching
2929 $output .= '<img class="grouppicture" align="middle" src="'.$CFG->wwwroot
.'/user/pixgroup.php/'.$group->id
.'/'.$file.'.jpg"'.
2930 ' border="0" width="'.$size.'" height="'.$size.'" alt="" title="'.s($group->name
).'"/>';
2932 $output .= '<img class="grouppicture" align="middle" src="'.$CFG->wwwroot
.'/user/pixgroup.php?file=/'.$group->id
.'/'.$file.'.jpg"'.
2933 ' border="0" width="'.$size.'" height="'.$size.'" alt="" title="'.s($group->name
).'"/>';
2936 if ($link or $isteacheredit) {
2940 if ($returnstring) {
2948 * Print a png image.
2950 * @param string $url ?
2951 * @param int $sizex ?
2952 * @param int $sizey ?
2953 * @param boolean $returnstring ?
2954 * @param string $parameters ?
2955 * @todo Finish documenting this function
2957 function print_png($url, $sizex, $sizey, $returnstring, $parameters='alt=""') {
2961 if (!isset($recentIE)) {
2962 $recentIE = check_browser_version('MSIE', '5.0');
2965 if ($recentIE) { // work around the HORRIBLE bug IE has with alpha transparencies
2966 $output .= '<img src="'. $CFG->pixpath
.'/spacer.gif" width="'. $sizex .'" height="'. $sizey .'"'.
2967 ' border="0" class="png" style="width: '. $sizex .'px; height: '. $sizey .'px; '.
2968 ' filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='.
2969 "'$url', sizingMethod='scale') ".
2970 ' '. $parameters .' />';
2972 $output .= '<img src="'. $url .'" border="0" width="'. $sizex .'" height="'. $sizey .'" '.
2973 ' '. $parameters .' />';
2976 if ($returnstring) {
2984 * Print a nicely formatted table.
2986 * @param array $table is an object with several properties.
2987 * <ul<li>$table->head - An array of heading names.
2988 * <li>$table->align - An array of column alignments
2989 * <li>$table->size - An array of column sizes
2990 * <li>$table->wrap - An array of "nowrap"s or nothing
2991 * <li>$table->data[] - An array of arrays containing the data.
2992 * <li>$table->width - A percentage of the page
2993 * <li>$table->tablealign - Align the whole table
2994 * <li>$table->cellpadding - Padding on each cell
2995 * <li>$table->cellspacing - Spacing between cells
2998 * @todo Finish documenting this function
3000 function print_table($table) {
3002 if (isset($table->align
)) {
3003 foreach ($table->align
as $key => $aa) {
3005 $align[$key] = ' align="'. $aa .'"';
3011 if (isset($table->size
)) {
3012 foreach ($table->size
as $key => $ss) {
3014 $size[$key] = ' width="'. $ss .'"';
3020 if (isset($table->wrap
)) {
3021 foreach ($table->wrap
as $key => $ww) {
3023 $wrap[$key] = ' nowrap="nowrap" ';
3030 if (empty($table->width
)) {
3031 $table->width
= '80%';
3034 if (empty($table->tablealign
)) {
3035 $table->tablealign
= 'center';
3038 if (empty($table->cellpadding
)) {
3039 $table->cellpadding
= '5';
3042 if (empty($table->cellspacing
)) {
3043 $table->cellspacing
= '1';
3046 if (empty($table->class)) {
3047 $table->class = 'generaltable';
3050 $tableid = empty($table->id
) ?
'' : 'id="'.$table->id
.'"';
3052 echo '<table width="'.$table->width
.'" border="0" align="'.$table->tablealign
.'" ';
3053 echo " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\" class=\"$table->class\" $tableid>\n";
3057 if (!empty($table->head
)) {
3058 $countcols = count($table->head
);
3060 foreach ($table->head
as $key => $heading) {
3062 if (!isset($size[$key])) {
3065 if (!isset($align[$key])) {
3068 echo '<th valign="top" '. $align[$key].$size[$key] .' nowrap="nowrap" class="header c'.$key.'">'. $heading .'</th>';
3073 if (!empty($table->data
)) {
3075 foreach ($table->data
as $key => $row) {
3076 $oddeven = $oddeven ?
0 : 1;
3077 echo '<tr class="r'.$oddeven.'">'."\n";
3078 if ($row == 'hr' and $countcols) {
3079 echo '<td colspan="'. $countcols .'"><div class="tabledivider"></div></td>';
3080 } else { /// it's a normal row of data
3081 foreach ($row as $key => $item) {
3082 if (!isset($size[$key])) {
3085 if (!isset($align[$key])) {
3088 if (!isset($wrap[$key])) {
3091 echo '<td '. $align[$key].$size[$key].$wrap[$key] .' class="cell c'.$key.'">'. $item .'</td>';
3097 echo '</table>'."\n";
3103 * Creates a nicely formatted table and returns it.
3105 * @param array $table is an object with several properties.
3106 * <ul<li>$table->head - An array of heading names.
3107 * <li>$table->align - An array of column alignments
3108 * <li>$table->size - An array of column sizes
3109 * <li>$table->wrap - An array of "nowrap"s or nothing
3110 * <li>$table->data[] - An array of arrays containing the data.
3111 * <li>$table->class - A css class name
3112 * <li>$table->fontsize - Is the size of all the text
3113 * <li>$table->tablealign - Align the whole table
3114 * <li>$table->width - A percentage of the page
3115 * <li>$table->cellpadding - Padding on each cell
3116 * <li>$table->cellspacing - Spacing between cells
3119 * @todo Finish documenting this function
3121 function make_table($table) {
3123 if (isset($table->align
)) {
3124 foreach ($table->align
as $key => $aa) {
3126 $align[$key] = ' align="'. $aa .'"';
3132 if (isset($table->size
)) {
3133 foreach ($table->size
as $key => $ss) {
3135 $size[$key] = ' width="'. $ss .'"';
3141 if (isset($table->wrap
)) {
3142 foreach ($table->wrap
as $key => $ww) {
3144 $wrap[$key] = ' nowrap="nowrap" ';
3151 if (empty($table->width
)) {
3152 $table->width
= '80%';
3155 if (empty($table->tablealign
)) {
3156 $table->tablealign
= 'center';
3159 if (empty($table->cellpadding
)) {
3160 $table->cellpadding
= '5';
3163 if (empty($table->cellspacing
)) {
3164 $table->cellspacing
= '1';
3167 if (empty($table->class)) {
3168 $table->class = 'generaltable';
3171 if (empty($table->fontsize
)) {
3174 $fontsize = '<font size="'. $table->fontsize
.'">';
3177 $output = '<table width="'. $table->width
.'" align="'. $table->tablealign
.'" ';
3178 $output .= ' cellpadding="'. $table->cellpadding
.'" cellspacing="'. $table->cellspacing
.'" class="'. $table->class .'">'."\n";
3180 if (!empty($table->head
)) {
3181 $output .= '<tr valign="top">';
3182 foreach ($table->head
as $key => $heading) {
3183 if (!isset($size[$key])) {
3186 if (!isset($align[$key])) {
3189 $output .= '<th valign="top" '. $align[$key].$size[$key] .' nowrap="nowrap" class="'. $table->class .'header">'.$fontsize.$heading.'</th>';
3191 $output .= '</tr>'."\n";
3194 foreach ($table->data
as $row) {
3195 $output .= '<tr valign="top">';
3196 foreach ($row as $key => $item) {
3197 if (!isset($size[$key])) {
3200 if (!isset($align[$key])) {
3203 if (!isset($wrap[$key])) {
3206 $output .= '<td '. $align[$key].$size[$key].$wrap[$key] .' class="'. $table->class .'cell">'. $fontsize . $item .'</td>';
3208 $output .= '</tr>'."\n";
3210 $output .= '</table>'."\n";
3215 function print_recent_activity_note($time, $user, $isteacher, $text, $link) {
3216 static $strftimerecent;
3218 if (empty($strftimerecent)) {
3219 $strftimerecent = get_string('strftimerecent');
3222 $date = userdate($time, $strftimerecent);
3223 $name = fullname($user, $isteacher);
3225 echo '<div class="head">';
3226 echo '<div class="date">'.$date.'</div> '.
3227 '<div class="name">'.fullname($user, $isteacher).'</div>';
3229 echo '<div class="info"><a href="'.$link.'">'.format_string($text,true).'</a></div>';
3234 * Prints a basic textarea field.
3237 * @param boolean $usehtmleditor ?
3238 * @param int $rows ?
3239 * @param int $cols ?
3240 * @param null $width <b>Legacy field no longer used!</b> Set to zero to get control over mincols
3241 * @param null $height <b>Legacy field no longer used!</b> Set to zero to get control over minrows
3242 * @param string $name ?
3243 * @param string $value ?
3244 * @param int $courseid ?
3245 * @todo Finish documenting this function
3247 function print_textarea($usehtmleditor, $rows, $cols, $width, $height, $name, $value='', $courseid=0, $return=false) {
3248 /// $width and height are legacy fields and no longer used as pixels like they used to be.
3249 /// However, you can set them to zero to override the mincols and minrows values below.
3251 global $CFG, $course;
3252 static $scriptcount; // For loading the htmlarea script only once.
3258 if ( empty($CFG->editorsrc
) ) { // for backward compatibility.
3259 if (empty($courseid)) {
3260 if (!empty($course->id
)) { // search for it in global context
3261 $courseid = $course->id
;
3265 if (empty($scriptcount)) {
3269 if ($usehtmleditor) {
3271 if (!empty($courseid) and isteacher($courseid)) {
3272 $str .= ($scriptcount < 1) ?
'<script type="text/javascript" src="'.
3273 $CFG->wwwroot
.'/lib/editor/htmlarea/htmlarea.php?id='. $courseid .'"></script>'."\n" : '';
3275 $str .= ($scriptcount < 1) ?
'<script type="text/javascript" src="'.
3276 $CFG->wwwroot
.'/lib/editor/htmlarea/htmlarea.php"></script>'."\n" : '';
3278 $str .= ($scriptcount < 1) ?
'<script type="text/javascript" src="'.
3279 $CFG->wwwroot
.'/lib/editor/htmlarea/lang/en.php"></script>'."\n" : '';
3282 if ($height) { // Usually with legacy calls
3283 if ($rows < $minrows) {
3287 if ($width) { // Usually with legacy calls
3288 if ($cols < $mincols) {
3294 $str .= '<textarea id="edit-'. $name .'" name="'. $name .'" rows="'. $rows .'" cols="'. $cols .'">';
3295 if ($usehtmleditor) {
3296 $str .= htmlspecialchars($value); // needed for editing of cleaned text!
3300 $str .= '</textarea>'."\n";
3309 * Legacy function, provided for backward compatability.
3310 * This method now simply calls {@link use_html_editor()}
3312 * @deprecated Use {@link use_html_editor()} instead.
3313 * @param string $name Form element to replace with HTMl editor by name
3314 * @todo Finish documenting this function
3316 function print_richedit_javascript($form, $name, $source='no') {
3317 use_html_editor($name);
3321 * Sets up the HTML editor on textareas in the current page.
3322 * If a field name is provided, then it will only be
3323 * applied to that field - otherwise it will be used
3324 * on every textarea in the page.
3326 * In most cases no arguments need to be supplied
3328 * @param string $name Form element to replace with HTMl editor by name
3330 function use_html_editor($name='', $editorhidebuttons='') {
3331 $editor = 'editor_'.md5($name); //name might contain illegal characters
3332 echo '<script language="javascript" type="text/javascript" defer="defer">'."\n";
3333 echo "$editor = new HTMLArea('edit-$name');\n";
3334 echo "var config = $editor.config;\n";
3336 echo print_editor_config($editorhidebuttons);
3339 echo "\nHTMLArea.replaceAll($editor.config);\n";
3341 echo "\n$editor.generate();\n";
3343 echo '</script>'."\n";
3346 function print_editor_config($editorhidebuttons='', $return=false) {
3349 $str = "config.pageStyle = \"body {";
3351 if (!(empty($CFG->editorbackgroundcolor
))) {
3352 $str .= " background-color: $CFG->editorbackgroundcolor;";
3355 if (!(empty($CFG->editorfontfamily
))) {
3356 $str .= " font-family: $CFG->editorfontfamily;";
3359 if (!(empty($CFG->editorfontsize
))) {
3360 $str .= " font-size: $CFG->editorfontsize;";
3364 $str .= "config.killWordOnPaste = ";
3365 $str .= (empty($CFG->editorkillword
)) ?
"false":"true";
3367 $str .= 'config.fontname = {'."\n";
3369 $fontlist = isset($CFG->editorfontlist
) ?
explode(';', $CFG->editorfontlist
) : array();
3370 $i = 1; // Counter is used to get rid of the last comma.
3372 foreach ($fontlist as $fontline) {
3373 if (!empty($fontline)) {
3377 list($fontkey, $fontvalue) = split(':', $fontline);
3378 $str .= '"'. $fontkey ."\":\t'". $fontvalue ."'";
3385 if (!empty($editorhidebuttons)) {
3386 $str .= "\nconfig.hideSomeButtons(\" ". $editorhidebuttons ." \");\n";
3387 } else if (!empty($CFG->editorhidebuttons
)) {
3388 $str .= "\nconfig.hideSomeButtons(\" ". $CFG->editorhidebuttons
." \");\n";
3391 if (!empty($CFG->editorspelling
) && !empty($CFG->aspellpath
)) {
3392 $str .= print_speller_code($usehtmleditor=true, true);
3402 * Returns a turn edit on/off button for course in a self contained form.
3403 * Used to be an icon, but it's now a simple form button
3407 * @param int $courseid The course to update by id as found in 'course' table
3410 function update_course_icon($courseid) {
3414 if (isteacheredit($courseid)) {
3415 if (!empty($USER->editing
)) {
3416 $string = get_string('turneditingoff');
3419 $string = get_string('turneditingon');
3422 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/view.php\">".
3423 "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
3424 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3425 "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />".
3426 "<input type=\"submit\" value=\"$string\" /></form>";
3431 * Returns a turn student view on/off button for course in a self contained form.
3435 * @param int $courseid The course to update by id as found in 'course' table
3438 function update_studentview_button($courseid) {
3442 if (isteacheredit($courseid,0,true)) {
3443 if (!empty($USER->studentview
)) {
3444 $svstring = get_string('studentviewoff');
3447 $svstring = get_string('studentviewon');
3450 $button = "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/view.php\">".
3451 "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
3452 "<input type=\"hidden\" name=\"studentview\" value=\"$svedit\" />".
3453 "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />".
3454 "<input type=\"submit\" value=\"$svstring\" /></form>";
3460 * Returns a turn edit on/off button for course in a self contained form.
3461 * Used to be an icon, but it's now a simple form button
3465 * @param int $courseid The course to update by id as found in 'course' table
3468 function update_mymoodle_icon() {
3472 if (!empty($USER->editing
)) {
3473 $string = get_string('updatemymoodleoff');
3476 $string = get_string('updatemymoodleon');
3479 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/my/index.php\">".
3480 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3481 "<input type=\"submit\" value=\"$string\" /></form>";
3485 * Prints the editing button on a module "view" page
3488 * @param type description
3489 * @todo Finish documenting this function
3491 function update_module_button($moduleid, $courseid, $string) {
3494 // do not display if studentview is on
3495 if (!empty($USER->studentview
)) {
3499 if (isteacheredit($courseid)) {
3500 $string = get_string('updatethis', '', $string);
3501 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/mod.php\">".
3502 "<input type=\"hidden\" name=\"update\" value=\"$moduleid\" />".
3503 "<input type=\"hidden\" name=\"return\" value=\"true\" />".
3504 "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />".
3505 "<input type=\"submit\" value=\"$string\" /></form>";
3512 * Prints the editing button on a category page
3516 * @param int $categoryid ?
3518 * @todo Finish documenting this function
3520 function update_category_button($categoryid) {
3524 if (!empty($USER->categoryediting
)) {
3525 $string = get_string('turneditingoff');
3528 $string = get_string('turneditingon');
3531 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/category.php\">".
3532 "<input type=\"hidden\" name=\"id\" value=\"$categoryid\" />".
3533 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3534 "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />".
3535 "<input type=\"submit\" value=\"$string\" /></form>";
3540 * Prints the editing button on categories listing
3546 function update_categories_button() {
3550 if (!empty($USER->categoryediting
)) {
3551 $string = get_string('turneditingoff');
3554 $string = get_string('turneditingon');
3557 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/index.php\">".
3558 '<input type="hidden" name="edit" value="'. $edit .'" />'.
3559 '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />'.
3560 '<input type="submit" value="'. $string .'" /></form>';
3565 * Prints the editing button on search results listing
3566 * For bulk move courses to another category
3569 function update_categories_search_button($search,$page,$perpage) {
3573 if (!empty($USER->categoryediting
)) {
3574 $string = get_string("turneditingoff");
3578 $string = get_string("turneditingon");
3581 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/search.php\">".
3582 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3583 "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />".
3584 "<input type=\"hidden\" name=\"search\" value=\"".s($search, true)."\" />".
3585 "<input type=\"hidden\" name=\"page\" value=\"$page\" />".
3586 "<input type=\"hidden\" name=\"perpage\" value=\"$perpage\" />".
3587 "<input type=\"submit\" value=\"".s($string)."\" /></form>";
3592 * Prints the editing button on group page
3596 * @param int $courseid The course group is associated with
3597 * @param int $groupid The group to update
3600 function update_group_button($courseid, $groupid) {
3603 if (isteacheredit($courseid)) {
3604 $string = get_string('editgroupprofile');
3605 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/group.php\">".
3606 '<input type="hidden" name="id" value="'. $courseid .'" />'.
3607 '<input type="hidden" name="group" value="'. $groupid .'" />'.
3608 '<input type="hidden" name="edit" value="on" />'.
3609 '<input type="submit" value="'. $string .'" /></form>';
3614 * Prints the editing button on groups page
3618 * @param int $courseid The id of the course to be edited
3620 * @todo Finish documenting this function
3622 function update_groups_button($courseid) {
3625 if (isteacheredit($courseid)) {
3626 if (!empty($USER->groupsediting
)) {
3627 $string = get_string('turneditingoff');
3630 $string = get_string('turneditingon');
3633 return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/groups.php\">".
3634 "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
3635 "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
3636 "<input type=\"submit\" value=\"$string\" /></form>";
3641 * Prints an appropriate group selection menu
3643 * @uses VISIBLEGROUPS
3644 * @param array $groups ?
3645 * @param int $groupmode ?
3646 * @param string $currentgroup ?
3647 * @param string $urlroot ?
3648 * @param boolean $showall: if set to 0, it is a student in separate groups, do not display all participants
3649 * @todo Finish documenting this function
3651 function print_group_menu($groups, $groupmode, $currentgroup, $urlroot, $showall=1) {
3653 /// Add an "All groups" to the start of the menu
3655 $groupsmenu[0] = get_string('allparticipants');
3657 foreach ($groups as $key => $groupname) {
3658 $groupsmenu[$key] = $groupname;
3661 echo '<table><tr><td align="right">';
3662 if ($groupmode == VISIBLEGROUPS
) {
3663 print_string('groupsvisible');
3665 print_string('groupsseparate');
3668 echo '</td><td nowrap="nowrap" align="left">';
3669 popup_form($urlroot.'&group=', $groupsmenu, 'selectgroup', $currentgroup, '', '', '', false, 'self');
3670 echo '</td></tr></table>';
3675 * Given a course and a (current) coursemodule
3676 * This function returns a small popup menu with all the
3677 * course activity modules in it, as a navigation menu
3678 * The data is taken from the serialised array stored in
3681 * @param course $course A {@link $COURSE} object.
3682 * @param course $cm A {@link $COURSE} object.
3683 * @param string $targetwindow ?
3685 * @todo Finish documenting this function
3687 function navmenu($course, $cm=NULL, $targetwindow='self') {
3689 global $CFG, $THEME;
3691 if (empty($THEME->navmenuwidth
)) {
3694 $width = $THEME->navmenuwidth
;
3701 if ($course->format
== 'weeks') {
3702 $strsection = get_string('week');
3704 $strsection = get_string('topic');
3706 $strjumpto = get_string('jumpto');
3708 if (!$modinfo = unserialize($course->modinfo
)) {
3711 $isteacher = isteacher($course->id
);
3715 $previousmod = NULL;
3723 $sections = get_records('course_sections','course',$course->id
,'section','section,visible,summary');
3725 if (!empty($THEME->makenavmenulist
)) { /// A hack to produce an XHTML navmenu list for use in themes
3726 $THEME->navmenulist
= navmenulist($course, $sections, $modinfo,
3727 $isteacher, $strsection, $strjumpto, $width, $cm);
3730 foreach ($modinfo as $mod) {
3731 if ($mod->mod
== 'label') {
3735 if ($mod->section
> $course->numsections
) { /// Don't show excess hidden sections
3739 if ($mod->section
> 0 and $section <> $mod->section
) {
3740 $thissection = $sections[$mod->section
];
3742 if ($thissection->visible
or !$course->hiddensections
or $isteacher) {
3743 $thissection->summary
= strip_tags(format_string($thissection->summary
,true));
3744 if ($course->format
== 'weeks' or empty($thissection->summary
)) {
3745 $menu[] = '-------------- '. $strsection ." ". $mod->section
.' --------------';
3747 if (strlen($thissection->summary
) < ($width-3)) {
3748 $menu[] = '-- '.$thissection->summary
;
3750 $menu[] = '-- '.substr($thissection->summary
, 0, $width).'...';
3756 $section = $mod->section
;
3758 //Only add visible or teacher mods to jumpmenu
3759 if ($mod->visible
or $isteacher) {
3760 $url = $mod->mod
.'/view.php?id='. $mod->cm
;
3761 if ($flag) { // the current mod is the "next" mod
3765 if ($cm == $mod->cm
) {
3768 $backmod = $previousmod;
3769 $flag = true; // set flag so we know to use next mod for "next"
3770 $mod->name
= $strjumpto;
3773 $mod->name
= strip_tags(format_string(urldecode($mod->name
),true));
3774 if (strlen($mod->name
) > ($width+
5)) {
3775 $mod->name
= substr($mod->name
, 0, $width).'...';
3777 if (!$mod->visible
) {
3778 $mod->name
= '('.$mod->name
.')';
3781 $menu[$url] = $mod->name
;
3782 $previousmod = $mod;
3785 if ($selectmod and $isteacher) {
3786 $logslink = "<td><a target=\"$CFG->framename\" href=".
3787 "\"$CFG->wwwroot/course/report/log/index.php?chooselog=1&user=0&date=0&id=$course->id&modid=$selectmod->cm\">".
3788 "<img border=\"0\" height=\"16\" width=\"16\" src=\"$CFG->pixpath/i/log.gif\" alt=\"\" /></a></td>";
3792 $backmod = "<form action=\"$CFG->wwwroot/mod/$backmod->mod/view.php\" target=\"$CFG->framename\">".
3793 "<input type=\"hidden\" name=\"id\" value=\"$backmod->cm\" />".
3794 "<input type=\"submit\" value=\"<\" /></form>";
3797 $nextmod = "<form action=\"$CFG->wwwroot/mod/$nextmod->mod/view.php\" target=\"$CFG->framename\">".
3798 "<input type=\"hidden\" name=\"id\" value=\"$nextmod->cm\" />".
3799 "<input type=\"submit\" value=\">\" /></form>";
3802 return '<table><tr>'.$logslink .'<td>'. $backmod .'</td><td>' .
3803 popup_form($CFG->wwwroot
.'/mod/', $menu, 'navmenu', $selected, $strjumpto,
3804 '', '', true, $targetwindow).
3805 '</td><td>'. $nextmod .'</td></tr></table>';
3810 * This function returns a small popup menu with all the
3811 * course activity modules in it, as a navigation menu
3812 * outputs a simple list structure in XHTML
3813 * The data is taken from the serialised array stored in
3816 * @param course $course A {@link $COURSE} object.
3818 * @todo Finish documenting this function
3820 function navmenulist($course, $sections, $modinfo, $isteacher, $strsection, $strjumpto, $width=50, $cmid=0) {
3827 $previousmod = NULL;
3835 $menu[] = '<ul class="navmenulist"><li class="jumpto section"><span>'.$strjumpto.'</span><ul>';
3836 foreach ($modinfo as $mod) {
3837 if ($mod->mod
== 'label') {
3841 if ($mod->section
> $course->numsections
) { /// Don't show excess hidden sections
3845 if ($mod->section
>= 0 and $section <> $mod->section
) {
3846 $thissection = $sections[$mod->section
];
3848 if ($thissection->visible
or !$course->hiddensections
or $isteacher) {
3849 $thissection->summary
= strip_tags(format_string($thissection->summary
,true));
3850 if (!empty($doneheading)) {
3851 $menu[] = '</ul></li>';
3853 if ($course->format
== 'weeks' or empty($thissection->summary
)) {
3854 $item = $strsection ." ". $mod->section
;
3856 if (strlen($thissection->summary
) < ($width-3)) {
3857 $item = $thissection->summary
;
3859 $item = substr($thissection->summary
, 0, $width).'...';
3862 $menu[] = '<li class="section"><span>'.$item.'</span>';
3864 $doneheading = true;
3868 $section = $mod->section
;
3870 //Only add visible or teacher mods to jumpmenu
3871 if ($mod->visible
or $isteacher) {
3872 $url = $mod->mod
.'/view.php?id='. $mod->cm
;
3873 if ($flag) { // the current mod is the "next" mod
3877 $mod->name
= strip_tags(format_string(urldecode($mod->name
),true));
3878 if (strlen($mod->name
) > ($width+
5)) {
3879 $mod->name
= substr($mod->name
, 0, $width).'...';
3881 if (!$mod->visible
) {
3882 $mod->name
= '('.$mod->name
.')';
3884 $class = 'activity '.$mod->mod
;
3885 $class .= ($cmid == $mod->cm
) ?
' selected' : '';
3886 $menu[] = '<li class="'.$class.'">'.
3887 '<img src="'.$CFG->modpixpath
.'/'.$mod->mod
.'/icon.gif" border="0" />'.
3888 '<a href="'.$CFG->wwwroot
.'/mod/'.$url.'">'.$mod->name
.'</a></li>';
3889 $previousmod = $mod;
3893 $menu[] = '</ul></li>';
3895 $menu[] = '</ul></li></ul>';
3897 return implode("\n", $menu);
3901 * Prints form items with the names $day, $month and $year
3903 * @param string $day fieldname
3904 * @param string $month fieldname
3905 * @param string $year fieldname
3906 * @param int $currenttime A default timestamp in GMT
3907 * @param boolean $return
3909 function print_date_selector($day, $month, $year, $currenttime=0, $return=false) {
3911 if (!$currenttime) {
3912 $currenttime = time();
3914 $currentdate = usergetdate($currenttime);
3916 for ($i=1; $i<=31; $i++
) {
3919 for ($i=1; $i<=12; $i++
) {
3920 $months[$i] = userdate(gmmktime(12,0,0,$i,1,2000), "%B");
3922 for ($i=1970; $i<=2020; $i++
) {
3925 return choose_from_menu($days, $day, $currentdate['mday'], '', '', '0', $return)
3926 .choose_from_menu($months, $month, $currentdate['mon'], '', '', '0', $return)
3927 .choose_from_menu($years, $year, $currentdate['year'], '', '', '0', $return);
3932 *Prints form items with the names $hour and $minute
3934 * @param string $hour fieldname
3935 * @param string ? $minute fieldname
3936 * @param $currenttime A default timestamp in GMT
3937 * @param int $step minute spacing
3938 * @param boolean $return
3940 function print_time_selector($hour, $minute, $currenttime=0, $step=5, $return=false) {
3942 if (!$currenttime) {
3943 $currenttime = time();
3945 $currentdate = usergetdate($currenttime);
3947 $currentdate['minutes'] = ceil($currentdate['minutes']/$step)*$step;
3949 for ($i=0; $i<=23; $i++
) {
3950 $hours[$i] = sprintf("%02d",$i);
3952 for ($i=0; $i<=59; $i+
=$step) {
3953 $minutes[$i] = sprintf("%02d",$i);
3956 return choose_from_menu($hours, $hour, $currentdate['hours'], '','','0',$return)
3957 .choose_from_menu($minutes, $minute, $currentdate['minutes'], '','','0',$return);
3961 * Prints time limit value selector
3964 * @param int $timelimit default
3965 * @param string $unit
3966 * @param string $name
3967 * @param boolean $return
3969 function print_timer_selector($timelimit = 0, $unit = '', $name = 'timelimit', $return=false) {
3977 // Max timelimit is sessiontimeout - 10 minutes.
3978 $maxvalue = ($CFG->sessiontimeout
/ 60) - 10;
3980 for ($i=1; $i<=$maxvalue; $i++
) {
3981 $minutes[$i] = $i.$unit;
3983 return choose_from_menu($minutes, $name, $timelimit, get_string('none'), '','','0',$return);
3987 * Prints a grade menu (as part of an existing form) with help
3988 * Showing all possible numerical grades and scales
3991 * @param int $courseid ?
3992 * @param string $name ?
3993 * @param string $current ?
3994 * @param boolean $includenograde ?
3995 * @todo Finish documenting this function
3997 function print_grade_menu($courseid, $name, $current, $includenograde=true) {
4001 $strscale = get_string('scale');
4002 $strscales = get_string('scales');
4004 $scales = get_scales_menu($courseid);
4005 foreach ($scales as $i => $scalename) {
4006 $grades[-$i] = $strscale .': '. $scalename;
4008 if ($includenograde) {
4009 $grades[0] = get_string('nograde');
4011 for ($i=100; $i>=1; $i--) {
4014 choose_from_menu($grades, $name, $current, '');
4016 $linkobject = '<span class="helplink"><img height="17" width="17" alt="'.$strscales.'" src="'.$CFG->pixpath
.'/help.gif" /></span>';
4017 link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true', 'ratingscales',
4018 $linkobject, 400, 500, $strscales);
4022 * Prints a scale menu (as part of an existing form) including help button
4023 * Just like {@link print_grade_menu()} but without the numeric grades
4025 * @param int $courseid ?
4026 * @param string $name ?
4027 * @param string $current ?
4028 * @todo Finish documenting this function
4030 function print_scale_menu($courseid, $name, $current) {
4034 $strscales = get_string('scales');
4035 choose_from_menu(get_scales_menu($courseid), $name, $current, '');
4037 $linkobject = '<span class="helplink"><img height="17" width="17" alt="'.$strscales.'" src="'.$CFG->pixpath
.'/help.gif" /></span>';
4038 link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true', 'ratingscales',
4039 $linkobject, 400, 500, $strscales);
4043 * Prints a help button about a scale
4046 * @param id $courseid ?
4047 * @param object $scale ?
4048 * @todo Finish documenting this function
4050 function print_scale_menu_helpbutton($courseid, $scale) {
4054 $strscales = get_string('scales');
4056 $linkobject = '<span class="helplink"><img height="17" width="17" alt="'.$scale->name
.'" src="'.$CFG->pixpath
.'/help.gif" /></span>';
4057 link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true&scaleid='. $scale->id
, 'ratingscale',
4058 $linkobject, 400, 500, $scale->name
);
4062 * Print an error page displaying an error message.
4063 * Old method, don't call directly in new code - use print_error instead.
4068 * @param string $message The message to display to the user about the error.
4069 * @param string $link The url where the user will be prompted to continue. If no url is provided the user will be directed to the site index page.
4071 function error ($message, $link='') {
4072 global $CFG, $SESSION;
4074 if (! defined('HEADER_PRINTED')) {
4075 //header not yet printed
4076 @header
('HTTP/1.0 404 Not Found');
4077 print_header(get_string('error'));
4082 $message = clean_text($message); // In case nasties are in here
4084 print_simple_box($message, '', '', '', '', 'errorbox');
4087 if ( !empty($SESSION->fromurl
) ) {
4088 $link = $SESSION->fromurl
;
4089 unset($SESSION->fromurl
);
4091 $link = $CFG->wwwroot
.'/';
4094 print_continue($link);
4096 for ($i=0;$i<512;$i++
) { // Padding to help IE work with 404
4103 * Print an error page displaying an error message. New method - use this for new code.
4107 * @param string $errorcode The name of the string from error.php to print
4108 * @param string $link The url where the user will be prompted to continue. If no url is provided the user will be directed to the site index page.
4109 * @param object $a Extra words and phrases that might be required in the error string
4111 function print_error ($errorcode, $module='', $link='', $a=NULL) {
4115 if (empty($module) ||
$module == 'moodle' ||
$module == 'core') {
4117 $modulelink = 'moodle';
4119 $modulelink = $module;
4122 if (!empty($CFG->errordocroot
)) {
4123 $errordocroot = $CFG->errordocroot
;
4124 } else if (!empty($CFG->docroot
)) {
4125 $errordocroot = $CFG->docroot
;
4127 $errordocroot = 'http://docs.moodle.org';
4130 $message = '<p class="errormessage">'.get_string($errorcode, $module, $a).'</p>'.
4131 '<p class="errorcode">'.
4132 '<a href="'.$errordocroot.'/en/error/'.$modulelink.'/'.$errorcode.'">'.
4133 get_string('moreinformation').'</a></p>';
4134 error($message, $link);
4139 * Print a help button.
4142 * @param string $page The keyword that defines a help page
4143 * @param string $title The title of links, rollover tips, alt tags etc
4144 * 'Help with' (or the language equivalent) will be prefixed and '...' will be stripped.
4145 * @param string $module Which module is the page defined in
4146 * @param mixed $image Use a help image for the link? (true/false/"both")
4147 * @param string $text If defined then this text is used in the page, and
4148 * the $page variable is ignored.
4149 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.
4150 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif
4152 * @todo Finish documenting this function
4154 function helpbutton ($page, $title='', $module='moodle', $image=true, $linktext=false, $text='', $return=false,
4158 if ($module == '') {
4163 //Accessibility: prefix the alt text/title with 'Help with', strip distracting dots '...'
4164 // PLEASE DO NOT CHANGE. ('...' is VERY distracting for non-visual users)
4165 $tooltip = get_string('helpprefix', '', trim($title, ". \t"));
4170 if ($imagetext == '') {
4171 $imagetext = '<img alt="'.$tooltip.'" src="'.
4172 $CFG->pixpath
.'/help.gif" />';
4175 $linkobject .= $title.' ';
4178 $linkobject .= $imagetext;
4181 $linkobject .= $tooltip;
4185 $url = '/help.php?module='. $module .'&text='. s(urlencode($text));
4187 $url = '/help.php?module='. $module .'&file='. $page .'.html';
4190 $link = '<span class="helplink">'.
4191 link_to_popup_window ($url, 'popup', $linkobject, 400, 500, $tooltip, 'none', true).
4202 * Print a help button.
4204 * Prints a special help button that is a link to the "live" emoticon popup
4207 * @param string $form ?
4208 * @param string $field ?
4209 * @todo Finish documenting this function
4211 function emoticonhelpbutton($form, $field) {
4213 global $CFG, $SESSION;
4215 $SESSION->inserttextform
= $form;
4216 $SESSION->inserttextfield
= $field;
4217 $imagetext = '<img src="' . $CFG->pixpath
. '/s/smiley.gif" border="0" align="middle" width="15" height="15" alt=""
4218 class="emoticon" style="margin-left: 7px" />';
4220 helpbutton('emoticons', get_string('helpemoticons'), 'moodle', true, true, '', false, $imagetext);
4224 * Print a message and exit.
4227 * @param string $message ?
4228 * @param string $link ?
4229 * @todo Finish documenting this function
4231 function notice ($message, $link='') {
4234 $message = clean_text($message);
4235 $link = clean_text($link);
4238 if (!empty($_SERVER['HTTP_REFERER'])) {
4239 $link = $_SERVER['HTTP_REFERER'];
4241 $link = $CFG->wwwroot
.'/';
4246 print_simple_box($message, 'center', '50%', '', '20', 'generalbox', 'notice');
4247 print_continue($link);
4248 print_footer(get_site());
4253 * Print a message along with "Yes" and "No" links for the user to continue.
4255 * @param string $message The text to display
4256 * @param string $linkyes The link to take the user to if they choose "Yes"
4257 * @param string $linkno The link to take the user to if they choose "No"
4259 function notice_yesno ($message, $linkyes, $linkno) {
4263 $message = clean_text($message);
4264 $linkyes = clean_text($linkyes);
4265 $linkno = clean_text($linkno);
4267 print_simple_box_start('center', '60%', '', 5, 'generalbox', 'notice');
4268 echo '<p align="center">'. $message .'</p>';
4269 echo '<table align="center" cellpadding="20"><tr><td>';
4270 print_single_button($linkyes, NULL, get_string('yes'), 'post', $CFG->framename
);
4272 print_single_button($linkno, NULL, get_string('no'), 'post', $CFG->framename
);
4273 echo '</td></tr></table>';
4274 print_simple_box_end();
4278 * Redirects the user to another page, after printing a notice
4280 * @param string $url The url to take the user to
4281 * @param string $message The text message to display to the user about the redirect, if any
4282 * @param string $delay How long before refreshing to the new page at $url?
4283 * @todo '&' needs to be encoded into '&' for XHTML compliance,
4284 * however, this is not true for javascript. Therefore we
4285 * first decode all entities in $url (since we cannot rely on)
4286 * the correct input) and then encode for where it's needed
4287 * echo "<script type='text/javascript'>alert('Redirect $url');</script>";
4289 function redirect($url, $message='', $delay=-1) {
4293 //$url = clean_text($url);
4294 if (!empty($CFG->usesid
) && !isset($_COOKIE[session_name()])) {
4295 $url = sid_process_url($url);
4298 $message = clean_text($message);
4300 $url = html_entity_decode($url); // for php < 4.3.0 this is defined in moodlelib.php
4301 $url = str_replace(array("\n", "\r"), '', $url); // some more cleaning
4302 $encodedurl = htmlentities($url);
4303 $tmpstr = clean_text('<a href="'.$encodedurl.'" />'); //clean encoded URL
4304 $encodedurl = substr($tmpstr, 9, strlen($tmpstr)-13);
4305 $url = addslashes(html_entity_decode($encodedurl));
4307 /// when no message and header printed yet, try to redirect
4308 if (empty($message) and !defined('HEADER_PRINTED')) {
4312 echo '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />';
4313 echo '<script type="text/javascript">'. "\n" .'<!--'. "\n". "location.replace('$url');". "\n". '//-->'. "\n". '</script>'; // To cope with Mozilla bug
4318 $delay = 3; // if no delay specified wait 3 seconds
4320 if (! defined('HEADER_PRINTED')) {
4321 print_header('', '', '', '', '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />');
4324 echo '<p>'. $message .'</p>';
4325 echo '<p>( <a href="'. $encodedurl .'">'. get_string('continue') .'</a> )</p>';
4329 <script type
="text/javascript">
4332 function redirect() {
4333 document
.location
.replace('<?php echo $url ?>');
4335 setTimeout("redirect()", <?php
echo ($delay * 1000) ?
>);
4343 * Print a bold message in an optional color.
4345 * @param string $message The message to print out
4346 * @param string $style Optional style to display message text in
4347 * @param string $align Alignment option
4348 * @param bool $return whether to return an output string or echo now
4350 function notify($message, $style='notifyproblem', $align='center', $return=false) {
4351 if ($style == 'green') {
4352 $style = 'notifysuccess'; // backward compatible with old color system
4355 $message = clean_text($message);
4357 $output = '<div class="'.$style.'" align="'. $align .'">'. $message .'</div>'."<br />\n";
4367 * Given an email address, this function will return an obfuscated version of it
4369 * @param string $email The email address to obfuscate
4372 function obfuscate_email($email) {
4375 $length = strlen($email);
4377 while ($i < $length) {
4379 $obfuscated.='%'.dechex(ord($email{$i}));
4381 $obfuscated.=$email{$i};
4389 * This function takes some text and replaces about half of the characters
4390 * with HTML entity equivalents. Return string is obviously longer.
4392 * @param string $plaintext The text to be obfuscated
4395 function obfuscate_text($plaintext) {
4398 $length = strlen($plaintext);
4400 $prev_obfuscated = false;
4401 while ($i < $length) {
4402 $c = ord($plaintext{$i});
4403 $numerical = ($c >= ord('0')) && ($c <= ord('9'));
4404 if ($prev_obfuscated and $numerical ) {
4405 $obfuscated.='&#'.ord($plaintext{$i}).';';
4406 } else if (rand(0,2)) {
4407 $obfuscated.='&#'.ord($plaintext{$i}).';';
4408 $prev_obfuscated = true;
4410 $obfuscated.=$plaintext{$i};
4411 $prev_obfuscated = false;
4419 * This function uses the {@link obfuscate_email()} and {@link obfuscate_text()}
4420 * to generate a fully obfuscated email link, ready to use.
4422 * @param string $email The email address to display
4423 * @param string $label The text to dispalyed as hyperlink to $email
4424 * @param boolean $dimmed If true then use css class 'dimmed' for hyperlink
4427 function obfuscate_mailto($email, $label='', $dimmed=false) {
4429 if (empty($label)) {
4433 $title = get_string('emaildisable');
4434 $dimmed = ' class="dimmed"';
4439 return sprintf("<a href=\"%s:%s\" $dimmed title=\"$title\">%s</a>",
4440 obfuscate_text('mailto'), obfuscate_email($email),
4441 obfuscate_text($label));
4445 * Prints a single paging bar to provide access to other pages (usually in a search)
4447 * @param int $totalcount Thetotal number of entries available to be paged through
4448 * @param int $page The page you are currently viewing
4449 * @param int $perpage The number of entries that should be shown per page
4450 * @param string $baseurl The url which will be used to create page numbered links. Each page will consist of the base url appended by the page
4451 var an equal sign, then the page number.
4452 * @param string $pagevar This is the variable name that you use for the page number in your code (ie. 'tablepage', 'blogpage', etc)
4454 function print_paging_bar($totalcount, $page, $perpage, $baseurl, $pagevar='page',$nocurr=false) {
4458 if ($totalcount > $perpage) {
4459 echo '<div class="paging">';
4460 echo get_string('page') .':';
4462 $pagenum = $page - 1;
4463 echo ' (<a href="'. $baseurl . $pagevar .'='. $pagenum .'">'. get_string('previous') .'</a>) ';
4465 $lastpage = ceil($totalcount / $perpage);
4467 $startpage = $page - 10;
4468 echo ' <a href="'. $baseurl . $pagevar .'=0">1</a> ...';
4472 $currpage = $startpage;
4474 while ($displaycount < $maxdisplay and $currpage < $lastpage) {
4475 $displaypage = $currpage+
1;
4476 if ($page == $currpage && empty($nocurr)) {
4477 echo ' '. $displaypage;
4479 echo ' <a href="'. $baseurl . $pagevar .'='. $currpage .'">'. $displaypage .'</a>';
4484 if ($currpage < $lastpage) {
4485 $lastpageactual = $lastpage - 1;
4486 echo ' ...<a href="'. $baseurl . $pagevar .'='. $lastpageactual .'">'. $lastpage .'</a> ';
4488 $pagenum = $page +
1;
4489 if ($pagenum != $displaypage) {
4490 echo ' (<a href="'. $baseurl . $pagevar .'='. $pagenum .'">'. get_string('next') .'</a>)';
4497 * This function is used to rebuild the <nolink> tag because some formats (PLAIN and WIKI)
4498 * will transform it to html entities
4500 * @param string $text Text to search for nolink tag in
4503 function rebuildnolinktag($text) {
4505 $text = preg_replace('/<(\/*nolink)>/i','<$1>',$text);
4511 * Prints a nice side block with an optional header. The content can either
4512 * be a block of HTML or a list of text with optional icons.
4514 * @param string $heading ?
4515 * @param string $content ?
4516 * @param array $list ?
4517 * @param array $icons ?
4518 * @param string $footer ?
4519 * @param array $attributes ?
4520 * @todo Finish documenting this function. Show example of various attributes, etc.
4522 function print_side_block($heading='', $content='', $list=NULL, $icons=NULL, $footer='', $attributes = array()) {
4524 //Accessibility: skip block link, with $block_id to differentiate links.
4525 static $block_id = 0;
4527 $skip_text = get_string('skipblock','access').' '.$block_id;
4528 $skip_link = '<a href="#sb-'.$block_id.'" class="skip-block" title="'.$skip_text.'"><span class="accesshide">'.$skip_text.'</span></a>';
4529 $skip_dest = '<span id="sb-'.$block_id.'" class="skip-block-to"></span>';
4530 if (! empty($heading)) {
4531 $heading .= $skip_link;
4536 print_side_block_start($heading, $attributes);
4541 echo '<div class="footer">'. $footer .'</div>';
4546 //Accessibility: replaced unnecessary table with list, see themes/standard/styles_layout.css
4547 echo "\n<ul class='list'>\n";
4548 foreach ($list as $key => $string) {
4549 echo '<li class="r'. $row .'">';
4551 echo '<span class="icon c0">'. $icons[$key] .'</span>';
4553 echo '<span class="c1">'. $string .'</span>';
4560 echo '<div class="footer">'. $footer .'</div>';
4565 print_side_block_end($attributes);
4570 * Starts a nice side block with an optional header.
4572 * @param string $heading ?
4573 * @param array $attributes ?
4574 * @todo Finish documenting this function
4576 function print_side_block_start($heading='', $attributes = array()) {
4580 // If there are no special attributes, give a default CSS class
4581 if (empty($attributes) ||
!is_array($attributes)) {
4582 $attributes = array('class' => 'sideblock');
4584 } else if(!isset($attributes['class'])) {
4585 $attributes['class'] = 'sideblock';
4587 } else if(!strpos($attributes['class'], 'sideblock')) {
4588 $attributes['class'] .= ' sideblock';
4591 // OK, the class is surely there and in addition to anything
4592 // else, it's tagged as a sideblock
4596 // IE misery: if I do it this way, blocks which start hidden cannot be "unhidden"
4598 // If there is a cookie to hide this thing, start it hidden
4599 if (!empty($attributes['id']) && isset($_COOKIE['hide:'.$attributes['id']])) {
4600 $attributes['class'] = 'hidden '.$attributes['class'];
4605 foreach ($attributes as $attr => $val) {
4606 $attrtext .= ' '.$attr.'="'.$val.'"';
4609 echo '<div '.$attrtext.'>';
4611 //Accessibility: replaced <div> with H2; no, H2 more appropriate in moodleblock.class.php: _title_html.
4612 echo '<div class="header">'.$heading.'</div>';
4614 echo '<div class="content">';
4620 * Print table ending tags for a side block box.
4622 function print_side_block_end($attributes = array()) {
4625 echo '</div></div>';
4627 // IE workaround: if I do it THIS way, it works! WTF?
4628 if (!empty($CFG->allowuserblockhiding
) && isset($attributes['id'])) {
4629 echo '<script type="text/javascript"><!-- '."\n".'elementCookieHide("'.$attributes['id'].'"); '."\n".'--></script>';
4636 * Prints out code needed for spellchecking.
4637 * Original idea by Ludo (Marc Alier).
4640 * @param boolean $usehtmleditor ?
4641 * @todo Finish documenting this function
4643 function print_speller_code ($usehtmleditor=false, $return=false) {
4647 if(!$usehtmleditor) {
4648 $str .= "\n".'<script language="javascript" type="text/javascript">'."\n";
4649 $str .= 'function openSpellChecker() {'."\n";
4650 $str .= "\tvar speller = new spellChecker();\n";
4651 $str .= "\tspeller.popUpUrl = \"" . $CFG->wwwroot
."/lib/speller/spellchecker.html\";\n";
4652 $str .= "\tspeller.spellCheckScript = \"". $CFG->wwwroot
."/lib/speller/server-scripts/spellchecker.php\";\n";
4653 $str .= "\tspeller.spellCheckAll();\n";
4655 $str .= '</script>'."\n";
4657 $str .= "\nfunction spellClickHandler(editor, buttonId) {\n";
4658 $str .= "\teditor._textArea.value = editor.getHTML();\n";
4659 $str .= "\tvar speller = new spellChecker( editor._textArea );\n";
4660 $str .= "\tspeller.popUpUrl = \"" . $CFG->wwwroot
."/lib/speller/spellchecker.html\";\n";
4661 $str .= "\tspeller.spellCheckScript = \"". $CFG->wwwroot
."/lib/speller/server-scripts/spellchecker.php\";\n";
4662 $str .= "\tspeller._moogle_edit=1;\n";
4663 $str .= "\tspeller._editor=editor;\n";
4664 $str .= "\tspeller.openChecker();\n";
4674 * Print button for spellchecking when editor is disabled
4676 function print_speller_button () {
4677 echo '<input type="button" value="Check spelling" onclick="openSpellChecker();" />'."\n";
4681 function page_id_and_class(&$getid, &$getclass) {
4682 // Create class and id for this page
4685 static $class = NULL;
4688 if (empty($CFG->pagepath
)) {
4689 $CFG->pagepath
= $ME;
4692 if (empty($class) ||
empty($id)) {
4693 $path = str_replace($CFG->httpswwwroot
.'/', '', $CFG->pagepath
); //Because the page could be HTTPSPAGEREQUIRED
4694 $path = str_replace('.php', '', $path);
4695 if (substr($path, -1) == '/') {
4698 if (empty($path) ||
$path == 'index') {
4701 } else if (substr($path, 0, 5) == 'admin') {
4702 $id = str_replace('/', '-', $path);
4705 $id = str_replace('/', '-', $path);
4706 $class = explode('-', $id);
4708 $class = implode('-', $class);
4717 * Prints a maintenance message from /maintenance.html
4719 function print_maintenance_message () {
4722 print_header(strip_tags($SITE->fullname
), $SITE->fullname
, 'home');
4723 print_simple_box_start('center');
4724 print_heading(get_string('sitemaintenance', 'admin'));
4725 @include
($CFG->dataroot
.'/1/maintenance.html');
4726 print_simple_box_end();
4731 * Adjust the list of allowed tags based on $CFG->allowobjectembed and user roles (admin)
4733 function adjust_allowed_tags() {
4735 global $CFG, $ALLOWED_TAGS;
4737 if (!empty($CFG->allowobjectembed
)) {
4738 $ALLOWED_TAGS .= '<embed><object>';
4742 /// Some code to print tabs
4744 /// A class for tabs
4749 var $linkedwhenselected;
4751 /// A constructor just because I like constructors
4752 function tabobject ($id, $link='', $text='', $title='', $linkedwhenselected=false) {
4754 $this->link
= $link;
4755 $this->text
= $text;
4756 $this->title
= $title ?
$title : $text;
4757 $this->linkedwhenselected
= $linkedwhenselected;
4761 /// a method to look after the messy business of setting up a tab cell
4762 /// with all the appropriate classes and things
4763 function createtab ($selected=false, $inactive=false, $activetwo=false, $last=false) {
4768 /// The text and anchor for this tab
4769 if ($inactive ||
$activetwo ||
($selected && !$this->linkedwhenselected
)) {
4770 $astr .= $this->text
;
4772 $astr .= '<a href="'.$this->link
.'" title="'.$this->title
.'">'.$this->text
.'</a>';
4775 /// There's an IE bug with background images in <a> tags
4776 /// so we put a div around so that we can add a background image
4777 $astr = '<div class="tablink">'.$astr.'</div>';
4779 /// Set the class for inactive cells
4781 $cstr .= ' inactive';
4783 /// Set the class for active cells in the second row
4785 $cstr .= ' activetwo';
4788 /// Set the class for the selected cell
4789 } else if ($selected) {
4790 $cstr .= ' selected';
4792 /// Set the standard class for a cell
4798 /// Are we on the last tab in this row?
4800 $astr = '<div class="last">'.$astr.'</div>';
4803 /// Lets set up the tab cell
4805 if (!empty($cstr)) {
4806 $str .= ' class="'.ltrim($cstr).'"';
4820 * Returns a string containing a table with tabs inside and formatted with
4823 * @param array $tabrows An array of rows where each row is an array of tab objects
4824 * @param string $selected The id of the selected tab
4825 * @param array $inactive Ids of inactive tabs
4827 function print_tabs($tabrows, $selected=NULL, $inactive=NULL, $activetwo=NULL, $return=false) {
4830 /// Bring the row with the selected tab to the front
4831 if (!empty($CFG->tabselectedtofront
) and ($selected !== NULL) ) {
4833 $frontrows = array();
4834 $rearrows = array();
4835 foreach ($tabrows as $row) {
4839 foreach ($row as $tab) {
4843 $found = ($selected == $tab->id
);
4845 $frontrows[] = $row;
4848 $tabrows = array_merge($rearrows,$frontrows);
4851 /// $inactive must be an array
4852 if (!is_array($inactive)) {
4853 $inactive = array();
4856 /// $activetwo must be an array
4857 if (!is_array($activetwo)) {
4858 $activetwo = array();
4861 /// A table to encapsulate the tabs
4862 $str = '<table class="tabs" cellspacing="0">';
4863 $str .= '<tr><td class="left side"></td><td>';
4865 $rowcount = count($tabrows);
4866 /// Cycle through the tab rows
4867 foreach ($tabrows as $row) {
4871 $str .= '<table class="tabrow r'.$rowcount.'" cellspacing="0">';
4874 $numberoftabs = count($row);
4880 /// Cycle through the tabs
4881 foreach ($row as $tab) {
4884 $str .= $tab->createtab( ($selected == $tab->id
), (in_array($tab->id
, $inactive)), (in_array($tab->id
, $activetwo)), ($currenttab == $numberoftabs) );
4890 $str .= '</td><td class="right side"></td></tr>';
4901 * Returns a string containing a link to the user documentation for the current
4902 * page. Also contains an icon by default. Shown to teachers and admin only.
4904 * @param string $text The text to be displayed for the link
4905 * @param string $iconpath The path to the icon to be displayed
4907 function page_doc_link($text='', $iconpath='') {
4910 if (empty($CFG->docroot
) ||
!isteacherinanycourse()) {
4914 if (empty($CFG->pagepath
)) {
4915 $CFG->pagepath
= $ME;
4919 if (!empty($CFG->doctonewwindow
)) {
4920 $target = ' target="_blank"';
4923 $path = str_replace($CFG->httpswwwroot
.'/','', $CFG->pagepath
); // Because the page could be HTTPSPAGEREQUIRED
4924 $path = str_replace('.php', '', $path);
4926 if (empty($path)) { // Not for home page
4930 $lang = str_replace('_utf8', '', current_language());
4932 $str = '<a href="' .$CFG->docroot
. '/' .$lang. '/' .$path. '"' .$target. '>';
4934 if (empty($iconpath)) {
4935 $iconpath = $CFG->wwwroot
. '/pix/docs.gif';
4938 $str .= '<img src="' .$iconpath. '" alt="Docs" />' .$text. '</a>';
4944 // vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140: