libdir/filterlib.php"); require_once("$CFG->libdir/ajax/ajaxlib.php"); /// Constants /// Define text formatting types ... eventually we can add Wiki, BBcode etc /** * Does all sorts of transformations and filtering */ define('FORMAT_MOODLE', '0'); // Does all sorts of transformations and filtering /** * Plain HTML (with some tags stripped) */ define('FORMAT_HTML', '1'); // Plain HTML (with some tags stripped) /** * Plain text (even tags are printed in full) */ define('FORMAT_PLAIN', '2'); // Plain text (even tags are printed in full) /** * Wiki-formatted text * Deprecated: left here just to note that '3' is not used (at the moment) * and to catch any latent wiki-like text (which generates an error) */ define('FORMAT_WIKI', '3'); // Wiki-formatted text /** * Markdown-formatted text http://daringfireball.net/projects/markdown/ */ define('FORMAT_MARKDOWN', '4'); // Markdown-formatted text http://daringfireball.net/projects/markdown/ /** * TRUSTTEXT marker - if present in text, text cleaning should be bypassed */ define('TRUSTTEXT', '#####TRUSTTEXT#####'); /** * Javascript related defines */ define('REQUIREJS_BEFOREHEADER', 0); define('REQUIREJS_INHEADER', 1); define('REQUIREJS_AFTERHEADER', 2); /** * Allowed tags - string of html tags that can be tested against for safe html tags * @global string $ALLOWED_TAGS */ global $ALLOWED_TAGS; $ALLOWED_TAGS = '
'.
''.
get_string('moreinformation').' '. $message .' " . $message;
}
$performanceinfo = '';
if (defined('MDL_PERF') || (!empty($CFG->perfdebug) and $CFG->perfdebug > 7)) {
if (defined('MDL_PERFTOLOG') && !function_exists('register_shutdown_function')) {
$perf = get_performance_info();
error_log("PERF: " . $perf['txt']);
}
}
/// when no message and header printed yet, try to redirect
if (empty($message) and !defined('HEADER_PRINTED')) {
// Technically, HTTP/1.1 requires Location: header to contain
// the absolute path. (In practice browsers accept relative
// paths - but still, might as well do it properly.)
// This code turns relative into absolute.
if (!preg_match('|^[a-z]+:|', $url)) {
// Get host name http://www.wherever.com
$hostpart = preg_replace('|^(.*?[^:/])/.*$|', '$1', $CFG->wwwroot);
if (preg_match('|^/|', $url)) {
// URLs beginning with / are relative to web server root so we just add them in
$url = $hostpart.$url;
} else {
// URLs not beginning with / are relative to path of current script, so add that on.
$url = $hostpart.preg_replace('|\?.*$|','',me()).'/../'.$url;
}
// Replace all ..s
while (true) {
$newurl = preg_replace('|/(?!\.\.)[^/]*/\.\./|', '/', $url);
if ($newurl == $url) {
break;
}
$url = $newurl;
}
}
$delay = 0;
//try header redirection first
@header($_SERVER['SERVER_PROTOCOL'] . ' 303 See Other'); //302 might not work for POST requests, 303 is ignored by obsolete clients
@header('Location: '.$url);
//another way for older browsers and already sent headers (eg trailing whitespace in config.php)
echo '';
print_js_call('document.location.replace', array($url));
die;
}
if ($delay == -1) {
$delay = 3; // if no delay specified wait 3 seconds
}
if (! defined('HEADER_PRINTED')) {
// this type of redirect might not be working in some browsers - such as lynx :-(
print_header('', '', '', '', $errorprinted ? '' : (''));
$delay += 3; // double redirect prevention, it was sometimes breaking upgrades before 1.7
} else {
print_container_end_all(false, $THEME->open_header_containers);
}
echo '';
return implode("\n", $menu);
}
/**
* Prints form items with the names $day, $month and $year
*
* @param string $day fieldname
* @param string $month fieldname
* @param string $year fieldname
* @param int $currenttime A default timestamp in GMT
* @param boolean $return
*/
function print_date_selector($day, $month, $year, $currenttime=0, $return=false) {
if (!$currenttime) {
$currenttime = time();
}
$currentdate = usergetdate($currenttime);
for ($i=1; $i<=31; $i++) {
$days[$i] = $i;
}
for ($i=1; $i<=12; $i++) {
$months[$i] = userdate(gmmktime(12,0,0,$i,15,2000), "%B");
}
for ($i=1970; $i<=2020; $i++) {
$years[$i] = $i;
}
return choose_from_menu($days, $day, $currentdate['mday'], '', '', '0', $return)
.choose_from_menu($months, $month, $currentdate['mon'], '', '', '0', $return)
.choose_from_menu($years, $year, $currentdate['year'], '', '', '0', $return);
}
/**
*Prints form items with the names $hour and $minute
*
* @param string $hour fieldname
* @param string ? $minute fieldname
* @param $currenttime A default timestamp in GMT
* @param int $step minute spacing
* @param boolean $return
*/
function print_time_selector($hour, $minute, $currenttime=0, $step=5, $return=false) {
if (!$currenttime) {
$currenttime = time();
}
$currentdate = usergetdate($currenttime);
if ($step != 1) {
$currentdate['minutes'] = ceil($currentdate['minutes']/$step)*$step;
}
for ($i=0; $i<=23; $i++) {
$hours[$i] = sprintf("%02d",$i);
}
for ($i=0; $i<=59; $i+=$step) {
$minutes[$i] = sprintf("%02d",$i);
}
return choose_from_menu($hours, $hour, $currentdate['hours'], '','','0',$return)
.choose_from_menu($minutes, $minute, $currentdate['minutes'], '','','0',$return);
}
/**
* Prints time limit value selector
*
* @uses $CFG
* @param int $timelimit default
* @param string $unit
* @param string $name
* @param boolean $return
*/
function print_timer_selector($timelimit = 0, $unit = '', $name = 'timelimit', $return=false) {
global $CFG;
if ($unit) {
$unit = ' '.$unit;
}
// Max timelimit is sessiontimeout - 10 minutes.
$maxvalue = ($CFG->sessiontimeout / 60) - 10;
for ($i=1; $i<=$maxvalue; $i++) {
$minutes[$i] = $i.$unit;
}
return choose_from_menu($minutes, $name, $timelimit, get_string('none'), '','','0',$return);
}
/**
* Prints a grade menu (as part of an existing form) with help
* Showing all possible numerical grades and scales
*
* @uses $CFG
* @param int $courseid ?
* @param string $name ?
* @param string $current ?
* @param boolean $includenograde ?
* @todo Finish documenting this function
*/
function print_grade_menu($courseid, $name, $current, $includenograde=true, $return=false) {
global $CFG;
$output = '';
$strscale = get_string('scale');
$strscales = get_string('scales');
$scales = get_scales_menu($courseid);
foreach ($scales as $i => $scalename) {
$grades[-$i] = $strscale .': '. $scalename;
}
if ($includenograde) {
$grades[0] = get_string('nograde');
}
for ($i=100; $i>=1; $i--) {
$grades[$i] = $i;
}
$output .= choose_from_menu($grades, $name, $current, '', '', 0, true);
$linkobject = '
';
$output .= link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true', 'ratingscales',
$linkobject, 400, 500, $strscales, 'none', true);
if ($return) {
return $output;
} else {
echo $output;
}
}
/**
* Prints a scale menu (as part of an existing form) including help button
* Just like {@link print_grade_menu()} but without the numeric grades
*
* @param int $courseid ?
* @param string $name ?
* @param string $current ?
* @todo Finish documenting this function
*/
function print_scale_menu($courseid, $name, $current, $return=false) {
global $CFG;
$output = '';
$strscales = get_string('scales');
$output .= choose_from_menu(get_scales_menu($courseid), $name, $current, '', '', 0, true);
$linkobject = '
';
$output .= link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true', 'ratingscales',
$linkobject, 400, 500, $strscales, 'none', true);
if ($return) {
return $output;
} else {
echo $output;
}
}
/**
* Prints a help button about a scale
*
* @uses $CFG
* @param id $courseid ?
* @param object $scale ?
* @todo Finish documenting this function
*/
function print_scale_menu_helpbutton($courseid, $scale, $return=false) {
global $CFG;
$output = '';
$strscales = get_string('scales');
$linkobject = '
';
$output .= link_to_popup_window ('/course/scales.php?id='. $courseid .'&list=true&scaleid='. $scale->id, 'ratingscale',
$linkobject, 400, 500, $scale->name, 'none', true);
if ($return) {
return $output;
} else {
echo $output;
}
}
/**
* Print an error page displaying an error message. New method - use this for new code.
*
* @param string $errorcode The name of the string from error.php to print
* @param string $module name of module
* @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.
* @param object $a Extra words and phrases that might be required in the error string
* @return terminates script, does not return!
*/
function print_error($errorcode, $module='error', $link='', $a=NULL) {
global $CFG, $UNITTEST;
// If unittest running, throw exception instead
if (!empty($UNITTEST->running)) {
// Errors in unit test become exceptions, so you can unit test
// code that might call error().
throw new moodle_exception($errorcode, $module, $link, $a);
}
if (empty($module) || $module == 'moodle' || $module == 'core') {
$module = 'error';
}
if (!isset($CFG->theme) or !isset($CFG->stylesheets)) {
// error found before setup.php finished
_print_early_error($errorcode, $module, $a);
} else {
_print_normal_error($errorcode, $module, $a, $link, debug_backtrace());
}
}
/**
* Internal function - do not use directly!!
*/
function _print_normal_error($errorcode, $module, $a, $link, $backtrace, $debuginfo=null, $showerrordebugwarning=false) {
global $CFG, $SESSION, $THEME, $DB;
if ($DB) {
//if you enable db debugging and exception is thrown, the print footer prints a lot of rubbish
$DB->set_debug(0);
}
if ($module === 'error') {
$modulelink = 'moodle';
} else {
$modulelink = $module;
}
$message = get_string($errorcode, $module, $a);
if ($module === 'error' and strpos($message, '[[') === 0) {
//search in moodle file if error specified - needed for backwards compatibility
$message = get_string($errorcode, 'moodle', $a);
}
if (defined('FULLME') && FULLME == 'cron') {
// Errors in cron should be mtrace'd.
mtrace($message);
die;
}
if (empty($link) and !defined('ADMIN_EXT_HEADER_PRINTED')) {
if ( !empty($SESSION->fromurl) ) {
$link = $SESSION->fromurl;
unset($SESSION->fromurl);
} else {
$link = $CFG->wwwroot .'/';
}
}
if (!empty($CFG->errordocroot)) {
$errordocroot = $CFG->errordocroot;
} else if (!empty($CFG->docroot)) {
$errordocroot = $CFG->docroot;
} else {
$errordocroot = 'http://docs.moodle.org';
}
if (! defined('HEADER_PRINTED')) {
//header not yet printed
@header('HTTP/1.0 404 Not Found');
print_header(get_string('error'));
} else {
print_container_end_all(false, $THEME->open_header_containers);
}
echo '
';
$message = clean_text(' '.
'';
return link_to_popup_window(s('/lib/form/editorhelp.php?'.$paramstring), 'popup', $linkobject, 400, 500, $alttag, 'none', true);
}
/**
* Print a help button.
*
* @uses $CFG
* @param string $page The keyword that defines a help page
* @param string $title The title of links, rollover tips, alt tags etc
* 'Help with' (or the language equivalent) will be prefixed and '...' will be stripped.
* @param string $module Which module is the page defined in
* @param mixed $image Use a help image for the link? (true/false/"both")
* @param boolean $linktext If true, display the title next to the help icon.
* @param string $text If defined then this text is used in the page, and
* the $page variable is ignored.
* @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.
* @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif
* @return string
* @todo Finish documenting this function
*/
function helpbutton($page, $title, $module='moodle', $image=true, $linktext=false, $text='', $return=false,
$imagetext='') {
global $CFG, $COURSE;
//warning if ever $text parameter is used
//$text option won't work properly because the text needs to be always cleaned and,
// when cleaned... html tags always break, so it's unusable.
if ( isset($text) && $text!='') {
debugging('Warning: it\'s not recommended to use $text parameter in helpbutton ($page=' . $page . ', $module=' . $module . ') function', DEBUG_DEVELOPER);
}
// fix for MDL-7734
if (!empty($COURSE->lang)) {
$forcelang = $COURSE->lang;
} else {
$forcelang = '';
}
// Catch references to the old text.html and emoticons.html help files that
// were renamed in MDL-13233.
if (in_array($page, array('text', 'emoticons', 'richtext'))) {
$oldname = $page;
$page .= '2';
debugging("You are referring to the old help file '$oldname'. " .
"This was renamed to '$page' becuase of MDL-13233. " .
"Please update your code.", DEBUG_DEVELOPER);
}
if ($module == '') {
$module = 'moodle';
}
if ($title == '' && $linktext == '') {
debugging('Error in call to helpbutton function: at least one of $title and $linktext is required');
}
// Warn users about new window for Accessibility
$tooltip = get_string('helpprefix2', '', trim($title, ". \t")) .' ('.get_string('newwindow').')';
$linkobject = '';
if ($image) {
if ($linktext) {
// MDL-7469 If text link is displayed with help icon, change to alt to "help with this".
$linkobject .= $title.' ';
$tooltip = get_string('helpwiththis');
}
if ($imagetext) {
$linkobject .= $imagetext;
} else {
$linkobject .= '
';
}
} else {
$linkobject .= $tooltip;
}
// fix for MDL-7734
if ($text) {
$url = '/help.php?module='. $module .'&text='. s(urlencode($text).'&forcelang='.$forcelang);
} else {
$url = '/help.php?module='. $module .'&file='. $page .'.html&forcelang='.$forcelang;
}
$link = ''.
link_to_popup_window ($url, 'popup', $linkobject, 400, 500, $tooltip, 'none', true).
'';
if ($return) {
return $link;
} else {
echo $link;
}
}
/**
* Print a help button.
*
* Prints a special help button that is a link to the "live" emoticon popup
* @uses $CFG
* @uses $SESSION
* @param string $form ?
* @param string $field ?
* @todo Finish documenting this function
*/
function emoticonhelpbutton($form, $field, $return = false) {
global $CFG, $SESSION;
$SESSION->inserttextform = $form;
$SESSION->inserttextfield = $field;
$imagetext = '
';
$help = helpbutton('emoticons2', get_string('helpemoticons'), 'moodle', true, true, '', true, $imagetext);
if (!$return){
echo $help;
} else {
return $help;
}
}
/**
* Print a help button.
*
* Prints a special help button for html editors (htmlarea in this case)
* @uses $CFG
*/
function editorshortcutshelpbutton() {
global $CFG;
//TODO: detect current editor and print correct info
/* $imagetext = '
';
return helpbutton('editorshortcuts', get_string('editorshortcutkeys'), 'moodle', true, false, '', true, $imagetext);*/
return '';
}
/**
* Print a message and exit.
*
* @uses $CFG
* @param string $message ?
* @param string $link ?
* @todo Finish documenting this function
*/
function notice ($message, $link='', $course=NULL) {
global $CFG, $SITE, $THEME, $COURSE;
$message = clean_text($message); // In case nasties are in here
if (defined('FULLME') && FULLME == 'cron') {
// notices in cron should be mtrace'd.
mtrace($message);
die;
}
if (! defined('HEADER_PRINTED')) {
//header not yet printed
print_header(get_string('notice'));
} else {
print_container_end_all(false, $THEME->open_header_containers);
}
print_box($message, 'generalbox', 'notice');
print_continue($link);
if (empty($course)) {
print_footer($COURSE);
} else {
print_footer($course);
}
exit;
}
/**
* Print a message along with "Yes" and "No" links for the user to continue.
*
* @param string $message The text to display
* @param string $linkyes The link to take the user to if they choose "Yes"
* @param string $linkno The link to take the user to if they choose "No"
* TODO Document remaining arguments
*/
function notice_yesno ($message, $linkyes, $linkno, $optionsyes=NULL, $optionsno=NULL, $methodyes='post', $methodno='post') {
global $CFG;
$message = clean_text($message);
$linkyes = clean_text($linkyes);
$linkno = clean_text($linkno);
print_box_start('generalbox', 'notice');
echo '
\n";
foreach ($list as $key => $string) {
echo '
\n";
}
}
// Footer, if any.
if ($footer) {
echo ' ';
}
print_side_block_end($attributes, $title);
echo $skip_dest;
}
/**
* Starts a nice side block with an optional header.
*
* @param string $heading HTML for the heading. Can include full HTML or just
* plain text - plain text will automatically be enclosed in the appropriate
* heading tags.
* @param array $attributes ?
* @todo Finish documenting this function
*/
function print_side_block_start($heading='', $attributes = array()) {
global $CFG, $THEME;
// If there are no special attributes, give a default CSS class
if (empty($attributes) || !is_array($attributes)) {
$attributes = array('class' => 'sideblock');
} else if(!isset($attributes['class'])) {
$attributes['class'] = 'sideblock';
} else if(!strpos($attributes['class'], 'sideblock')) {
$attributes['class'] .= ' sideblock';
}
// OK, the class is surely there and in addition to anything
// else, it's tagged as a sideblock
/*
// IE misery: if I do it this way, blocks which start hidden cannot be "unhidden"
// If there is a cookie to hide this thing, start it hidden
if (!empty($attributes['id']) && isset($_COOKIE['hide:'.$attributes['id']])) {
$attributes['class'] = 'hidden '.$attributes['class'];
}
*/
$attrtext = '';
foreach ($attributes as $attr => $val) {
$attrtext .= ' '.$attr.'="'.$val.'"';
}
echo ''.$heading.'