]> git.mjollnir.org Git - moodle.git/commitdiff
themes: MDL-19077 new $OUTPUT->header/footer to replace print_header/footer.
authortjhunt <tjhunt>
Fri, 26 Jun 2009 09:06:16 +0000 (09:06 +0000)
committertjhunt <tjhunt>
Fri, 26 Jun 2009 09:06:16 +0000 (09:06 +0000)
Also, part of the change from weblib.php functions to $OUTPUT-> methods.

This is part of http://docs.moodle.org/en/Development:Theme_engines_for_Moodle%3F

This is a big change, and the result is not perfect yet. Expect some debugging output
on some pages.

The main part of these changes are that $OUTPUT->header now looks for a file
in the theme called layout.php, rather than header.html and footer.html. Also
you can have special templates for certain pages like layout-home.php. There is
fallback code for Moodle 1.9 themes, so they still work.

A few of the old arguments to print_header are no longer supported. (You get an
exception if you try to use them.) Sam H will be cleaning those up.

All the weblib functions that have been replaced with $OUTPUT-> have version in
deprecatedlib, so existing code will go on working for the foreseeable future.

31 files changed:
admin/report/unittest/test_tables.php
course/view.php
grade/lib.php
grade/report/grader/index.php
index.php
lib/deprecatedlib.php
lib/dml/moodle_database.php
lib/emptyfile.php [new file with mode: 0644]
lib/javascript-static.js
lib/moodlelib.php
lib/outputlib.php
lib/pagelib.php
lib/questionlib.php
lib/setup.php
lib/setuplib.php
lib/simpletest/testoutputlib.php
lib/simpletest/testpagelib_moodlepage.php
lib/upgradelib.php
lib/weblib.php
mod/data/edit.php
mod/data/view.php
mod/quiz/edit.php
mod/quiz/report/default.php
mod/quiz/report/responses/report.php
question/edit.php
question/question.php
theme/standard/config.php
theme/standard/layout-home.php [new file with mode: 0644]
theme/standard/layout.php [new file with mode: 0644]
theme/standardwhite/layout-home.php [new file with mode: 0644]
theme/standardwhite/layout.php [new file with mode: 0644]

index c0baa05a363ba5cef1b281c9b9ef57ed931d857c..730a70871b2100cd1afdef6e948ea241368e9328 100644 (file)
@@ -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);
index 15edd623cc118ba41feeff54f4873890bdb8844e..a3e58eea4856429aefb0746b2cb76b689b27cb60 100644 (file)
     }
 
 
-    print_footer(NULL, $course);
+    print_footer();
 
 ?>
index 81c63f6bbb6fa36e3682a78f31e657978e9ac525..3ab3bb2b21a8ad285cfc56321d2cf97f739c2726 100644 (file)
@@ -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) {
index 1a47a201bbb7d7b5f65111b74fbba8259c280192..ec95ae0d87a5358d2b7d4eeaa15624a1e7539f6e 100644 (file)
@@ -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;
index d40f73e052802839f740a142c1e3e03191db976e..0930fd5d2e36c01b7f5ab7595d16cb402e33e24d 100644 (file)
--- a/index.php
+++ b/index.php
     $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', '',
-                 '<meta name="description" content="'. strip_tags(format_text($SITE->summary, FORMAT_HTML)) .'" />',
-                 true, '', user_login_string($SITE).$langmenu);
+    print_header($SITE->fullname, $SITE->fullname, 'home', '', '', true, '', user_login_string($SITE).$langmenu);
 
 ?>
 
 
 
 <?php
-    print_footer('home');     // Please do not modify this line
+    print_footer();
 ?>
index e314c3e1117c65c23ad36fe5aad8ff9aeb06938d..27cef30285a227718fd66519ee73fbb64ce94224 100644 (file)
@@ -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('&', '&amp;', $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 <body> 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='&nbsp;', $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 = '&nbsp;';
+    }
+    $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
index 2223f05b2907a700d4155573a59cb51fb44d5a10..c1e1e4e5ef460d4c782cdb1e7233e974faf5ed73 100644 (file)
@@ -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 (file)
index 0000000..eca7185
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * 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
index bd42ac72b08508da5aed0e57511deeaf28581305..27afefac73c6dd0da0bdc0790ffa51534ad95654 100644 (file)
@@ -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
index 0fa87bbf8b0d3819797a6093dac5e13113c2da77..8e38f1fb6e97fcb4d33ad7c8848760ba155baba3 100644 (file)
@@ -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('<a href="' . $CFG->wwwroot . '/' . $CFG->admin .
+                '/settings.php?section=maintenancemode">' . get_string('maintenancemode', 'admin') .
+                '</a> ' . $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;
 
+    if (defined('MESSAGE_WINDOW') || empty($CFG->messaging)) {
+        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 (!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 (!get_user_preferences('message_showmessagewindow', 1)) {
+        return;
     }
 
-    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));
+    }
 }
 
 /**
index adb781e5c6d73c3720c7d0331c6ebee5aa360ef6..423d2e170c84708dee28d4c87332223473cccc83 100644 (file)
  */
 
 
