diff --git a/admin/report/unittest/test_tables.php b/admin/report/unittest/test_tables.php
index c0baa05a363..730a70871b2 100644
--- a/admin/report/unittest/test_tables.php
+++ b/admin/report/unittest/test_tables.php
@@ -35,7 +35,6 @@ die;die;die;
$CFG->config_php_settings = $real_cfg->config_php_settings;
$CFG->frametarget = $real_cfg->frametarget;
$CFG->framename = $real_cfg->framename;
- $CFG->footer = $real_cfg->footer;
$CFG->debug = 0;
$DB = moodle_database::get_driver_instance($CFG->dbtype, $CFG->dblibrary);
diff --git a/course/view.php b/course/view.php
index 15edd623cc1..a3e58eea485 100644
--- a/course/view.php
+++ b/course/view.php
@@ -255,6 +255,6 @@
}
- print_footer(NULL, $course);
+ print_footer();
?>
diff --git a/grade/lib.php b/grade/lib.php
index 81c63f6bbb6..3ab3bb2b21a 100644
--- a/grade/lib.php
+++ b/grade/lib.php
@@ -811,7 +811,7 @@ class grade_plugin_info {
* @return string HTML code or nothing if $return == false
*/
function print_grade_page_head($courseid, $active_type, $active_plugin=null,
- $heading = false, $return=false, $bodytags='',
+ $heading = false, $return=false,
$buttons=false, $extracss=array()) {
global $CFG, $COURSE;
$strgrades = get_string('grades');
@@ -867,7 +867,7 @@ function print_grade_page_head($courseid, $active_type, $active_plugin=null,
}
$returnval = print_header_simple($strgrades . ': ' . $stractive_type, $title, $navigation, '',
- $bodytags, true, $buttons, navmenu($COURSE), false, '', $return);
+ '', true, $buttons, navmenu($COURSE), false, '', $return);
// Guess heading if not given explicitly
if (!$heading) {
diff --git a/grade/report/grader/index.php b/grade/report/grader/index.php
index 1a47a201bbb..ec95ae0d87a 100644
--- a/grade/report/grader/index.php
+++ b/grade/report/grader/index.php
@@ -130,7 +130,7 @@ if ($report->get_pref('enableajax')) {
// make sure separate group does not prevent view
if ($report->currentgroup == -2) {
- print_grade_page_head($COURSE->id, 'report', 'grader', $reportname, false, null, $buttons);
+ print_grade_page_head($COURSE->id, 'report', 'grader', $reportname, false, $buttons);
print_heading(get_string("notingroup"));
print_footer($course);
exit;
diff --git a/index.php b/index.php
index d40f73e0528..0930fd5d2e3 100644
--- a/index.php
+++ b/index.php
@@ -96,15 +96,14 @@
$PAGE->set_other_editing_capability('moodle/course:manageactivities');
$PAGE->set_url('');
$PAGE->set_docs_path('');
+ $PAGE->set_generaltype('home');
$pageblocks = blocks_setup($PAGE);
$editing = $PAGE->user_is_editing();
$preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
BLOCK_L_MAX_WIDTH);
$preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
BLOCK_R_MAX_WIDTH);
- print_header($SITE->fullname, $SITE->fullname, 'home', '',
- '',
- true, '', user_login_string($SITE).$langmenu);
+ print_header($SITE->fullname, $SITE->fullname, 'home', '', '', true, '', user_login_string($SITE).$langmenu);
?>
@@ -277,5 +276,5 @@
diff --git a/lib/deprecatedlib.php b/lib/deprecatedlib.php
index e314c3e1117..27cef30285a 100644
--- a/lib/deprecatedlib.php
+++ b/lib/deprecatedlib.php
@@ -202,6 +202,7 @@ function get_recent_enrolments($courseid, $timestart) {
* parameters remain. If possible, $align, $width and $color should not be defined at all.
* Preferably just use print_box() in weblib.php
*
+ * @deprecated
* @param string $message The message to display
* @param string $align alignment of the box, not the text (default center, left, right).
* @param string $width width of the box, including units %, for example '100%'.
@@ -242,6 +243,7 @@ function print_simple_box($message, $align='', $width='', $color='', $padding=5,
* @return string|void Depending on $return
*/
function print_simple_box_start($align='', $width='', $color='', $padding=5, $class='generalbox', $id='', $return=false) {
+ debugging('print_simple_box(_star/_end) is deprecated. Please use $OUTPUT->box(_star/_end) instead', DEBUG_DEVELOPER);
$output = '';
@@ -1746,3 +1748,365 @@ function formerr($error) {
echo $OUTPUT->error_text($error);
}
+/**
+ * Return the markup for the destination of the 'Skip to main content' links.
+ * Accessibility improvement for keyboard-only users.
+ *
+ * Used in course formats, /index.php and /course/index.php
+ *
+ * @deprecated use $OUTPUT->skip_link_target() in instead.
+ * @return string HTML element.
+ */
+function skip_main_destination() {
+ global $OUTPUT;
+ return $OUTPUT->skip_link_target();
+}
+
+/**
+ * Prints a string in a specified size (retained for backward compatibility)
+ *
+ * @deprecated
+ * @param string $text The text to be displayed
+ * @param int $size The size to set the font for text display.
+ * @param bool $return If set to true output is returned rather than echoed Default false
+ * @return string|void String if return is true
+ */
+function print_headline($text, $size=2, $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->heading($text, $size);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints text in a format for use in headings.
+ *
+ * @deprecated
+ * @param string $text The text to be displayed
+ * @param string $deprecated No longer used. (Use to do alignment.)
+ * @param int $size The size to set the font for text display.
+ * @param string $class
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @param string $id The id to use in the element
+ * @return string|void String if return=true nothing otherwise
+ */
+function print_heading($text, $deprecated = '', $size = 2, $class = 'main', $return = false, $id = '') {
+ global $OUTPUT;
+ if (!empty($deprecated)) {
+ debugging('Use of deprecated align attribute of print_heading. ' .
+ 'Please do not specify styling in PHP code like that.', DEBUG_DEVELOPER);
+ }
+ $output = $OUTPUT->heading($text, $size, $class, $id);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Output a standard heading block
+ *
+ * @deprecated
+ * @param string $heading The text to write into the heading
+ * @param string $class An additional Class Attr to use for the heading
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @return string|void HTML String if return=true nothing otherwise
+ */
+function print_heading_block($heading, $class='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->heading($heading, 2, 'headingblock header ' . moodle_renderer_base::prepare_classes($class));
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a message in a standard themed box.
+ * Replaces print_simple_box (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param string $message, the content of the box
+ * @param string $classes, space-separated class names.
+ * @param string $ids
+ * @param boolean $return, return as string or just print it
+ * @return string|void mixed string or void
+ */
+function print_box($message, $classes='generalbox', $ids='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box($message, $classes, $ids);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Starts a box using divs
+ * Replaces print_simple_box_start (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param string $classes, space-separated class names.
+ * @param string $ids
+ * @param boolean $return, return as string or just print it
+ * @return string|void string or void
+ */
+function print_box_start($classes='generalbox', $ids='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box_start($classes, $ids);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Simple function to end a box (see above)
+ * Replaces print_simple_box_end (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param boolean $return, return as string or just print it
+ * @return string|void Depending on value of return
+ */
+function print_box_end($return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box_end();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a message in a standard themed container.
+ *
+ * @deprecated
+ * @param string $message, the content of the container
+ * @param boolean $clearfix clear both sides
+ * @param string $classes, space-separated class names.
+ * @param string $idbase
+ * @param boolean $return, return as string or just print it
+ * @return string|void Depending on value of $return
+ */
+function print_container($message, $clearfix=false, $classes='', $idbase='', $return=false) {
+ global $OUTPUT;
+ if ($clearfix) {
+ $classes .= ' clearfix';
+ }
+ $output = $OUTPUT->container($message, $classes, $idbase);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Starts a container using divs
+ *
+ * @deprecated
+ * @param boolean $clearfix clear both sides
+ * @param string $classes, space-separated class names.
+ * @param string $idbase
+ * @param boolean $return, return as string or just print it
+ * @return string|void Based on value of $return
+ */
+function print_container_start($clearfix=false, $classes='', $idbase='', $return=false) {
+ global $OUTPUT;
+ if ($clearfix) {
+ $classes .= ' clearfix';
+ }
+ $output = $OUTPUT->container_start($classes, $idbase);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Simple function to end a container (see above)
+ *
+ * @deprecated
+ * @param boolean $return, return as string or just print it
+ * @return string|void Based on $return
+ */
+function print_container_end($return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->container_end();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a bold message in an optional color.
+ *
+ * @deprecated use $OUTPUT->notification instead.
+ * @param string $message The message to print out
+ * @param string $style Optional style to display message text in
+ * @param string $align Alignment option
+ * @param bool $return whether to return an output string or echo now
+ * @return string|bool Depending on $result
+ */
+function notify($message, $classes = 'notifyproblem', $align = 'center', $return = false) {
+ global $OUTPUT;
+
+ if ($classes == 'green') {
+ debugging('Use of deprecated class name "green" in notify. Please change to "notifysuccess".', DEBUG_DEVELOPER);
+ $classes = 'notifysuccess'; // Backward compatible with old color system
+ }
+
+ $output = $OUTPUT->notification($message, $classes);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a continue button that goes to a particular URL.
+ *
+ * @param string $link The url to create a link to.
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @return string|void HTML String if return=true nothing otherwise
+ */
+function print_continue($link, $return = false) {
+ global $CFG, $OUTPUT;
+
+ if ($link == '') {
+ if (!empty($_SERVER['HTTP_REFERER'])) {
+ $link = $_SERVER['HTTP_REFERER'];
+ $link = str_replace('&', '&', $link); // make it valid XHTML
+ } else {
+ $link = $CFG->wwwroot .'/';
+ }
+ }
+
+ $output = $OUTPUT->continue_button($link);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Returns a string containing a link to the user documentation for the current
+ * page. Also contains an icon by default. Shown to teachers and admin only.
+ *
+ * @global object
+ * @global object
+ * @param string $text The text to be displayed for the link
+ * @param string $iconpath The path to the icon to be displayed
+ * @return string The link to user documentation for this current page
+ */
+function page_doc_link($text='', $iconpath='') {
+ global $CFG, $PAGE;
+
+ if (empty($CFG->docroot) || during_initial_install()) {
+ return '';
+ }
+ if (!has_capability('moodle/site:doclinks', $PAGE->context)) {
+ return '';
+ }
+
+ $path = $PAGE->docspath;
+ if (!$path) {
+ return '';
+ }
+ return doc_link($path, $text, $iconpath);
+}
+
+/**
+ * Print a standard header
+ *
+ * @param string $title Appears at the top of the window
+ * @param string $heading Appears at the top of the page
+ * @param string $navigation Array of $navlinks arrays (keys: name, link, type) for use as breadcrumbs links
+ * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
+ * @param string $meta Meta tags to be added to the header
+ * @param boolean $cache Should this page be cacheable?
+ * @param string $button HTML code for a button (usually for module editing)
+ * @param string $menu HTML code for a popup menu
+ * @param boolean $usexml use XML for this page
+ * @param string $bodytags This text will be included verbatim in the
tag (useful for onload() etc)
+ * @param bool $return If true, return the visible elements of the header instead of echoing them.
+ * @return string|void If return=true then string else void
+ */
+function print_header($title='', $heading='', $navigation='', $focus='',
+ $meta='', $cache=true, $button=' ', $menu='',
+ $usexml=false, $bodytags='', $return=false) {
+ global $PAGE, $OUTPUT;
+
+ $PAGE->set_title($title);
+ $PAGE->set_heading($heading);
+ $PAGE->set_cacheable($cache);
+ $PAGE->set_focuscontrol($focus);
+ if ($button == '') {
+ $button = ' ';
+ }
+ $PAGE->set_button($button);
+
+ if ($navigation == 'home') {
+ $navigation = '';
+ }
+ if (gettype($navigation) == 'string' && strlen($navigation) != 0 && $navigation != 'home') {
+ debugging("print_header() was sent a string as 3rd ($navigation) parameter. "
+ . "This is deprecated in favour of an array built by build_navigation(). Please upgrade your code.", DEBUG_DEVELOPER);
+ }
+
+ // TODO $navigation
+ // TODO $menu
+
+ if ($meta) {
+ throw new coding_exception('The $meta parameter to print_header is no longer supported. '.
+ 'You should be able to do weverything you want with $PAGE->requires and other such mechanisms.');
+ }
+ if ($usexml) {
+ throw new coding_exception('The $usexml parameter to print_header is no longer supported.');
+ }
+ if ($bodytags) {
+ throw new coding_exception('The $bodytags parameter to print_header is no longer supported.');
+ }
+
+ $output = $OUTPUT->header($navigation, $menu);
+
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+function print_footer($course = NULL, $usercourse = NULL, $return = false) {
+ global $PAGE, $OUTPUT;
+ // TODO check arguments.
+ if (is_string($course)) {
+ debugging("Magic values like 'home', 'empty' passed to print_footer no longer have any effect. " .
+ 'To achieve a similar effect, call $PAGE->set_generaltype before you call print_header.', DEBUG_DEVELOPER);
+ } else if (!empty($course->id) && $course->id != $PAGE->course->id) {
+ throw new coding_exception('The $course object you passed to print_footer does not match $PAGE->course.');
+ }
+ if (!is_null($usercourse)) {
+ debugging('The second parameter ($usercourse) to print_footer is no longer supported. ' .
+ '(I did not think it was being used anywhere.)', DEBUG_DEVELOPER);
+ }
+ $output = $OUTPUT->footer();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
\ No newline at end of file
diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php
index 2223f05b290..c1e1e4e5ef4 100644
--- a/lib/dml/moodle_database.php
+++ b/lib/dml/moodle_database.php
@@ -400,7 +400,7 @@ abstract class moodle_database {
$log->sqlparams = var_export((array)$this->last_params, true);
$log->error = (int)$iserror;
$log->info = $iserror ? $error : null;
- $log->backtrace = print_backtrace($backtrace, true, true);
+ $log->backtrace = format_backtrace($backtrace, true);
$log->exectime = $time;
$log->timelogged = time();
$this->insert_record('log_queries', $log);
diff --git a/lib/emptyfile.php b/lib/emptyfile.php
new file mode 100644
index 00000000000..eca71850d1b
--- /dev/null
+++ b/lib/emptyfile.php
@@ -0,0 +1,21 @@
+.
+
+/**
+ * This is an empty file. For those times when you want something you can request
+ * to get an empty response.
+ */
\ No newline at end of file
diff --git a/lib/javascript-static.js b/lib/javascript-static.js
index bd42ac72b08..27afefac73c 100644
--- a/lib/javascript-static.js
+++ b/lib/javascript-static.js
@@ -1029,4 +1029,15 @@ function hide_item(itemid) {
if (item) {
item.style.display = "none";
}
+}
+
+/**
+ * Tranfer keyboard focus to the HTML element with the given id, if it exists.
+ * @param controlid the control id.
+ */
+function focuscontrol(controlid) {
+ var control = document.getElementById(controlid);
+ if (control) {
+ control.focus();
+ }
}
\ No newline at end of file
diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 0fa87bbf8b0..8e38f1fb6e9 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -8483,36 +8483,62 @@ function moodle_request_shutdown() {
}
/**
- * If new messages are waiting for the current user, then return
- * Javascript code to create a popup window
- *
- * @global object
- * @global object
- * @return string Javascript code
+ * This function is called when output is started. This is a chance for Moodle core
+ * to check things like whether the messages popup should be shown.
+ */
+function output_starting_hook() {
+ global $CFG, $PAGE;
+
+ // If maintenance mode is on, change the page header.
+ if (!empty($CFG->maintenance_enabled)) {
+ $PAGE->set_button('' . get_string('maintenancemode', 'admin') .
+ ' ' . $PAGE->button);
+
+ $title = $PAGE->title;
+ if ($title) {
+ $title .= ' - ';
+ }
+ $PAGE->set_title($title . get_string('maintenancemode', 'admin'));
+ }
+
+ // Show the messaging popup, if there are messages.
+ message_popup_window();
+}
+
+/**
+ * If new messages are waiting for the current user, then load the
+ * JavaScript required to pop up the messaging window.
*/
function message_popup_window() {
global $USER, $DB, $PAGE;
- $popuplimit = 30; // Minimum seconds between popups
-
- if (!defined('MESSAGE_WINDOW')) {
- if (isset($USER->id) and !isguestuser()) {
- if (!isset($USER->message_lastpopup)) {
- $USER->message_lastpopup = 0;
- }
- if ((time() - $USER->message_lastpopup) > $popuplimit) { /// It's been long enough
- if (get_user_preferences('message_showmessagewindow', 1) == 1) {
- if ($DB->count_records_select('message', 'useridto = ? AND timecreated > ?', array($USER->id, $USER->message_lastpopup))) {
- $USER->message_lastpopup = time();
- $PAGE->requires->js_function_call('openpopup', array('/message/index.php', 'message',
- 'menubar=0,location=0,scrollbars,status,resizable,width=400,height=500', 0));
- }
- }
- }
- }
+ if (defined('MESSAGE_WINDOW') || empty($CFG->messaging)) {
+ return;
}
- return '';
+ if (!isset($USER->id) || isguestuser()) {
+ return;
+ }
+
+ if (!isset($USER->message_lastpopup)) {
+ $USER->message_lastpopup = 0;
+ }
+
+ $popuplimit = 30; // Minimum seconds between popups
+ if ((time() - $USER->message_lastpopup) <= $popuplimit) { /// It's been long enough
+ return;
+ }
+
+ if (!get_user_preferences('message_showmessagewindow', 1)) {
+ return;
+ }
+
+ if ($DB->count_records_select('message', 'useridto = ? AND timecreated > ?', array($USER->id, $USER->message_lastpopup))) {
+ $USER->message_lastpopup = time();
+ $PAGE->requires->js_function_call('openpopup', array('/message/index.php', 'message',
+ 'menubar=0,location=0,scrollbars,status,resizable,width=400,height=500', 0));
+ }
}
/**
diff --git a/lib/outputlib.php b/lib/outputlib.php
index adb781e5c6d..423d2e170c8 100644
--- a/lib/outputlib.php
+++ b/lib/outputlib.php
@@ -28,6 +28,20 @@
*/
+/**
+ * Set up a preliminary $OUTPUT. This will be changed later once the correct theme
+ * for this page is known. Must be called after $PAGE is setup.
+ */
+function setup_bootstrat_output() {
+ global $OUTPUT, $PAGE;
+ if (CLI_SCRIPT) {
+ $OUTPUT = new cli_core_renderer(new xhtml_container_stack(), $PAGE);
+ } else {
+ $OUTPUT = new moodle_core_renderer(new xhtml_container_stack(), $PAGE);
+ }
+}
+
+
/**
* A renderer factory is just responsible for creating an appropriate renderer
* for any given part of Moodle.
@@ -87,6 +101,8 @@ abstract class renderer_factory_base implements renderer_factory {
/** Used to cache renderers as they are created. */
protected $renderers = array();
+ protected $opencontainers;
+
/**
* Constructor.
* @param object $theme the theme we are rendering for.
@@ -95,6 +111,7 @@ abstract class renderer_factory_base implements renderer_factory {
public function __construct($theme, $page) {
$this->theme = $theme;
$this->page = $page;
+ $this->opencontainers = new xhtml_container_stack();
}
/* Implement the interface method. */
@@ -164,10 +181,10 @@ class standard_renderer_factory extends renderer_factory_base {
/* Implement the subclass method. */
public function create_renderer($module) {
if ($module == 'core') {
- return new moodle_core_renderer($this->page->opencontainers);
+ return new moodle_core_renderer($this->opencontainers, $this->page);
} else {
$class = $this->standard_renderer_class_for_module($module);
- return new $class($this->page->opencontainers, $this->get_renderer('core'));
+ return new $class($this->opencontainers, $this->get_renderer('core'), $this->page);
}
}
}
@@ -191,7 +208,7 @@ class custom_corners_renderer_factory extends standard_renderer_factory {
*/
public function __construct($theme, $page) {
parent::__construct($theme, $page);
- $this->renderers = array('core' => new custom_corners_core_renderer($this->page->opencontainers));
+ $this->renderers = array('core' => new custom_corners_core_renderer($this->opencontainers, $this->page));
}
}
@@ -245,9 +262,9 @@ class theme_overridden_renderer_factory extends standard_renderer_factory {
$classname = $prefix . $module . '_renderer';
if (class_exists($classname)) {
if ($module == 'core') {
- return new $classname($this->page->opencontainers);
+ return new $classname($this->opencontainers, $this->page);
} else {
- return new $classname($this->page->opencontainers, $this->get_renderer('core'));
+ return new $classname($this->opencontainers, $this->get_renderer('core'), $this->page);
}
}
}
@@ -325,7 +342,7 @@ class template_renderer_factory extends renderer_factory_base {
// Create a template_renderer that copies the API of the standard renderer.
$copiedclass = $this->standard_renderer_class_for_module($module);
- return new template_renderer($copiedclass, $searchpaths, $this->page->opencontainers);
+ return new template_renderer($copiedclass, $searchpaths, $this->opencontainers, $this->page);
}
}
@@ -343,14 +360,18 @@ class template_renderer_factory extends renderer_factory_base {
*/
class moodle_renderer_base {
/** @var xhtml_container_stack the xhtml_container_stack to use. */
- protected $containerstack;
+ protected $opencontainers;
+ /** @var moodle_page the page we are rendering for. */
+ protected $page;
/**
* Constructor
- * @param $containerstack the xhtml_container_stack to use.
+ * @param $opencontainers the xhtml_container_stack to use.
+ * @param moodle_page $page the page we are doing output for.
*/
- public function __construct($containerstack) {
- $this->containerstack = $containerstack;
+ public function __construct($opencontainers, $page) {
+ $this->opencontainers = $opencontainers;
+ $this->page = $page;
}
protected function output_tag($tagname, $attributes, $contents) {
@@ -368,6 +389,7 @@ class moodle_renderer_base {
}
protected function output_attribute($name, $value) {
+ $value = trim($value);
if ($value || is_numeric($value)) { // We want 0 to be output.
return ' ' . $name . '="' . $value . '"';
}
@@ -379,8 +401,11 @@ class moodle_renderer_base {
}
return $output;
}
- protected function output_class_attribute($classes) {
- return $this->output_attribute('class', implode(' ', $classes));
+ public static function prepare_classes($classes) {
+ if (is_array($classes)) {
+ return implode(' ', array_unique($classes));
+ }
+ return $classes;
}
}
@@ -418,10 +443,11 @@ class template_renderer extends moodle_renderer_base {
* Constructor
* @param string $copiedclass the name of a class whose API we should be copying.
* @param $searchpaths a list of folders to search for templates in.
- * @param $containerstack the xhtml_container_stack to use.
+ * @param $opencontainers the xhtml_container_stack to use.
+ * @param moodle_page $page the page we are doing output for.
*/
- public function __construct($copiedclass, $searchpaths, $containerstack) {
- parent::__construct($containerstack);
+ public function __construct($copiedclass, $searchpaths, $opencontainers, $page) {
+ parent::__construct($opencontainers, $page);
$this->copiedclass = new ReflectionClass($copiedclass);
$this->searchpaths = $searchpaths;
}
@@ -485,7 +511,10 @@ class template_renderer extends moodle_renderer_base {
// with the names of any variables being passed to the template.
// Set up the global variables that the template may wish to access.
- global $CFG, $PAGE, $THEME;
+ global $CFG, $THEME;
+ $PAGE = $this->page; // Also, make $PAGE and $OUTPUT point to us.
+ $OUTPUT = $this;
+ $COURSE = $this->page->course;
// And the parameters from the function call.
extract($_namedarguments);
@@ -526,7 +555,7 @@ class template_renderer extends moodle_renderer_base {
array_unshift($arguments, self::contentstoken);
$html = $this->process_template($template, $arguments);
list($start, $end) = explode(self::contentstoken, $html, 2);
- $this->containerstack->push($template, $end);
+ $this->opencontainers->push($template, $end);
return $start;
}
@@ -538,7 +567,7 @@ class template_renderer extends moodle_renderer_base {
* @return string the HTML to be output.
*/
protected function process_end($template, $arguments) {
- return $this->containerstack->pop($template);
+ return $this->opencontainers->pop($template);
}
/**
@@ -571,7 +600,7 @@ class template_renderer extends moodle_renderer_base {
*/
class xhtml_container_stack {
/** @var array stores the list of open containers. */
- protected $opencontainsers = array();
+ protected $opencontainers = array();
/**
* Push the close HTML for a recently opened container onto the stack.
@@ -583,7 +612,7 @@ class xhtml_container_stack {
$container = new stdClass;
$container->type = $type;
$container->closehtml = $closehtml;
- array_push($this->opencontainsers, $container);
+ array_push($this->opencontainers, $container);
}
/**
@@ -594,12 +623,12 @@ class xhtml_container_stack {
* @return string the HTML requried to close the container.
*/
public function pop($type) {
- if (empty($this->opencontainsers)) {
+ if (empty($this->opencontainers)) {
debugging('There are no more open containers. This suggests there is a nesting problem.', DEBUG_DEVELOPER);
return;
}
- $container = array_pop($this->opencontainsers);
+ $container = array_pop($this->opencontainers);
if ($container->type != $type) {
debugging('The type of container to be closed (' . $container->type .
') does not match the type of the next open container (' . $type .
@@ -608,6 +637,14 @@ class xhtml_container_stack {
return $container->closehtml;
}
+ /**
+ * Return how many containers are currently open.
+ * @return integer how many containers are currently open.
+ */
+ public function count() {
+ return count($this->opencontainers);
+ }
+
/**
* Close all but the last open container. This is useful in places like error
* handling, where you want to close all the open containers (apart from )
@@ -616,8 +653,8 @@ class xhtml_container_stack {
*/
public function pop_all_but_last() {
$output = '';
- while (count($this->opencontainsers) > 1) {
- $container = array_pop($this->opencontainsers);
+ while (count($this->opencontainers) > 1) {
+ $container = array_pop($this->opencontainers);
$output .= $container->closehtml;
}
return $output;
@@ -630,7 +667,7 @@ class xhtml_container_stack {
* debug warning. After calling this method, the instance can no longer be used.
*/
public function discard() {
- $this->opencontainsers = null;
+ $this->opencontainers = null;
}
/**
@@ -638,13 +675,13 @@ class xhtml_container_stack {
* containers have been closed, output the rest with a developer debug warning.
*/
public function __destruct() {
- if (empty($this->opencontainsers)) {
+ if (empty($this->opencontainers)) {
return;
}
debugging('Some containers were left open. This suggests there is a nesting problem.', DEBUG_DEVELOPER);
echo $this->pop_all_but_last();
- $container = array_pop($this->opencontainsers);
+ $container = array_pop($this->opencontainers);
echo $container->closehtml;
}
}
@@ -658,6 +695,292 @@ class xhtml_container_stack {
* @since Moodle 2.0
*/
class moodle_core_renderer extends moodle_renderer_base {
+ const PERFORMANCE_INFO_TOKEN = '%%PERFORMANCEINFO%%';
+ const END_HTML_TOKEN = '%%ENDHTML%%';
+ const MAIN_CONTENT_TOKEN = '[MAIN CONTENT GOES HERE]';
+ protected $contenttype;
+
+ public function doctype() {
+ global $CFG;
+
+ $doctype = '' . "\n";
+ $this->contenttype = 'text/html; charset=utf-8';
+
+ if (empty($CFG->xmlstrictheaders)) {
+ return $doctype;
+ }
+
+ // We want to serve the page with an XML content type, to force well-formedness errors to be reported.
+ $prolog = '' . "\n";
+ if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') !== false) {
+ // Firefox and other browsers that can cope natively with XHTML.
+ $this->contenttype = 'application/xhtml+xml; charset=utf-8';
+
+ } else if (preg_match('/MSIE.*Windows NT/', $_SERVER['HTTP_USER_AGENT'])) {
+ // IE can't cope with application/xhtml+xml, but it will cope if we send application/xml with an XSL stylesheet.
+ $this->contenttype = 'application/xml; charset=utf-8';
+ $prolog .= 'httpswwwroot . '/lib/xhtml.xsl"?>' . "\n";
+
+ } else {
+ $prolog = '';
+ }
+
+ return $prolog . $doctype;
+ }
+
+ public function htmlattributes() {
+ return get_html_lang(true) . ' xmlns="http://www.w3.org/1999/xhtml"';
+ }
+
+ public function standard_head_html() {
+ global $CFG, $THEME;
+ $output = '';
+ $output .= '' . "\n";
+ $output .= '' . "\n";
+ if (!$this->page->cacheable) {
+ $output .= '' . "\n";
+ $output .= '' . "\n";
+ }
+ ob_start();
+ include($CFG->javascript);
+ $output .= ob_get_contents();
+ ob_end_clean();
+ $output .= $this->page->requires->get_head_code();
+
+ foreach ($this->page->alternateversions as $type => $alt) {
+ $output .= $this->output_empty_tag('link', array('rel' => 'alternate',
+ 'type' => $type, 'title' => $alt->title, 'href' => $alt->url));
+ }
+
+ // Add the meta page from the themes if any were requested
+ // TODO kill this.
+ $PAGE = $this->page;
+ $metapage = '';
+ if (!isset($THEME->standardmetainclude) || $THEME->standardmetainclude) {
+ ob_start();
+ include_once($CFG->dirroot.'/theme/standard/meta.php');
+ $output .= ob_get_contents();
+ ob_end_clean();
+ }
+ if ($THEME->parent && (!isset($THEME->parentmetainclude) || $THEME->parentmetainclude)) {
+ if (file_exists($CFG->dirroot.'/theme/'.$THEME->parent.'/meta.php')) {
+ ob_start();
+ include_once($CFG->dirroot.'/theme/'.$THEME->parent.'/meta.php');
+ $output .= ob_get_contents();
+ ob_end_clean();
+ }
+ }
+ if (!isset($THEME->metainclude) || $THEME->metainclude) {
+ if (file_exists($CFG->dirroot.'/theme/'.current_theme().'/meta.php')) {
+ ob_start();
+ include_once($CFG->dirroot.'/theme/'.current_theme().'/meta.php');
+ $output .= ob_get_contents();
+ ob_end_clean();
+ }
+ }
+
+ return $output;
+ }
+
+ public function standard_top_of_body_html() {
+ return $this->page->requires->get_top_of_body_code();
+ }
+
+ public function standard_footer_html() {
+ $output = self::PERFORMANCE_INFO_TOKEN;
+ if (debugging()) {
+ $output .= '
';
+ }
+ return $output;
+ }
+
+ public function standard_end_of_body_html() {
+ echo self::END_HTML_TOKEN;
+ }
+
+ public function login_info() {
+ global $USER;
+ return user_login_string($this->page->course, $USER);
+ }
+
+ public function home_link() {
+ global $CFG, $SITE;
+
+ if ($this->page->pagetype == 'site-index') {
+ // Special case for site home page - please do not remove
+ return '