+/**
+ * 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 <body>)
@@ -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 = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\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 = '<?xml version="1.0" encoding="utf-8"?>' . "\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 .= '<?xml-stylesheet type="text/xsl" href="' . $CFG->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 .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . "\n";
+        $output .= '<meta name="keywords" content="moodle, ' . $this->page->title . '" />' . "\n";
+        if (!$this->page->cacheable) {
+            $output .= '<meta http-equiv="pragma" content="no-cache" />' . "\n";
+            $output .= '<meta http-equiv="expires" content="0" />' . "\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 .= '<div class="validators"><ul>
+              <li><a href="http://validator.w3.org/check?verbose=1&amp;ss=1&amp;uri=' . urlencode(qualified_me()) . '">Validate HTML</a></li>
+              <li><a href="http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=-1&amp;url1=' . urlencode(qualified_me()) . '">Section 508 Check</a></li>
+              <li><a href="http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=0&amp;warnp2n3e=1&amp;url1=' . urlencode(qualified_me()) . '">WCAG 1 (2,3) Check</a></li>
+            </ul></div>';
+        }
+        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 '<div class="sitelink">' .
+                   '<a title="Moodle ' . $CFG->release . '" href="http://moodle.org/">' .
+                   '<img style="width:100px;height:30px" src="' . $CFG->httpswwwroot . '/pix/moodlelogo.gif" alt="moodlelogo" /></a></div>';
+
+        } else if (!empty($CFG->target_release) && $CFG->target_release != $CFG->release) {
+            // Special case for during install/upgrade.
+            return '<div class="sitelink">'.
+                   '<a title="Moodle ' . $CFG->target_release . '" href="http://docs.moodle.org/en/Administrator_documentation" onclick="this.target=\'_blank\'">' .
+                   '<img style="width:100px;height:30px" src="' . $CFG->httpswwwroot . '/pix/moodlelogo.gif" alt="moodlelogo" /></a></div>';
+
+        } else if ($this->page->course->id == $SITE->id || strpos($this->page->pagetype, 'course-view') === 0) {
+            return '<div class="homelink"><a href="' . $CFG->wwwroot . '/">' .
+                    get_string('home') . '</a></div>';
+
+        } else {
+            return '<div class="homelink"><a href="' . $CFG->wwwroot . '/course/view.php?id=' . $this->page->course->id . '">' .
+                    format_string($this->page->course->shortname) . '</a></div>';
+        }
+    }
+
+    // TODO remove $navigation and $menu arguments - replace with $PAGE->navigation
+    public function header($navigation = '', $menu='') {
+        global $USER, $CFG;
+
+        output_starting_hook();
+        $this->page->set_state(moodle_page::STATE_PRINTING_HEADER);
+
+        // Add any stylesheets required using the horrible legacy mechanism. TODO kill this.
+        foreach ($CFG->stylesheets as $stylesheet) {
+            $this->page->requires->css($stylesheet, true);
+        }
+
+        // Find the appropriate page template, based on $this->page->generaltype.
+        $templatefile = $this->find_page_template();
+        if ($templatefile) {
+            // Render the template.
+            $template = $this->render_page_template($templatefile, $menu, $navigation);
+        } else {
+            // New style template not found, fall back to using header.html and footer.html.
+            $template = $this->handle_legacy_theme($navigation, $menu);
+        }
+
+        // Slice the template output into header and footer.
+        $cutpos = strpos($template, self::MAIN_CONTENT_TOKEN);
+        if ($cutpos === false) {
+            throw new coding_exception('Layout template ' . $templatefile .
+                    ' does not contain the string "' . self::MAIN_CONTENT_TOKEN . '".');
+        }
+        $header = substr($template, 0, $cutpos);
+        $footer = substr($template, $cutpos + strlen(self::MAIN_CONTENT_TOKEN));
+
+        send_headers($this->contenttype, $this->page->cacheable);
+        $this->opencontainers->push('header/footer', $footer);
+        $this->page->set_state(moodle_page::STATE_IN_BODY);
+        return $header . $this->skip_link_target();
+    }
+
+    protected function find_page_template() {
+        global $THEME;
+
+        // If this is a particular page type, look for a specific template.
+        $type = $this->page->generaltype;
+        if ($type != 'normal') {
+            $templatefile = $THEME->dir . '/layout-' . $type . '.php';
+            if (is_readable($templatefile)) {
+                return $templatefile;
+            }
+        }
+
+        // Otherwise look for the general template.
+        $templatefile = $THEME->dir . '/layout.php';
+        if (is_readable($templatefile)) {
+            return $templatefile;
+        }
+
+        return false;
+    }
+
+    protected function render_page_template($templatefile, $menu, $navigation) {
+        global $CFG, $SITE, $THEME, $USER;
+        // Set some pretend globals from the properties of this class.
+        $OUTPUT = $this;
+        $PAGE = $this->page;
+        $COURSE = $this->page->course;
+
+        ob_start();
+        include($templatefile);
+        $template = ob_get_contents();
+        ob_end_clean();
+        return $template;
+    }
+
+    protected function handle_legacy_theme($navigation, $menu) {
+        global $CFG, $SITE, $THEME, $USER;
+        // Set a pretend global from the properties of this class.
+        $COURSE = $this->page->course;
+
+        // Set up local variables that header.html expects.
+        $direction = $this->htmlattributes();
+        $title = $this->page->title;
+        $heading = $this->page->heading;
+        $focus = $this->page->focuscontrol;
+        $button = $this->page->button;
+        $pageid = $this->page->pagetype;
+        $pageclass = $this->page->bodyclasses;
+        $bodytags = ' class="' . $pageclass . '" id="' . $pageid . '"';
+        $home = $this->page->generaltype == 'home';
+
+        $meta = $this->standard_head_html();
+        // The next line is a nasty hack. having set $meta to standard_head_html, we have already
+        // got the contents of include($CFG->javascript). However, legacy themes are going to
+        // include($CFG->javascript) again. We want to make sure that when they do, nothing is output.
+        $CFG->javascript = $CFG->libdir . '/emptyfile.php';
+
+        // Set up local variables that footer.html expects.
+        $homelink = $this->home_link();
+        $loggedinas = $this->login_info();
+        $course = $this->page->course;
+        $performanceinfo = self::PERFORMANCE_INFO_TOKEN;
+
+        if (!$menu && $navigation) {
+            $menu = $loggedinas;
+        }
+
+        ob_start();
+        include($THEME->dir . '/header.html');
+        $this->page->requires->get_top_of_body_code();
+        echo self::MAIN_CONTENT_TOKEN;
+
+        $menu = str_replace('navmenu', 'navmenufooter', $menu);
+        include($THEME->dir . '/footer.html');
+
+        $output = ob_get_contents();
+        ob_end_clean();
+
+        $output = str_replace('</body>', self::END_HTML_TOKEN . '</body>', $output);
+
+        return $output;
+    }
+
+    public function footer() {
+        $output = '';
+        if ($this->opencontainers->count() != 1) {
+            debugging('Some HTML tags were opened in the body of the page but not closed.', DEBUG_DEVELOPER);
+            $output .= $this->opencontainers->pop_all_but_last();
+        }
+
+        $footer = $this->opencontainers->pop('header/footer');
+
+        // Provide some performance info if required
+        $performanceinfo = '';
+        if (defined('MDL_PERF') || (!empty($CFG->perfdebug) and $CFG->perfdebug > 7)) {
+            $perf = get_performance_info();
+            if (defined('MDL_PERFTOLOG') && !function_exists('register_shutdown_function')) {
+                error_log("PERF: " . $perf['txt']);
+            }
+            if (defined('MDL_PERFTOFOOT') || debugging() || $CFG->perfdebug > 7) {
+                $performanceinfo = $perf['html'];
+            }
+        }
+        $footer = str_replace(self::PERFORMANCE_INFO_TOKEN, $performanceinfo, $footer);
+
+        $footer = str_replace(self::END_HTML_TOKEN, $this->page->requires->get_end_code(), $footer);
+
+        $this->page->set_state(moodle_page::STATE_DONE);
+
+        return $output . $footer;
+    }
+
     public function link_to_popup_window() {
         
     }
@@ -756,6 +1079,138 @@ class moodle_core_renderer extends moodle_renderer_base {
         }
         return $this->output_tag('span', array('class' => 'error'), $message);
     }
+
+    /**
+     * Do not call this function directly.
+     *
+     * To terminate the current script with a fatal error, call the {@link print_error}
+     * function, or throw an exception. Doing either of those things will then call this
+     * funciton to display the error, before terminating the exection.
+     *
+     * @param string $message
+     * @param string $moreinfourl
+     * @param string $link
+     * @param array $backtrace
+     * @param string $debuginfo
+     * @param bool $showerrordebugwarning
+     * @return string the HTML to output.
+     */
+    public function fatal_error($message, $moreinfourl, $link, $backtrace,
+                $debuginfo = null, $showerrordebugwarning = false) {
+
+        $output = '';
+
+        if ($this->opencontainers->count() == 0) {
+            // Header not yet printed
+            @header('HTTP/1.0 404 Not Found');
+            print_header(get_string('error'));
+        } else {
+            $output .= $this->opencontainers->pop_all_but_last();
+        }
+
+        $message = '<p class="errormessage">' . $message . '</p>'.
+                '<p class="errorcode"><a href="' . $moreinfourl . '">' .
+                get_string('moreinformation') . '</a></p>';
+        $output .= $this->box($message, 'errorbox');
+
+        if (debugging('', DEBUG_DEVELOPER)) {
+            if ($showerrordebugwarning) {
+                $output .= $this->notification('error() is a deprecated function. ' .
+                        'Please call print_error() instead of error()', 'notifytiny');
+            }
+            if (!empty($debuginfo)) {
+                $output .= $this->notification($debuginfo, 'notifytiny');
+            }
+            if (!empty($backtrace)) {
+                $output .= $this->notification('Stack trace: ' .
+                        format_backtrace($backtrace, true), 'notifytiny');
+            }
+        }
+
+        if (!empty($link)) {
+            $output .= $this->continue_button($link);
+        }
+
+        print_footer();
+
+        // Padding to encourage IE to display our error page, rather than its own.
+        $output .= str_repeat(' ', 512);
+
+        return $output;
+    }
+
+    /**
+     * Output a notification (that is, a status message about something that has
+     * just happened).
+     *
+     * @param string $message the message to print out
+     * @param string $classes normally 'notifyproblem' or 'notifysuccess'.
+     * @return string the HTML to output.
+     */
+    public function notification($message, $classes = 'notifyproblem') {
+        return $this->output_tag('div', array('class' =>
+                moodle_renderer_base::prepare_classes($classes)), clean_text($message));
+    }
+
+    /**
+     * Print a continue button that goes to a particular URL.
+     *
+     * @param string|moodle_url $link The url the button goes to.
+     * @return string the HTML to output.
+     */
+    public function continue_button($link) {
+        if (!is_a($link, 'moodle_url')) {
+            $link = new moodle_url($link);
+        }
+        return $this->output_tag('div', array('class' => 'continuebutton'),
+                print_single_button($link->out(true), $link->params(), get_string('continue'), 'get', '', true));
+    }
+
+    /**
+     * Output the place a skip link goes to.
+     * @param $id The target name from the corresponding $PAGE->requires->skip_link_to($target) call.
+     * @return string the HTML to output.
+     */
+    public function skip_link_target($id = 'maincontent') {
+        return $this->output_tag('span', array('id' => $id), '');
+    }
+
+    public function heading($text, $level, $classes = 'main', $id = '') {
+        $level = (integer) $level;
+        if ($level < 1 or $level > 6) {
+            throw new coding_exception('Heading level must be an integer between 1 and 6.');
+        }
+        return $this->output_tag('h' . $level,
+                array('id' => $id, 'class' => moodle_renderer_base::prepare_classes($classes)), $text);
+    }
+
+    public function box($contents, $classes = 'generalbox', $id = '') {
+        return $this->box_start($classes, $id) . $contents . $this->box_end();
+    }
+
+    public function box_start($classes = 'generalbox', $id = '') {
+        $this->opencontainers->push('box', $this->output_end_tag('div'));
+        return $this->output_start_tag('div', array('id' => $id,
+                'class' => 'box ' . moodle_renderer_base::prepare_classes($classes)));
+    }
+
+    public function box_end() {
+        return $this->opencontainers->pop('box');
+    }
+
+    public function container($contents, $classes = '', $id = '') {
+        return $this->container_start($classes, $id) . $contents . $this->container_end();
+    }
+
+    public function container_start($classes = '', $id = '') {
+        $this->opencontainers->push('container', $this->output_end_tag('div'));
+        return $this->output_start_tag('div', array('id' => $id,
+                'class' => moodle_renderer_base::prepare_classes($classes)));
+    }
+
+    public function container_end() {
+        return $this->opencontainers->pop('container');
+    }
 }
 
 
@@ -838,7 +1293,7 @@ class moodle_html_component {
 
 /**
  * This class hold all the information required to describe a <select> menu that
- * will be printed by {@link moodle_core_renderer::select_menu()}. (Or by an overrides
+ * will be printed by {@link moodle_core_renderer::select_menu()}. (Or by an overridden
  * version of that method in a subclass.)
  *
  * All the fields that are not set by the constructor have sensible defaults, so
@@ -944,6 +1399,57 @@ class moodle_select_menu extends moodle_html_component {
 }
 
 
+/**
+ * A renderer that generates output for commandlines scripts.
+ *
+ * The implementation of this renderer is probably incomplete.
+ *
+ * @copyright 2009 Tim Hunt
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since     Moodle 2.0
+ */
+class cli_core_renderer extends moodle_core_renderer {
+    public function header() {
+        output_starting_hook();
+        return $this->page->heading . "\n";
+    }
+
+    public function heading($text, $level, $classes = 'main', $id = '') {
+        $text .= "\n";
+        switch ($level) {
+            case 1:
+                return '=>' . $text;
+            case 2:
+                return '-->' . $text;
+            default:
+                return $text;
+        }
+    }
+
+    public function fatal_error($errorcode, $module, $a, $link, $backtrace,
+                $debuginfo = null, $showerrordebugwarning = false) {
+        $output = "!!! $message !!!\n";
+
+        if (debugging('', DEBUG_DEVELOPER)) {
+            if (!empty($debuginfo)) {
+                $this->notification($debuginfo, 'notifytiny');
+            }
+            if (!empty($backtrace)) {
+                $this->notification('Stack trace: ' . format_backtrace($backtrace, true), 'notifytiny');
+            }
+        }
+    }
+
+    public function notification($message, $classes = 'notifyproblem') {
+        $message = clean_text($message);
+        if ($style === 'notifysuccess') {
+            return "++ $message ++\n";
+        }
+        return "!! $message !!\n";
+    }
+}
+
+
 /**
  * A renderer for the custom corner theme, and other themes based on it.
  *
@@ -954,7 +1460,59 @@ class moodle_select_menu extends moodle_html_component {
  * @since     Moodle 2.0
  */
 class custom_corners_core_renderer extends moodle_core_renderer {
+    protected function custom_corners_divs($classes = '', $idbase = '') {
+        if (strpos($classes, 'clearfix') !== false) {
+            $clearfix = ' clearfix';
+            $classes = trim(str_replace('clearfix', '', $classes));
+        } else {
+            $clearfix = '';
+        }
 
-    // TODO
-}
+        // Analise if we want ids for the custom corner elements
+        $id = '';
+        $idbt = '';
+        $idi1 = '';
+        $idi2 = '';
+        $idi3 = '';
+        $idbb = '';
+        if ($idbase) {
+            $id = $idbase;
+            $idbt = $idbase . '-bt';
+            $idi1 = $idbase . '-i1';
+            $idi2 = $idbase . '-i2';
+            $idi3 = $idbase . '-i3';
+            $idbb = $idbase . '-bb';
+        }
+
+        // Calculate current level
+        $level = $this->opencontainers->count();
+
+        // Create start tags.
+        $start = $this->output_start_tag('div', array('id' => $idbb, 'class' => "wrap wraplevel$level $classes")) . "\n";
+        $start .= $this->output_tag('div', array('id' => $idbt, 'class' => 'bt'), '<div>&nbsp;</div>') . "\n";
+        $start .= $this->output_start_tag('div', array('id' => $idi1, 'class' => 'i1'));
+        $start .= $this->output_start_tag('div', array('id' => $idi2, 'class' => 'i2'));
+        $start .= $this->output_start_tag('div', array('id' => $idi3, 'class' => "i3$clearfix"));
+
+        // Create end tags.
+        $end = $this->output_end_tag('div');
+        $end .= $this->output_end_tag('div');
+        $end .= $this->output_end_tag('div');
+        $end .= $this->output_tag('div', array('id' => $idbb, 'class' => 'bb'), '<div>&nbsp;</div>') . "\n";
+        $end .= $this->output_end_tag('div');
+
+        return array($start, $end);
+    }
 
+    public function box_start($classes = 'generalbox', $id = '') {
+        list($start, $end) = $this->custom_corners_divs('ccbox box ' . moodle_renderer_base::prepare_classes($classes), $id);
+        $this->opencontainers->push('box', $end);
+        return $start;
+    }
+
+    public function container_start($classes = '', $id = '') {
+        list($start, $end) = $this->custom_corners_divs(moodle_renderer_base::prepare_classes($classes), $id);
+        $this->opencontainers->push('container', $end);
+        return $start;
+    }
+}
index 13d128d2d925294a0e1b64a1c75abbdf2964d8a3..548a990b83a80744607cc8e8c2760a302ecd08c6 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since Moodle 2.0
  *
+ * @property-read string $generaltype the general type of page this is. For example 'normal', 'popup', 'home'.
+ *      Allows the theme to display things differently, if it wishes to.
+ * @property-read string $title the title that should go in the <head> section of the HTML of this page.
+ * @property-read string $heading the main heading that should be displayed at the top of the <body>.
+ * @property-read string $cacheable defaults to true. Set to false to stop the page being cached at all.
  * @property-read page_requirements_manager $requires Tracks resources (for example required .css and .js files) required by this page.
- * @property-read xhtml_container_stack $opencontainers Tracks open XHTML tags. Helps us generate well-formed XML, even in the face of errors.
  */
 class moodle_page {
     /**#@+ Tracks the where we are in the generation of the page. */
     const STATE_BEFORE_HEADER = 0;
     const STATE_PRINTING_HEADER = 1;
     const STATE_IN_BODY = 2;
-    const STATE_PRINTING_FOOTER = 3;
-    const STATE_DONE = 4;
+    const STATE_DONE = 3;
     /**#@-*/
 
 /// Field declarations =========================================================
@@ -89,8 +92,14 @@ class moodle_page {
 
     protected $_bodyclasses = array();
 
+    protected $_title = '';
+
+    protected $_heading = '';
+
     protected $_pagetype = null;
 
+    protected $_generaltype = 'normal';
+
     protected $_subpage = '';
 
     protected $_docspath = null;
@@ -99,6 +108,8 @@ class moodle_page {
 
     protected $_url = null;
 
+    protected $_alternateversions = array();
+
     protected $_blocks = null;
 
     protected $_requires = null;
@@ -107,7 +118,11 @@ class moodle_page {
 
     protected $_othereditingcaps = array();
 
-    protected $_opencontainers = null;
+    protected $_cacheable = true;
+
+    protected $_focuscontrol = '';
+
+    protected $_button = '';
 
     /**
      * This is simply to improve backwards compatability. If old code relies on
@@ -122,7 +137,7 @@ class moodle_page {
 /// methods, but instead use the $PAGE->x syntax.
 
     /**
-     * Please do not call this method directly, use the ->state syntax. @see __get().
+     * Please do not call this method directly, use the ->state syntax. {@link __get()}.
      * @return integer one of the STATE_... constants. You should not normally need
      * to use this in your code. It is indended for internal use by this class
      * and its friends like print_header, to check that everything is working as
@@ -133,7 +148,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->headerprinted syntax. @see __get().
+     * Please do not call this method directly, use the ->headerprinted syntax. {@link __get()}.
      * @return boolean has the header already been printed?
      */
     public function get_headerprinted() {
@@ -141,7 +156,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->course syntax. @see __get().
+     * Please do not call this method directly, use the ->course syntax. {@link __get()}.
      *
      * @global object
      * @return object the current course that we are inside - a row from the
@@ -157,7 +172,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->cm syntax. @see __get().
+     * Please do not call this method directly, use the ->cm syntax. {@link __get()}.
      * @return object the course_module that this page belongs to. Will be null
      * if this page is not within a module. This is a full cm object, as loaded
      * by get_coursemodule_from_id or get_coursemodule_from_instance,
@@ -168,7 +183,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->activityrecord syntax. @see __get().
+     * Please do not call this method directly, use the ->activityrecord syntax. {@link __get()}.
      * @return object the row from the activities own database table (for example
      * the forum or quiz table) that this page belongs to. Will be null
      * if this page is not within a module.
@@ -181,7 +196,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->activityname syntax. @see __get().
+     * Please do not call this method directly, use the ->activityname syntax. {@link __get()}.
      * @return string|null the The type of activity we are in, for example 'forum' or 'quiz'.
      * Will be null if this page is not within a module.
      */
@@ -193,7 +208,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->category syntax. @see __get().
+     * Please do not call this method directly, use the ->category syntax. {@link __get()}.
      * @return mixed the category that the page course belongs to. If there isn't one
      * (that is, if this is the front page course) returns null.
      */
@@ -207,7 +222,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->categories syntax. @see __get().
+     * Please do not call this method directly, use the ->categories syntax. {@link __get()}.
      * @return array an array of all the categories the page course belongs to,
      * starting with the immediately containing category, and working out to
      * the top-level category. This may be the empty array if we are in the
@@ -219,7 +234,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->context syntax. @see __get().
+     * Please do not call this method directly, use the ->context syntax. {@link __get()}.
      * @return object the main context to which this page belongs.
      */
     public function get_context() {
@@ -230,7 +245,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->pagetype syntax. @see __get().
+     * Please do not call this method directly, use the ->pagetype syntax. {@link __get()}.
      * @return string e.g. 'my-index' or 'mod-quiz-attempt'. Same as the id attribute on <body>.
      */
     public function get_pagetype() {
@@ -241,7 +256,16 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->subpage syntax. @see __get().
+     * Please do not call this method directly, use the ->generaltype syntax. {@link __get()}.
+     * @return string the general type of page this is. For example 'normal', 'popup', 'home'.
+     *      Allows the theme to display things differently, if it wishes to.
+     */
+    public function get_generaltype() {
+        return $this->_generaltype;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->subpage syntax. {@link __get()}.
      * @return string|null The subpage identifier, if any.
      */
     public function get_subpage() {
@@ -249,7 +273,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->bodyclasses syntax. @see __get().
+     * Please do not call this method directly, use the ->bodyclasses syntax. {@link __get()}.
      * @return string the class names to put on the body element in the HTML.
      */
     public function get_bodyclasses() {
@@ -257,7 +281,23 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->docspath syntax. @see __get().
+     * Please do not call this method directly, use the ->title syntax. {@link __get()}.
+     * @return string the title that should go in the <head> section of the HTML of this page.
+     */
+    public function get_title() {
+        return $this->_title;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->heading syntax. {@link __get()}.
+     * @return string the main heading that should be displayed at the top of the <body>.
+     */
+    public function get_heading() {
+        return $this->_heading;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->docspath syntax. {@link __get()}.
      * @return string the path to the Moodle docs for this page.
      */
     public function get_docspath() {
@@ -269,7 +309,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->url syntax. @see __get().
+     * Please do not call this method directly, use the ->url syntax. {@link __get()}.
      * @return moodle_url the clean URL required to load the current page. (You
      * should normally use this in preference to $ME or $FULLME.)
      */
@@ -283,7 +323,15 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->blocks syntax. @see __get().
+     * The list of alternate versions of this page.
+     * @return array mime type => object with ->url and ->title.
+     */
+    public function get_alternateversions() {
+        return $this->_alternateversions;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->blocks syntax. {@link __get()}.
      * @return blocks_manager the blocks manager object for this page.
      */
     public function get_blocks() {
@@ -300,7 +348,7 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->requires syntax. @see __get().
+     * Please do not call this method directly, use the ->requires syntax. {@link __get()}.
      * @return page_requirements_manager tracks the JavaScript, CSS files, etc. required by this page.
      */
     public function get_requires() {
@@ -312,15 +360,27 @@ class moodle_page {
     }
 
     /**
-     * Please do not call this method directly, use the ->opencontainers syntax. @see __get().
-     * @return xhtml_container_stack Tracks the open XHTML tags on this page.
+     * Please do not call this method directly, use the ->cacheable syntax. {@link __get()}.
+     * @return boolean can this page be cached by the user's browser.
      */
-    public function get_opencontainers() {
-        global $CFG;
-        if (is_null($this->_opencontainers)) {
-            $this->_opencontainers = new xhtml_container_stack();
-        }
-        return $this->_opencontainers;
+    public function get_cacheable() {
+        return $this->_cacheable;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->focuscontrol syntax. {@link __get()}.
+     * @return string the id of the HTML element to be focussed when the page has loaded.
+     */
+    public function get_focuscontrol() {
+        return $this->_focuscontrol;
+    }
+
+    /**
+     * Please do not call this method directly, use the ->button syntax. {@link __get()}.
+     * @return string the HTML to go where the Turn editing on button normaly goes.
+     */
+    public function get_button() {
+        return $this->_button;
     }
 
     /**
@@ -488,6 +548,17 @@ class moodle_page {
         $this->_pagetype = $pagetype;
     }
 
+    /**
+     * @param string $generaltype the general type of page this is. For example 'popup', 'home'.
+     * This properly defaults to 'normal', so you only need to call this function if
+     * you want something different. The exact range of supported page types is not
+     * strictly defined, this value is just passed to the theme. However, at the moment
+     * only 'normal', 'popup' amd 'home' are used.
+     */
+    public function set_generaltype($generaltype) {
+        $this->_generaltype = $generaltype;
+    }
+
     /**
      * If context->id and pagetype are not enough to uniquely identify this page,
      * then you can set a subpage id as well. For example, the tags page sets
@@ -521,6 +592,22 @@ class moodle_page {
         }
     }
 
+    /**
+     * $param string $title the title that should go in the <head> section of the HTML of this page.
+     */
+    public function set_title($title) {
+        $title = format_string($title);
+        $title = str_replace('"', '&quot;', $title);
+        $this->_title = $title;
+    }
+
+    /**
+     * $param string $heading the main heading that should be displayed at the top of the <body>.
+     */
+    public function set_heading($heading) {
+        $this->_heading = format_string($heading);
+    }
+
     /**
      * Set the course category this page belongs to manually. This automatically
      * sets $PAGE->course to be the site coures. You cannot use this method if
@@ -574,6 +661,43 @@ class moodle_page {
         }
     }
 
+    /**
+     * There can be alternate versions of some pages (for example an RSS feed version).
+     * If such other version exist, call this method, and a link to the alternate
+     * version will be included in the <head> of the page.
+     *
+     * @param $title The title to give the alternate version.
+     * @param $url The URL of the alternate version.
+     * @param $mimetype The mime-type of the alternate version.
+     */
+    public function add_alternate_version($title, $url, $mimetype) {
+        if ($this->_state > self::STATE_BEFORE_HEADER) {
+            throw new coding_exception('Cannot call moodle_page::add_alternate_version after output has been started.');
+        }
+        $alt = new stdClass;
+        $alt->title = $title;
+        $alt->url = url;
+        $this->_alternateversions[$mimetype] = $alt;
+    }
+
+    /**
+     * Specify a form control should be focussed when the page has loaded.
+     *
+     * @param string $controlid the id of the HTML element to be focussed.
+     */
+    public function set_focuscontrol($controlid) {
+        $this->_focuscontrol = $controlid;
+    }
+
+    /**
+     * Specify a fragment of HTML that goes where the 'Turn editing on' button normally goes.
+     *
+     * @param string $html the HTML to display there.
+     */
+    public function set_button($html) {
+        $this->_button = $html;
+    }
+
     /**
      * Set the capability that allows users to edit blocks on this page. Normally
      * the default of 'moodle/site:manageblocks' is used, but a few pages like
@@ -598,6 +722,13 @@ class moodle_page {
         }
     }
 
+    /**
+     * @return boolean $cacheable can this page be cached by the user's browser.
+     */
+    public function set_cacheable($cacheable) {
+        $this->_cacheable = $cacheable;
+    }
+
 /// Initialisation methods =====================================================
 /// These set various things up in a default way.
 
index 2b7b547e75d4473f30842c3ab4c24f096d80cd73..926ab4bb1416fa1f41c36c776d7858faecbd6e8e 100644 (file)
@@ -2133,20 +2133,11 @@ function get_html_head_contributions($questionlist, &$questions, &$states) {
     $PAGE->requires->yui_lib('connection');
     $PAGE->requires->js('question/qengine.js');
 
-    // An inline script to record various lang strings, etc. that qengine.js needs.
-    $contributions = array();
-
     // Anything that questions on this page need.
     foreach ($questionlist as $questionid) {
         $question = $questions[$questionid];
-        $newcontributions = $QTYPES[$question->qtype]->
-                get_html_head_contributions($question, $states[$questionid]);
-        if (!empty($newcontributions)) {
-            $contributions = array_merge($contributions, $newcontributions);
-        }
+        $QTYPES[$question->qtype]->get_html_head_contributions($question, $states[$questionid]);
     }
-
-    return implode("\n", array_unique($contributions));
 }
 
 /**
@@ -2158,11 +2149,7 @@ function get_html_head_contributions($questionlist, &$questions, &$states) {
  */
 function get_editing_head_contributions($question) {
     global $QTYPES;
-    $contributions = $QTYPES[$question->qtype]->get_editing_head_contributions();
-    if (empty($contributions)) {
-        $contributions = array();
-    }
-    return implode("\n", array_unique($contributions));
+    $QTYPES[$question->qtype]->get_editing_head_contributions();
 }
 
 /**
index 633cfb0ce993ea20a402c30bcf815f01c485c3b4..57bd20c431ddda3ab1430f364a9e675352acb4b5 100644 (file)
@@ -94,11 +94,19 @@ global $PAGE;
 global $COURSE;
 
 /**
- * $THEME is a global that defines the site theme.
+ * $OUTPUT is an instance of moodle_core_renderer or one of its subclasses. Use
+ * it to generate HTML for output.
  *
- * Items found in the theme record:
- *  - $THEME->cellheading - Cell colors.
- *  - $THEME->cellheading2 - Alternate cell colors.
+ * $OUTPUT is initialised when the theme is setup. That normally happens during
+ * the call to require_login, or $PAGE->set_course.
+ *
+ * @global object $OUTPUT
+ * @name $OUTPUT
+ */
+global $OUTPUT;
+
+/**
+ * $THEME is a global that defines the current theme.
  *
  * @global object $THEME
  * @name THEME
@@ -222,7 +230,8 @@ global $SCRIPT;
     require_once($CFG->libdir .'/textlib.class.php');   // Functions to handle multibyte strings
     require_once($CFG->libdir .'/filterlib.php');       // Functions for filtering test as it is output
     require_once($CFG->libdir .'/ajax/ajaxlib.php');    // Functions for managing our use of JavaScript and YUI
-    require_once($CFG->libdir .'/weblib.php');          // Functions for producing HTML
+    require_once($CFG->libdir .'/weblib.php');          // Functions relating to HTTP and content
+    require_once($CFG->libdir .'/outputlib.php');       // Functions for generating output
     require_once($CFG->libdir .'/dmllib.php');          // Database access
     require_once($CFG->libdir .'/datalib.php');         // Legacy lib with a big-mix of functions.
     require_once($CFG->libdir .'/accesslib.php');       // Access control functions
@@ -367,6 +376,10 @@ global $SCRIPT;
         $classname = 'moodle_page';
     }
     $PAGE = new $classname();
+
+/// Create an initial $OUTPUT. This will be changes later once we know the theme.
+    setup_bootstrat_output();
+
     unset($classname);
 
 /// detect unsupported upgrade jump as soon as possible - do not change anything, do not use system functions
index 66cc0f40c14670569d39bf8589d87990b5f23a55..2677ad94b20de6ca17784e63a7935b8891af41ca 100644 (file)
@@ -135,7 +135,7 @@ function default_exception_handler($ex) {
     $place = array('file'=>$ex->getFile(), 'line'=>$ex->getLine(), 'exception'=>get_class($ex));
     array_unshift($backtrace, $place);
 
-    $earlyerror = !isset($CFG->theme) || !isset($CFG->stylesheets);
+    $earlyerror = empty($OUTPUT);
     foreach ($backtrace as $stackframe) {
         if (isset($stackframe['function']) && $stackframe['function'] == 'print_header') {
             $earlyerror = true;
@@ -157,11 +157,190 @@ function default_exception_handler($ex) {
         $debuginfo = null;
     }
 
+    list($message, $moreinfourl, $link) = prepare_error_message($errorcode, $module, $link, $a);
+
     if ($earlyerror) {
-        _print_early_error($errorcode, $module, $a, $backtrace, $debuginfo);
+        // Error found before setup.php finished
+        _print_early_error($message, $backtrace, $debuginfo);
+    } else {
+        echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
+    }
+
+    exit(1); // General error code
+}
+
+/**
+ * Abort execution, displaying an error message.
+ *
+ * @param string $errorcode The name of the language string containing the error message.
+ *      Normally this should be in the error.php lang file.
+ * @param string $module The language file to get the error message from.
+ * @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 void terminates script, does not return!
+ */
+function print_error($errorcode, $module = 'error', $link = '', $a = null) {
+    global $OUTPUT, $UNITTEST;
+
+    // Errors in unit test become exceptions, so you can unit test code that might call print_error().
+    if (!empty($UNITTEST->running)) {
+        throw new moodle_exception($errorcode, $module, $link, $a);
+    }
+
+    list($message, $moreinfourl, $link) = prepare_error_message($errorcode, $module, $link, $a);
+
+    if (empty($OUTPUT)) {
+        // Error found before setup.php finished
+        _print_early_error($message);
+    } else {
+        echo $OUTPUT->fatal_error($message, $moreinfourl, $link, debug_backtrace());
+    }
+
+    exit(1); // General error code
+}
+
+/**
+ * Private method used by print_error and default_exception_handler.
+ * @param $errorcode
+ * @param $module
+ * @param $link
+ * @param $a
+ * @return array
+ */
+function prepare_error_message($errorcode, $module, $link, $a) {
+    global $CFG, $DB, $SESSION;
+
+    if ($DB) {
+        // If you enable db debugging and exception is thrown, the print footer prints a lot of rubbish
+        $DB->set_debug(0);
+    }
+
+    if (empty($module) || $module == 'moodle' || $module == 'core') {
+        $module = 'error';
+    }
+    $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);
+    }
+    $message = clean_text($message);
+
+    if (!empty($CFG->errordocroot)) {
+        $errordocroot = $CFG->errordocroot;
+    } else if (!empty($CFG->docroot)) {
+        $errordocroot = $CFG->docroot;
     } else {
-        _print_normal_error($errorcode, $module, $a, $link, $backtrace, $debuginfo);
+        $errordocroot = 'http://docs.moodle.org';
     }
+    if ($module === 'error') {
+        $modulelink = 'moodle';
+    } else {
+        $modulelink = $module;
+    }
+    $moreinfourl = $errordocroot . '/en/error/' . $modulelink . '/' . $errorcode;
+
+    if (empty($link) && !defined('ADMIN_EXT_HEADER_PRINTED')) {
+        if (!empty($SESSION->fromurl)) {
+            $link = $SESSION->fromurl;
+            unset($SESSION->fromurl);
+        } else {
+            $link = $CFG->wwwroot .'/';
+        }
+    }
+
+    return array($message, $moreinfourl, $link);
+}
+
+/**
+ * Internal function used by print_error. Do not use this directly!!
+ *
+ * Displays a fatal error before the theme is fully initialised.
+ * For example errors that occur during lib/setup.php.
+ *
+ * @param string $message
+ * @param string $link
+ * @param array $backtrace
+ * @param string $debuginfo
+ */
+function _print_early_error($message, $backtrace = null, $debuginfo = null) {
+    // In the name of protocol correctness, monitoring and performance
+    // profiling, set the appropriate error headers for machine comsumption
+    if (isset($_SERVER['SERVER_PROTOCOL'])) {
+        // Avoid it with cron.php. Note that we assume it's HTTP/1.x
+        @header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable');
+    }
+
+    // better disable any caching
+    @header('Content-Type: text/html; charset=utf-8');
+    @header('Cache-Control: no-store, no-cache, must-revalidate');
+    @header('Cache-Control: post-check=0, pre-check=0', false);
+    @header('Pragma: no-cache');
+    @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
+    @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
+
+    echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" ' . get_html_lang() . '>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>' . get_string('error') . '</title>
+</head><body>
+<div style="margin-top: 6em; margin-left:auto; margin-right:auto; color:#990000; text-align:center; font-size:large; border-width:1px;
+    border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse;
+    width: 80%; -moz-border-radius: 20px; padding: 15px">
+' . $message . '
+</div>';
+    if (debugging('', DEBUG_DEVELOPER)) {
+        if (!empty($debuginfo)) {
+            echo '<div class="notifytiny">' . $debuginfo . '</div>';
+        }
+        if (!empty($backtrace)) {
+            echo '<div class="notifytiny">Stack trace: ' . format_backtrace($backtrace, false) . '</div>';
+        }
+    }
+
+    echo '</body></html>';
+}
+
+/**
+ * Formats a backtrace ready for output.
+ *
+ * @param array $callers backtrace array, as returned by debug_backtrace().
+ * @param boolean $plaintext if false, generates HTML, if true generates plain text.
+ * @return string formatted backtrace, ready for output.
+ */
+function format_backtrace($callers, $plaintext = false) {
+    // do not use $CFG->dirroot because it might not be available in desctructors
+    $dirroot = dirname(dirname(__FILE__));
+    if (empty($callers)) {
+        return '';
+    }
+
+    $from = $plaintext ? '' : '<ul style="text-align: left">';
+    foreach ($callers as $caller) {
+        if (!isset($caller['line'])) {
+            $caller['line'] = '?'; // probably call_user_func()
+        }
+        if (!isset($caller['file'])) {
+            $caller['file'] = 'unknownfile'; // probably call_user_func()
+        }
+        $from .= $plaintext ? '* ' : '<li>';
+        $from .= 'line ' . $caller['line'] . ' of ' . str_replace($dirroot, '', $caller['file']);
+        if (isset($caller['function'])) {
+            $from .= ': call to ';
+            if (isset($caller['class'])) {
+                $from .= $caller['class'] . $caller['type'];
+            }
+            $from .= $caller['function'] . '()';
+        } else if (isset($caller['exception'])) {
+            $from .= ': '.$caller['exception'].' thrown';
+        }
+        $from .= $plaintext ? "\n" : '</li>';
+    }
+    $from .= $plaintext ? '' : '</ul>';
+
+    return $from;
 }
 
 /**
index 9aa3f49f31b4c1e150ca7cc79376b1cd3ab71b4d..f3a8cdabaabca111bdb7a5d34f02636c7c57aeba 100644 (file)
@@ -50,7 +50,7 @@ class testable_renderer_factory extends renderer_factory_base {
 
     public function create_renderer($module) {
         $this->createcalls[] = $module;
-        return new moodle_core_renderer(new xhtml_container_stack());
+        return new moodle_core_renderer(new xhtml_container_stack(), null);
     }
 
     public function standard_renderer_class_for_module($module) {
@@ -63,8 +63,8 @@ class testable_renderer_factory extends renderer_factory_base {
  * Renderer class for testing.
  */
 class moodle_test_renderer extends moodle_core_renderer {
-    public function __construct($containerstack) {
-        parent::__construct($containerstack);
+    public function __construct($containerstack, $page) {
+        parent::__construct($containerstack, $page);
     }
 
     public function greeting($name = 'world') {
@@ -155,9 +155,7 @@ class standard_renderer_factory_test extends UnitTestCase {
 
     public function setUp() {
         parent::setUp();
-        $page = new stdClass;
-        $page->opencontainers = new xhtml_container_stack();
-        $this->factory = new standard_renderer_factory(null, $page);
+        $this->factory = new standard_renderer_factory(null, null);
     }
 
     public function tearDown() {
@@ -188,9 +186,7 @@ class custom_corners_renderer_factory_test extends UnitTestCase {
 
     public function setUp() {
         parent::setUp();
-        $page = new stdClass;
-        $page->opencontainers = new xhtml_container_stack();
-        $this->factory = new custom_corners_renderer_factory(null, $page);
+        $this->factory = new custom_corners_renderer_factory(null, null);
     }
 
     public function tearDown() {
@@ -246,7 +242,6 @@ class theme_overridden_renderer_factory_test extends UnitTestCase {
         $this->foldertocleanup = $CFG->themedir;
 
         $this->page = new stdClass;
-        $this->page->opencontainers = new xhtml_container_stack();
     }
 
     public function tearDown() {
@@ -414,7 +409,6 @@ class template_renderer_factory_test extends UnitTestCase {
         $this->foldertocleanup = $CFG->themedir;
 
         $this->page = new stdClass;
-        $this->page->opencontainers = new xhtml_container_stack();
     }
 
     public function tearDown() {
@@ -722,8 +716,10 @@ class template_renderer_test extends UnitTestCase {
         parent::setUp();
         $this->templatefolder = $CFG->dataroot . '/temp/template_renderer_fixtures/test';
         make_upload_directory('temp/template_renderer_fixtures/test');
+        $page = new stdClass;
+        $page->course = new stdClass;
         $this->renderer = new template_renderer('moodle_test_renderer',
-                array($this->templatefolder), new xhtml_container_stack());
+                array($this->templatefolder), new xhtml_container_stack(), $page);
         $this->savedtemplates = array();
     }
 
@@ -788,7 +784,7 @@ class moodle_core_renderer_test extends UnitTestCase {
     public function setUp() {
         parent::setUp();
         $this->containerstack = new xhtml_container_stack();
-        $this->renderer = new moodle_core_renderer($this->containerstack);
+        $this->renderer = new moodle_core_renderer($this->containerstack, null);
     }
 
     public function test_select_menu_simple() {
index 331d908d2e8ea253196380236c6526f631432a39..75c8566f3507f8514b7e6503a13507cbe6b94a0d 100644 (file)
@@ -324,6 +324,32 @@ class moodle_page_test extends UnitTestCase {
         // Validate
         $this->assertEqual('somestring', $this->testpage->subpage);
     }
+
+    public function test_set_heading() {
+        // Exercise SUT
+        $this->testpage->set_heading('a heading');
+        // Validate
+        $this->assertEqual('a heading', $this->testpage->heading);
+    }
+
+    public function test_set_title() {
+        // Exercise SUT
+        $this->testpage->set_title('a title');
+        // Validate
+        $this->assertEqual('a title', $this->testpage->title);
+    }
+
+    public function test_default_generaltype() {
+        // Exercise SUT and Validate
+        $this->assertEqual('normal', $this->testpage->generaltype);
+    }
+
+    public function test_set_generaltype() {
+        // Exercise SUT
+        $this->testpage->set_generaltype('type');
+        // Validate
+        $this->assertEqual('type', $this->testpage->generaltype);
+    }
 }
 
 /**
index c3b5ab5bf0ee6b441f91e2e19996cc4fb5247e1c..d14477d6dc7599279bfecb7b84d5529cd8320f2a 100644 (file)
@@ -674,7 +674,7 @@ function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
 
     $plugin = ($plugin==='moodle') ? null : $plugin;
 
-    $backtrace = print_backtrace($backtrace, true, true);
+    $backtrace = format_backtrace($backtrace, true);
 
     $version = null;
 
index 883225556089661ebc7950263823ea64545202ea..081dd60ee15a3372a05df28986195c566cff8816 100644 (file)
@@ -2329,33 +2329,37 @@ function get_html_lang($dir = false) {
     return ($direction.' lang="'.$language.'" xml:lang="'.$language.'"');
 }
 
+
+/// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
+
 /**
- * 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
- *
- * @return string HTML element.
+ * Send the HTTP headers that Moodle requires.
+ * @param $cacheable Can this page be cached on back?
  */
-function skip_main_destination() {
-    return '<span id="maincontent"></span>';
-}
-
+function send_headers($contenttype, $cacheable = true) {
+    @header('Content-Type: ' . $contenttype);
+    @header('Content-Script-Type: text/javascript');
+    @header('Content-Style-Type: text/css');
 
-/// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
+    if ($cacheable) {
+        // Allow caching on "back" (but not on normal clicks)
+        @header('Cache-Control: private, pre-check=0, post-check=0, max-age=0');
+        @header('Pragma: no-cache');
+        @header('Expires: ');
+    } else {
+        // Do everything we can to always prevent clients and proxies caching
+        @header('Cache-Control: no-store, no-cache, must-revalidate');
+        @header('Cache-Control: post-check=0, pre-check=0', false);
+        @header('Pragma: no-cache');
+        @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
+        @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
+    }
+    @header('Accept-Ranges: none');
+}
 
 /**
  * Print a standard header
  *
- * @global object
- * @global object
- * @global object
- * @global object
- * @global string Doesnt appear to be used here
- * @global string Doesnt appear to be used here
- * @global object
- * @global object
- * @uses $_SERVER
  * @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
@@ -2369,7 +2373,7 @@ function skip_main_destination() {
  * @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='',
+function print_header_old($title='', $heading='', $navigation='', $focus='',
                        $meta='', $cache=true, $button='&nbsp;', $menu='',
                        $usexml=false, $bodytags='', $return=false) {
 
@@ -2603,63 +2607,6 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
     }
 }
 
-/**
- * Debugging aid: serve page as 'application/xhtml+xml' where possible,
- *     and substitute the XHTML strict document type.
- *     Note, requires the 'xmlns' fix in function print_header above.
- *     See:  {@link http://tracker.moodle.org/browse/MDL-7883}
- *
- * @global object
- * @uses $_SERVER
- * @param string The HTML to apply the strict header to
- * @return string The HTML with strict header
- */
-function force_strict_header($output) {
-    global $CFG;
-    $strict = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
-    $xsl = '/lib/xhtml.xsl';
-
-    if (!headers_sent() && !empty($CFG->xmlstrictheaders)) {   // With xml strict headers, the browser will barf
-        $ctype = 'Content-Type: ';
-        $prolog= "<?xml version='1.0' encoding='utf-8'?>\n";
-
-        if (isset($_SERVER['HTTP_ACCEPT'])
-            && false !== strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml')) {
-            //|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') //Safari "Entity 'copy' not defined".
-            // Firefox et al.
-            $ctype .= 'application/xhtml+xml';
-            $prolog .= "<!--\n  DEBUG: $ctype \n-->\n";
-
-        } else if (file_exists($CFG->dirroot.$xsl)
-            && preg_match('/MSIE.*Windows NT/', $_SERVER['HTTP_USER_AGENT'])) {
-            // XSL hack for IE 5+ on Windows.
-            //$www_xsl = preg_replace('/(http:\/\/.+?\/).*/', '', $CFG->wwwroot) .$xsl;
-            $www_xsl = $CFG->wwwroot .$xsl;
-            $ctype .= 'application/xml';
-            $prolog .= "<?xml-stylesheet type='text/xsl' href='$www_xsl'?>\n";
-            $prolog .= "<!--\n  DEBUG: $ctype \n-->\n";
-
-        } else {
-            //ELSE: Mac/IE, old/non-XML browsers.
-            $ctype .= 'text/html';
-            $prolog = '';
-        }
-        @header($ctype.'; charset=utf-8');
-        $output = $prolog . $output;
-
-        // Test parser error-handling.
-        if (isset($_GET['error'])) {
-            $output .= "__ TEST: XML well-formed error < __\n";
-        }
-    }
-
-    $output = preg_replace('/(<!DOCTYPE.+?>)/s', $strict, $output);   // Always change the DOCTYPE to Strict 1.0
-
-    return $output;
-}
-
-
-
 /**
  * This version of print_header is simpler because the course name does not have to be
  * provided explicitly in the strings. It can be used on the site page as in courses
@@ -2728,7 +2675,7 @@ function print_header_simple($title='', $heading='', $navigation='', $focus='',
  * @param boolean $return output as string
  * @return mixed string or void
  */
-function print_footer($course=NULL, $usercourse=NULL, $return=false) {
+function print_footer_old($course=NULL, $usercourse=NULL, $return=false) {
     global $USER, $CFG, $THEME, $COURSE, $SITE, $PAGE;
 
     if (defined('ADMIN_EXT_HEADER_PRINTED') and !defined('ADMIN_EXT_FOOTER_PRINTED')) {
@@ -3225,10 +3172,6 @@ function theme_setup($theme = '', $params=NULL) {
         $CFG->modpixpath = $CFG->themewww .'/'. $theme .'/pix/mod';
     }
 
-/// Header and footer paths
-    $CFG->header = $CFG->themedir .'/'. $theme .'/header.html';
-    $CFG->footer = $CFG->themedir .'/'. $theme .'/footer.html';
-
 /// Define stylesheet loading order
     $CFG->stylesheets = array();
     if ($theme != 'standard') {    /// The standard sheet is always loaded first
@@ -3286,6 +3229,10 @@ function theme_setup($theme = '', $params=NULL) {
 function user_login_string($course=NULL, $user=NULL) {
     global $USER, $CFG, $SITE, $DB;
 
+    if (during_initial_install()) {
+        return '';
+    }
+
     if (empty($user) and !empty($USER->id)) {
         $user = $USER;
     }
@@ -3335,7 +3282,31 @@ function user_login_string($course=NULL, $user=NULL) {
         $loggedinas = get_string('loggedinnot', 'moodle').
                       " (<a $CFG->frametarget href=\"$loginurl\">".get_string('login').'</a>)';
     }
-    return '<div class="logininfo">'.$loggedinas.'</div>';
+
+    $loggedinas = '<div class="logininfo">'.$loggedinas.'</div>';
+
+    if (isset($SESSION->justloggedin)) {
+        unset($SESSION->justloggedin);
+        if (!empty($CFG->displayloginfailures)) {
+            if (!empty($USER->username) and $USER->username != 'guest') {
+                if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) {
+                    $loggedinas .= '&nbsp;<div class="loginfailures">';
+                    if (empty($count->accounts)) {
+                        $loggedinas .= get_string('failedloginattempts', '', $count);
+                    } else {
+                        $loggedinas .= get_string('failedloginattemptsall', '', $count);
+                    }
+                    if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) {
+                        $loggedinas .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php'.
+                                             '?chooselog=1&amp;id=1&amp;modid=site_errors">'.get_string('logs').'</a>)';
+                    }
+                    $loggedinas .= '</div>';
+                }
+            }
+        }
+    }
+
+    return $loggedinas;
 }
 
 /**
@@ -3743,70 +3714,6 @@ function build_navigation($extranavlinks, $cm = null) {
     return(array('newnav' => true, 'navlinks' => $navigation));
 }
 
-
-/**
- * Prints a string in a specified size  (retained for backward compatibility)
- *
- * @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) {
-    $output = print_heading($text, '', $size, true);
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-/**
- * Prints text in a format for use in headings.
- *
- * @global string Apparently not used in this function
- * @uses CLI_SCRIPT
- * @param string $text The text to be displayed
- * @param string $align The alignment of the printed paragraph of text
- * @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, $align='', $size=2, $class='main', $return=false, $id='') {
-    global $verbose;
-    if ($align) {
-        $align = ' style="text-align:'.$align.';"';
-    }
-    if ($class) {
-        $class = ' class="'.$class.'"';
-    }
-    if ($id) {
-        $id = ' id="'.$id.'"';
-    }
-    if (!CLI_SCRIPT) {
-        $output = "<h$size $align $class $id>".$text."</h$size>";
-    } else {
-        $output = $text;
-        if ($size == 1) {
-            $output = '=>'.$output;
-        } else if ($size == 2) {
-            $output = '-->'.$output;
-        }
-    }
-
-    if ($return) {
-        return $output;
-    } else {
-        if (!CLI_SCRIPT) {
-            echo $output;
-        } else {
-            echo $output."\n";
-        }
-    }
-}
-
 /**
  * Centered heading with attached help button (same title text)
  * and optional icon attached
@@ -3831,132 +3738,6 @@ function print_heading_with_help($text, $helppage, $module='moodle', $icon='', $
     }
 }
 
-/**
- * Output a standard heading block
- *
- * @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) {
-    //Accessibility: 'headingblock' is now H1, see theme/standard/styles_*.css: ??
-    $output = '<h2 class="headingblock header '.$class.'">'.$heading.'</h2>';
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-
-/**
- * Print a link to continue on to another page.
- *
- * @global object
- * @uses $_SERVER
- * @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('&', '&amp;', $link); // make it valid XHTML
-        } else {
-            $link = $CFG->wwwroot .'/';
-        }
-    }
-
-    $options = array();
-    $linkparts = parse_url(str_replace('&amp;', '&', $link));
-    if (isset($linkparts['query'])) {
-        parse_str($linkparts['query'], $options);
-    }
-
-    $output .= '<div class="continuebutton">';
-
-    $output .= print_single_button($link, $options, get_string('continue'), 'get', $CFG->framename, true);
-    $output .= '</div>'."\n";
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-
-/**
- * Print a message in a standard themed box.
- * Replaces print_simple_box (see deprecatedlib.php)
- *
- * @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) {
-
-    $output  = print_box_start($classes, $ids, true);
-    $output .= $message;
-    $output .= print_box_end(true);
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-/**
- * Starts a box using divs
- * Replaces print_simple_box_start (see deprecatedlib.php)
- *
- * @global object
- * @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 $THEME;
-
-    if (strpos($classes, 'clearfix') !== false) {
-        $clearfix = true;
-        $classes = trim(str_replace('clearfix', '', $classes));
-    } else {
-        $clearfix = false;
-    }
-
-    if (!empty($THEME->customcorners)) {
-        $classes .= ' ccbox box';
-    } else {
-        $classes .= ' box';
-    }
-
-    return print_container_start($clearfix, $classes, $ids, $return);
-}
-
-/**
- * Simple function to end a box (see above)
- * Replaces print_simple_box_end (see deprecatedlib.php)
- *
- * @param boolean $return, return as string or just print it
- * @return string|void Depending on value of return
- */
-function print_box_end($return=false) {
-    return print_container_end($return);
-}
-
 /**
  * Print (or return) a collapisble region, that has a caption that can
  * be clicked to expand or collapse the region.
@@ -4051,107 +3832,6 @@ function print_collapsible_region_end($return = false) {
     }
 }
 
-/**
- * Print a message in a standard themed container.
- *
- * @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) {
-
-    $output  = print_container_start($clearfix, $classes, $idbase, true);
-    $output .= $message;
-    $output .= print_container_end(true);
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-/**
- * Starts a container using divs
- *
- * @global object
- * @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 $THEME;
-
-    if (!isset($THEME->open_containers)) {
-        $THEME->open_containers = array();
-    }
-    $THEME->open_containers[] = $idbase;
-
-
-    if (!empty($THEME->customcorners)) {
-        $output = _print_custom_corners_start($clearfix, $classes, $idbase);
-    } else {
-        if ($idbase) {
-            $id = ' id="'.$idbase.'"';
-        } else {
-            $id = '';
-        }
-        if ($clearfix) {
-            $clearfix = ' clearfix';
-        } else {
-            $clearfix = '';
-        }
-        if ($classes or $clearfix) {
-            $class = ' class="'.$classes.$clearfix.'"';
-        } else {
-            $class = '';
-        }
-        $output = '<div'.$id.$class.'>';
-    }
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
-/**
- * Simple function to end a container (see above)
- *
- * @global object
- * @uses DEBUG_DEVELOPER
- * @param boolean $return, return as string or just print it
- * @return string|void Based on $return
- */
-function print_container_end($return=false) {
-    global $THEME;
-
-    if (empty($THEME->open_containers)) {
-        debugging('Incorrect request to end container - no more open containers.', DEBUG_DEVELOPER);
-        $idbase = '';
-    } else {
-        $idbase = array_pop($THEME->open_containers);
-    }
-
-    if (!empty($THEME->customcorners)) {
-        $output = _print_custom_corners_end($idbase);
-    } else {
-        $output = '</div>';
-    }
-
-    if ($return) {
-        return $output;
-    } else {
-        echo $output;
-    }
-}
-
 /**
  * Returns number of currently open containers
  *
@@ -5681,207 +5361,6 @@ function print_scale_menu_helpbutton($courseid, $scale, $return=false) {
     }
 }
 
-/**
- * Print an error page displaying an error message.  New method - use this for new code.
- *
- * @global object
- * @global object
- * @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 void 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!!
- *
- * @global object
- * @global object
- * @global object
- * @global object
- * @global object
- * @param string $errorcode
- * @param string $module
- * @param string $a
- * @param string $link
- * @param array $backtrace
- * @param string $debuginfo
- * @param bool $showerrordebugwarning
- * @return void Script dies no return
- */
-function _print_normal_error($errorcode, $module, $a, $link, $backtrace, $debuginfo=null, $showerrordebugwarning=false) {
-    global $CFG, $SESSION, $THEME, $DB, $PAGE;
-
-    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 (CLI_SCRIPT) {
-        echo("!!! $message !!!\n");
-        if (debugging('', DEBUG_DEVELOPER)) {
-            if ($debuginfo) {
-                debugging($debuginfo, DEBUG_DEVELOPER, $backtrace);
-            } else {
-                notify('Stack trace:'.print_backtrace($backtrace, true, true), 'notifytiny');
-            }
-        }
-        exit(1); // general error code
-    }
-
-    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 (!$PAGE->headerprinted) {
-        //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 '<br />';
-
-    $message = clean_text('<p class="errormessage">'.$message.'</p>'.
-               '<p class="errorcode">'.
-               '<a href="'.$errordocroot.'/en/error/'.$modulelink.'/'.$errorcode.'">'.
-                 get_string('moreinformation').'</a></p>');
-
-    print_simple_box($message, '', '', '', '', 'errorbox');
-
-    if ($showerrordebugwarning) {
-        debugging('error() is a deprecated function, please call print_error() instead of error()', DEBUG_DEVELOPER);
-
-    } else {
-        if (debugging('', DEBUG_DEVELOPER)) {
-            if ($debuginfo) {
-                debugging($debuginfo, DEBUG_DEVELOPER, $backtrace);
-            } else {
-                notify('Stack trace:'.print_backtrace($backtrace, false, true), 'notifytiny');
-            }
-        }
-    }
-
-    if (!empty($link)) {
-        print_continue($link);
-    }
-
-    print_footer();
-
-    for ($i=0;$i<512;$i++) {  // Padding to help IE work with 404
-        echo ' ';
-    }
-    exit(1); // general error code
-}
-
-/**
- * Internal function - do not use directly!!
- * This function is used if fatal error occures before the themes are fully initialised (eg. in lib/setup.php)
- *
- * @uses $_SERVER
- * @uses DEBUG_DEVELOPER
- * @param string $errorcode
- * @param string $module
- * @param string $a
- * @param string $link
- * @param array $backtrace
- * @param string $debuginfo
- * @return void Script dies does not return
- */
-function _print_early_error($errorcode, $module, $a, $backtrace=null, $debuginfo=null) {
-    $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);
-    }
-    $message = clean_text($message);
-
-    // In the name of protocol correctness, monitoring and performance
-    // profiling, set the appropriate error headers for machine comsumption
-    if (isset($_SERVER['SERVER_PROTOCOL'])) {
-        // Avoid it with cron.php. Note that we assume it's HTTP/1.x
-        @header($_SERVER['SERVER_PROTOCOL'] . ' 503 Service Unavailable');
-    }
-
-    // better disable any caching
-    @header('Content-Type: text/html; charset=utf-8');
-    @header('Cache-Control: no-store, no-cache, must-revalidate');
-    @header('Cache-Control: post-check=0, pre-check=0', false);
-    @header('Pragma: no-cache');
-    @header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
-    @header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
-
-    echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" '.get_html_lang().'>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>'.get_string('error').'</title>
-</head><body>
-<div style="margin-top: 6em; margin-left:auto; margin-right:auto; color:#990000; text-align:center; font-size:large; border-width:1px;
-    border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse;
-    width: 80%; -moz-border-radius: 20px; padding: 15px">
-'.$message.'
-</div>';
-    if (debugging('', DEBUG_DEVELOPER)) {
-        if ($debuginfo) {
-            debugging($debuginfo, DEBUG_DEVELOPER, $backtrace);
-        } else if ($backtrace) {
-            notify('Stack trace:'.print_backtrace($backtrace, false, true), 'notifytiny');
-        }
-    }
-
-    echo '</body></html>';
-    exit(1); // general error code
-}
-
 /**
  * Print an error to STDOUT and exit with a non-zero code. For commandline scripts.
  * Default errorcode is 1.
@@ -6286,43 +5765,6 @@ function redirect($url, $message='', $delay=-1) {
     die;
 }
 
-/**
- * Print a bold message in an optional color.
- *
- * @global object
- * @uses CLI_SCRIPT
- * @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, $style='notifyproblem', $align='center', $return=false) {
-    global $DB;
-
-    if ($style == 'green') {
-        $style = 'notifysuccess';  // backward compatible with old color system
-    }
-
-    $message = clean_text($message);
-    if (!CLI_SCRIPT) {
-        $output = '<div class="'.$style.'" style="text-align:'. $align .'">'. $message .'</div>'."\n";
-    } else {
-        if ($style === 'notifysuccess') {
-            $output = '++'.$message.'++'."\n";
-        } else {
-            $output = '!!'.$message.'!!'."\n";
-        }
-    }
-
-    if ($return) {
-        return $output;
-    }
-
-    echo $output;
-}
-
-
 /**
  * Given an email address, this function will return an obfuscated version of it
  *
@@ -6918,34 +6360,6 @@ function convert_tabrows_to_tree($tabrows, $selected, $inactive, $activated) {
     return $subtree;
 }
 
-
-/**
- * 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);
-}
-
 /**
  * Returns the Moodle Docs URL in the users language
  *
@@ -7021,85 +6435,32 @@ function doc_link($path='', $text='', $iconpath='') {
  * @param array $backtrace use different backtrace
  * @return bool
  */
-function debugging($message='', $level=DEBUG_NORMAL, $backtrace=null) {
-
+function debugging($message = '', $level = DEBUG_NORMAL, $backtrace = null) {
     global $CFG;
 
-    if (empty($CFG->debug)) {
+    if (empty($CFG->debug) || $CFG->debug < $level) {
         return false;
     }
 
-    if ($CFG->debug >= $level) {
-        if ($message) {
-            if (!$backtrace) {
-                $backtrace = debug_backtrace();
-            }
-            $from = print_backtrace($backtrace, CLI_SCRIPT, true);
-            if (!isset($CFG->debugdisplay)) {
-                $CFG->debugdisplay = ini_get_bool('display_errors');
-            }
-            if ($CFG->debugdisplay) {
-                if (!defined('DEBUGGING_PRINTED')) {
-                    define('DEBUGGING_PRINTED', 1); // indicates we have printed something
-                }
-                notify($message . $from, 'notifytiny');
-            } else {
-                trigger_error($message . $from, E_USER_NOTICE);
-            }
-        }
-        return true;
-    }
-    return false;
-}
-
-/**
- * Prints formatted backtrace
- *
- * @global object
- * @param array $callers backtrace array
- * @param bool $return return as string or print
- * @return string|bool Depending on $return
- */
-function print_backtrace($callers, $plaintext=false, $return=false) {
-    // do not use $CFG->dirroot because it might not be available in desctructors
-    $dirroot = dirname(dirname(__FILE__));
-    if (empty($callers)) {
-        if ($return) {
-            return '';
-        } else {
-            return;
-        }
+    if (!isset($CFG->debugdisplay)) {
+        $CFG->debugdisplay = ini_get_bool('display_errors');
     }
 
-    $from = $plaintext ? '' : '<ul style="text-align: left">';
-    foreach ($callers as $caller) {
-        if (!isset($caller['line'])) {
-            $caller['line'] = '?'; // probably call_user_func()
-        }
-        if (!isset($caller['file'])) {
-            $caller['file'] = 'unknownfile'; // probably call_user_func()
+    if ($message) {
+        if (!$backtrace) {
+            $backtrace = debug_backtrace();
         }
-        $from .= $plaintext ? '* ' : '<li>';
-        $from .= 'line ' . $caller['line'] . ' of ' . str_replace($dirroot, '', $caller['file']);
-        if (isset($caller['function'])) {
-            $from .= ': call to ';
-            if (isset($caller['class'])) {
-                $from .= $caller['class'] . $caller['type'];
+        $from = format_backtrace($backtrace, CLI_SCRIPT);
+        if ($CFG->debugdisplay) {
+            if (!defined('DEBUGGING_PRINTED')) {
+                define('DEBUGGING_PRINTED', 1); // indicates we have printed something
             }
-            $from .= $caller['function'] . '()';
-        } else if (isset($caller['exception'])) {
-            $from .= ': '.$caller['exception'].' thrown';
+            notify($message . $from, 'notifytiny');
+        } else {
+            trigger_error($message . $from, E_USER_NOTICE);
         }
-        $from .= $plaintext ? "\n" : '</li>';
-    }
-    $from .= $plaintext ? '' : '</ul>';
-
-    if ($return) {
-        return $from;
-    } else {
-        echo $from;
     }
+    return true;
 }
 
 /**
index 0bef0b6d9a83b96115bafc13274254a2eb00351d..9e21d13f264964b83b8ed4bd0e3f93a8ba6966a3 100755 (executable)
 
 
 /// RSS and CSS and JS meta
-    $meta = '';
     if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) {
         $rsspath = rss_get_url($course->id, $USER->id, 'data', $data->id);
-        $meta .= '<link rel="alternate" type="application/rss+xml" ';
-        $meta .= 'title ="'. format_string($course->shortname) .': %fullname%" href="'.$rsspath.'" />';
+        $PAGE->add_alternate_version(format_string($course->shortname) . ': %fullname%',
+                $rsspath, 'application/rss+xml');
     }
     if ($data->csstemplate) {
-        $meta .= '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/mod/data/css.php?d='.$data->id.'" /> ';
+        $PAGE->requires->css('mod/data/css.php?d='.$data->id);
     }
     if ($data->jstemplate) {
         $PAGE->requires->js('mod/data/js.php?d='.$data->id)->in_head();
 
     $navigation = build_navigation('', $cm);
     print_header_simple($data->name, '', $navigation,
-                        '', $meta, true, update_module_button($cm->id, $course->id, get_string('modulename', 'data')),
+                        '', '', true, update_module_button($cm->id, $course->id, get_string('modulename', 'data')),
                         navmenu($course, $cm), '', '');
 
 /// Check to see if groups are being used here
index 181e7ac98d654a6a2e69a33f1aaaf9778db7004d..840ff67cf88a89b349bc264c83ea6ca6a4610c66 100755 (executable)
     $meta = '';
     if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) {
         $rsspath = rss_get_url($course->id, $USER->id, 'data', $data->id);
-        $meta .= '<link rel="alternate" type="application/rss+xml" ';
-        $meta .= 'title ="'. format_string($course->shortname) .': %fullname%" href="'.$rsspath.'" />';
+        $PAGE->add_alternate_version(format_string($course->shortname) . ': %fullname%',
+                $rsspath, 'application/rss+xml');
     }
     if ($data->csstemplate) {
-        $meta .= '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/mod/data/css.php?d='.$data->id.'" /> ';
+        $PAGE->requires->css('mod/data/css.php?d='.$data->id);
     }
     if ($data->jstemplate) {
         $PAGE->requires->js('mod/data/js.php?d='.$data->id)->in_head();
index 006b71e0d22c8fce2ff440f55dece9e491a32816..2b67a562378ff4e9b3f13997f4f3b4a9c7626274 100644 (file)
@@ -441,9 +441,7 @@ $strupdatemodule = has_capability('moodle/course:manageactivities',
         get_string('modulename', 'quiz')) :
         "";
 $navigation = build_navigation($pagetitle, $cm);
-$localcss = '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.
-        '/lib/yui/container/assets/container.css" />';
-print_header_simple($pagetitle, '', $navigation, "", $localcss, true,
+print_header_simple($pagetitle, '', $navigation, '', '', true,
         $questionbankmanagement.$strupdatemodule);
 //TODO: these skip links really need to be right after the opening of the body element,
 // and preferably implemented in an <ul> element. See MDL-17730.
index c08a734c2b1174a1f7a506ec7f9348542469dd42..b77bd1eff23abe0e9cdccfd873cb491a182f6a5b 100644 (file)
@@ -21,7 +21,7 @@ class quiz_default_report {
         return true;
     }
 
-    function print_header_and_tabs($cm, $course, $quiz, $reportmode="overview", $meta=""){
+    function print_header_and_tabs($cm, $course, $quiz, $reportmode="overview"{
         global $CFG;
     /// Define some strings
         $strquizzes = get_string("modulenameplural", "quiz");
@@ -30,7 +30,7 @@ class quiz_default_report {
         $navigation = build_navigation('', $cm);
         
         print_header_simple(format_string($quiz->name), "", $navigation,
-                     '', $meta, true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm));
+                     '', '', true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm));
     /// Print the tabs    
         $currenttab = 'reports';
         $mode = $reportmode;
index cb2dd2b2669d4bccb0137d22d15e81aca7eff678..813f551a22ee83d4dfb23c5cc1a510abca8234f0 100644 (file)
@@ -17,7 +17,7 @@ class quiz_responses_report extends quiz_default_report {
      * Display the report.
      */
     function display($quiz, $cm, $course) {
-        global $CFG, $COURSE, $DB;
+        global $CFG, $COURSE, $DB, $PAGE;
 
         $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
@@ -131,9 +131,10 @@ class quiz_responses_report extends quiz_default_report {
         $table->is_downloading($download, get_string('reportresponses','quiz_responses'),
                     "$COURSE->shortname ".format_string($quiz->name,true));
         if (!$table->is_downloading()) {
+            
             // Only print headers if not asked to download data
-            $meta = '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/mod/quiz/report/responses/styles.css" />'."\n";
-            $this->print_header_and_tabs($cm, $course, $quiz, "responses", $meta);
+            $PAGE->requires->css('mod/quiz/report/responses/styles.css');
+            $this->print_header_and_tabs($cm, $course, $quiz, 'responses', '');
         }
 
         if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used
index 2579b71590bc88b46916859e79ca4add9c17c2fc..1c891a45d8b192b0d83a4b9d17267da0337f1243 100644 (file)
@@ -52,7 +52,7 @@
         $navlinks[] = array('name' => format_string($module->name), 'link' => "$CFG->wwwroot/mod/{$cm->modname}/view.php?id={$cm->id}", 'type' => 'title');
         $navlinks[] = array('name' => $streditingquestions, 'link' => '', 'type' => 'title');
         $navigation = build_navigation($navlinks);
-        print_header_simple($streditingquestions, '', $navigation, '', $localcss, true, $strupdatemodule);
+        print_header_simple($streditingquestions, '', $navigation, '', '', true, $strupdatemodule);
 
         $currenttab = 'edit';
         $mode = 'questions';
@@ -64,7 +64,7 @@
         $navlinks[] = array('name' => $streditingquestions, 'link' => '', 'type' => 'title');
         $navigation = build_navigation($navlinks);
 
-        print_header_simple($streditingquestions, '', $navigation, '', $localcss);
+        print_header_simple($streditingquestions, '', $navigation, '', '');
 
         // print tabs
         $currenttab = 'questions';
index 4f5158b8772079b23abbbce27dc807f4ce9708e0..d191493c2e102b47b79045f8e1a7ab9b3b8ba52d 100644 (file)
@@ -241,7 +241,6 @@ if ($mform->is_cancelled()){
 } else {
 
     $streditingquestion = $QTYPES[$question->qtype]->get_heading();
-    $headtags = get_editing_head_contributions($question);
     if ($cm !== null) {
         $strmodule = get_string('modulename', $cm->modname);
         $strupdatemodule = has_capability('moodle/course:manageactivities', get_context_instance(CONTEXT_COURSE, $COURSE->id))
@@ -259,7 +258,7 @@ if ($mform->is_cancelled()){
         }
         $navlinks[] = array('name' => $streditingquestion, 'link' => '', 'type' => 'title');
         $navigation = build_navigation($navlinks);
-        print_header_simple($streditingquestion, '', $navigation, '', $headtags, true, $strupdatemodule);
+        print_header_simple($streditingquestion, '', $navigation, '', '', true, $strupdatemodule);
 
     } else {
         $navlinks = array();
@@ -268,7 +267,7 @@ if ($mform->is_cancelled()){
         $strediting = '<a href="edit.php?courseid='.$COURSE->id.'">'.
                 get_string("editquestions", "quiz").'</a> -> '.$streditingquestion;
         $navigation = build_navigation($navlinks);
-        print_header_simple($streditingquestion, '', $navigation, '', $headtags);
+        print_header_simple($streditingquestion, '', $navigation, '', '');
     }
 
     // Display a heading, question editing form and possibly some extra content needed for
index f182eb0206175b30b3e52ba11b633f05d2f94bba..e3d14dedca3f3200a76556ec1060b96ee6562504 100644 (file)
@@ -178,4 +178,12 @@ $THEME->defaultblockregion = 'side-post';
 /// added a block when anther theme was selected).
 ////////////////////////////////////////////////////////////////////////////////
 
-?>
+
+$THEME->rendererfactory = 'standard_renderer_factory';
+/// This is an advanced features that lets you control the HTML that Moodle
+/// generates. You need to specify a class that implements the renderer_factory
+/// interface. As well as the default 'standard_renderer_factory', there is
+/// also the experimental 'template_renderer_factory', or you could implement
+/// your own. For more information, please see
+/// http://docs.moodle.org/en/Developement:How_Moodle_outputs_HTML
+////////////////////////////////////////////////////////////////////////////////
diff --git a/theme/standard/layout-home.php b/theme/standard/layout-home.php
new file mode 100644 (file)
index 0000000..28edf44
--- /dev/null
@@ -0,0 +1,46 @@
+<?php echo $OUTPUT->doctype() ?>
+<html <?php echo $OUTPUT->htmlattributes() ?>>
+<head>
+    <?php echo $OUTPUT->standard_head_html() ?>
+    <title><?php echo $PAGE->title ?></title>
+    <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
+    <meta name="description" content="<?php echo strip_tags(format_text($SITE->summary, FORMAT_HTML)) ?>" />
+</head>
+<body id="<?php echo $PAGE->pagetype ?>" class="<?php echo $PAGE->bodyclasses ?>">
+<?php echo $OUTPUT->standard_top_of_body_html() ?>
+
+<div id="page">
+
+    <div id="header-home" class="clearfix">
+        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
+        <div class="headermenu"><?php
+        if ($menu) {
+            echo $menu;
+        } else {
+            echo $OUTPUT->login_info();
+        }
+        ?></div>
+    </div>
+    <hr />
+<!-- END OF HEADER -->
+
+    <div id="content" class="clearfix">
+        [MAIN CONTENT GOES HERE]
+    </div>
+
+<!-- START OF FOOTER -->
+    <div id="footer" class="clearfix">
+        <p class="helplink">
+        <?php echo page_doc_link(get_string('moodledocslink')) ?>
+        </p>
+
+        <?php
+        echo $OUTPUT->login_info();
+        echo $OUTPUT->home_link();
+        echo $OUTPUT->standard_footer_html();
+        ?>
+    </div>
+</div>
+<?php echo $OUTPUT->standard_end_of_body_html() ?>
+</body>
+</html>
\ No newline at end of file
diff --git a/theme/standard/layout.php b/theme/standard/layout.php
new file mode 100644 (file)
index 0000000..f0c441a
--- /dev/null
@@ -0,0 +1,49 @@
+<?php echo $OUTPUT->doctype() ?>
+<html <?php echo $OUTPUT->htmlattributes() ?>>
+<head>
+    <title><?php echo $PAGE->title ?></title>
+    <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
+    <?php echo $OUTPUT->standard_head_html() ?>
+</head>
+<body id="<?php echo $PAGE->pagetype ?>" class="<?php echo $PAGE->bodyclasses ?>">
+<?php echo $OUTPUT->standard_top_of_body_html() ?>
+
+<div id="page">
+
+<?php if ($PAGE->heading) { ?>
+    <div id="header" class="clearfix">
+        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
+        <div class="headermenu"><?php echo $menu ?></div>
+    </div>
+<?php } ?>
+
+<?php if ($navigation) { // This is the navigation bar with breadcrumbs  ?>
+    <div class="navbar clearfix">
+        <div class="breadcrumb"><?php print_navigation($navigation); ?></div>
+        <div class="navbutton"><?php echo $PAGE->button; ?></div>
+    </div>
+<?php } else if ($PAGE->heading) { // If no navigation, but a heading, then print a line ?>
+    <hr />
+<?php } ?>
+<!-- END OF HEADER -->
+
+    <div id="content" class="clearfix">
+        [MAIN CONTENT GOES HERE]
+    </div>
+
+<!-- START OF FOOTER -->
+    <div id="footer" class="clearfix">
+        <p class="helplink">
+        <?php echo page_doc_link(get_string('moodledocslink')) ?>
+        </p>
+
+        <?php
+        echo $OUTPUT->login_info();
+        echo $OUTPUT->home_link();
+        echo $OUTPUT->standard_footer_html();
+        ?>
+    </div>
+</div>
+<?php echo $OUTPUT->standard_end_of_body_html() ?>
+</body>
+</html>
\ No newline at end of file
diff --git a/theme/standardwhite/layout-home.php b/theme/standardwhite/layout-home.php
new file mode 100644 (file)
index 0000000..28edf44
--- /dev/null
@@ -0,0 +1,46 @@
+<?php echo $OUTPUT->doctype() ?>
+<html <?php echo $OUTPUT->htmlattributes() ?>>
+<head>
+    <?php echo $OUTPUT->standard_head_html() ?>
+    <title><?php echo $PAGE->title ?></title>
+    <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
+    <meta name="description" content="<?php echo strip_tags(format_text($SITE->summary, FORMAT_HTML)) ?>" />
+</head>
+<body id="<?php echo $PAGE->pagetype ?>" class="<?php echo $PAGE->bodyclasses ?>">
+<?php echo $OUTPUT->standard_top_of_body_html() ?>
+
+<div id="page">
+
+    <div id="header-home" class="clearfix">
+        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
+        <div class="headermenu"><?php
+        if ($menu) {
+            echo $menu;
+        } else {
+            echo $OUTPUT->login_info();
+        }
+        ?></div>
+    </div>
+    <hr />
+<!-- END OF HEADER -->
+
+    <div id="content" class="clearfix">
+        [MAIN CONTENT GOES HERE]
+    </div>
+
+<!-- START OF FOOTER -->
+    <div id="footer" class="clearfix">
+        <p class="helplink">
+        <?php echo page_doc_link(get_string('moodledocslink')) ?>
+        </p>
+
+        <?php
+        echo $OUTPUT->login_info();
+        echo $OUTPUT->home_link();
+        echo $OUTPUT->standard_footer_html();
+        ?>
+    </div>
+</div>
+<?php echo $OUTPUT->standard_end_of_body_html() ?>
+</body>
+</html>
\ No newline at end of file
diff --git a/theme/standardwhite/layout.php b/theme/standardwhite/layout.php
new file mode 100644 (file)
index 0000000..f0c441a
--- /dev/null
@@ -0,0 +1,49 @@
+<?php echo $OUTPUT->doctype() ?>
+<html <?php echo $OUTPUT->htmlattributes() ?>>
+<head>
+    <title><?php echo $PAGE->title ?></title>
+    <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
+    <?php echo $OUTPUT->standard_head_html() ?>
+</head>
+<body id="<?php echo $PAGE->pagetype ?>" class="<?php echo $PAGE->bodyclasses ?>">
+<?php echo $OUTPUT->standard_top_of_body_html() ?>
+
+<div id="page">
+
+<?php if ($PAGE->heading) { ?>
+    <div id="header" class="clearfix">
+        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
+        <div class="headermenu"><?php echo $menu ?></div>
+    </div>
+<?php } ?>
+
+<?php if ($navigation) { // This is the navigation bar with breadcrumbs  ?>
+    <div class="navbar clearfix">
+        <div class="breadcrumb"><?php print_navigation($navigation); ?></div>
+        <div class="navbutton"><?php echo $PAGE->button; ?></div>
+    </div>
+<?php } else if ($PAGE->heading) { // If no navigation, but a heading, then print a line ?>
+    <hr />
+<?php } ?>
+<!-- END OF HEADER -->
+
+    <div id="content" class="clearfix">
+        [MAIN CONTENT GOES HERE]
+    </div>
+
+<!-- START OF FOOTER -->
+    <div id="footer" class="clearfix">
+        <p class="helplink">
+        <?php echo page_doc_link(get_string('moodledocslink')) ?>
+        </p>
+
+        <?php
+        echo $OUTPUT->login_info();
+        echo $OUTPUT->home_link();
+        echo $OUTPUT->standard_footer_html();
+        ?>
+    </div>
+</div>
+<?php echo $OUTPUT->standard_end_of_body_html() ?>
+</body>
+</html>
\ No newline at end of file