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.
$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);
}
- print_footer(NULL, $course);
+ print_footer();
?>
* @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');
}
$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) {
// 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;
$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();
?>
* 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%'.
* @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 = '';
echo $OUTPUT->error_text($error);
}
+/**
+ * Return the markup for the destination of the 'Skip to main content' links.
+ * Accessibility improvement for keyboard-only users.
+ *
+ * Used in course formats, /index.php and /course/index.php
+ *
+ * @deprecated use $OUTPUT->skip_link_target() in instead.
+ * @return string HTML element.
+ */
+function skip_main_destination() {
+ global $OUTPUT;
+ return $OUTPUT->skip_link_target();
+}
+
+/**
+ * Prints a string in a specified size (retained for backward compatibility)
+ *
+ * @deprecated
+ * @param string $text The text to be displayed
+ * @param int $size The size to set the font for text display.
+ * @param bool $return If set to true output is returned rather than echoed Default false
+ * @return string|void String if return is true
+ */
+function print_headline($text, $size=2, $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->heading($text, $size);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints text in a format for use in headings.
+ *
+ * @deprecated
+ * @param string $text The text to be displayed
+ * @param string $deprecated No longer used. (Use to do alignment.)
+ * @param int $size The size to set the font for text display.
+ * @param string $class
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @param string $id The id to use in the element
+ * @return string|void String if return=true nothing otherwise
+ */
+function print_heading($text, $deprecated = '', $size = 2, $class = 'main', $return = false, $id = '') {
+ global $OUTPUT;
+ if (!empty($deprecated)) {
+ debugging('Use of deprecated align attribute of print_heading. ' .
+ 'Please do not specify styling in PHP code like that.', DEBUG_DEVELOPER);
+ }
+ $output = $OUTPUT->heading($text, $size, $class, $id);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Output a standard heading block
+ *
+ * @deprecated
+ * @param string $heading The text to write into the heading
+ * @param string $class An additional Class Attr to use for the heading
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @return string|void HTML String if return=true nothing otherwise
+ */
+function print_heading_block($heading, $class='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->heading($heading, 2, 'headingblock header ' . moodle_renderer_base::prepare_classes($class));
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a message in a standard themed box.
+ * Replaces print_simple_box (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param string $message, the content of the box
+ * @param string $classes, space-separated class names.
+ * @param string $ids
+ * @param boolean $return, return as string or just print it
+ * @return string|void mixed string or void
+ */
+function print_box($message, $classes='generalbox', $ids='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box($message, $classes, $ids);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Starts a box using divs
+ * Replaces print_simple_box_start (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param string $classes, space-separated class names.
+ * @param string $ids
+ * @param boolean $return, return as string or just print it
+ * @return string|void string or void
+ */
+function print_box_start($classes='generalbox', $ids='', $return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box_start($classes, $ids);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Simple function to end a box (see above)
+ * Replaces print_simple_box_end (see deprecatedlib.php)
+ *
+ * @deprecated
+ * @param boolean $return, return as string or just print it
+ * @return string|void Depending on value of return
+ */
+function print_box_end($return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->box_end();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a message in a standard themed container.
+ *
+ * @deprecated
+ * @param string $message, the content of the container
+ * @param boolean $clearfix clear both sides
+ * @param string $classes, space-separated class names.
+ * @param string $idbase
+ * @param boolean $return, return as string or just print it
+ * @return string|void Depending on value of $return
+ */
+function print_container($message, $clearfix=false, $classes='', $idbase='', $return=false) {
+ global $OUTPUT;
+ if ($clearfix) {
+ $classes .= ' clearfix';
+ }
+ $output = $OUTPUT->container($message, $classes, $idbase);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Starts a container using divs
+ *
+ * @deprecated
+ * @param boolean $clearfix clear both sides
+ * @param string $classes, space-separated class names.
+ * @param string $idbase
+ * @param boolean $return, return as string or just print it
+ * @return string|void Based on value of $return
+ */
+function print_container_start($clearfix=false, $classes='', $idbase='', $return=false) {
+ global $OUTPUT;
+ if ($clearfix) {
+ $classes .= ' clearfix';
+ }
+ $output = $OUTPUT->container_start($classes, $idbase);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Simple function to end a container (see above)
+ *
+ * @deprecated
+ * @param boolean $return, return as string or just print it
+ * @return string|void Based on $return
+ */
+function print_container_end($return=false) {
+ global $OUTPUT;
+ $output = $OUTPUT->container_end();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a bold message in an optional color.
+ *
+ * @deprecated use $OUTPUT->notification instead.
+ * @param string $message The message to print out
+ * @param string $style Optional style to display message text in
+ * @param string $align Alignment option
+ * @param bool $return whether to return an output string or echo now
+ * @return string|bool Depending on $result
+ */
+function notify($message, $classes = 'notifyproblem', $align = 'center', $return = false) {
+ global $OUTPUT;
+
+ if ($classes == 'green') {
+ debugging('Use of deprecated class name "green" in notify. Please change to "notifysuccess".', DEBUG_DEVELOPER);
+ $classes = 'notifysuccess'; // Backward compatible with old color system
+ }
+
+ $output = $OUTPUT->notification($message, $classes);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Print a continue button that goes to a particular URL.
+ *
+ * @param string $link The url to create a link to.
+ * @param bool $return If set to true output is returned rather than echoed, default false
+ * @return string|void HTML String if return=true nothing otherwise
+ */
+function print_continue($link, $return = false) {
+ global $CFG, $OUTPUT;
+
+ if ($link == '') {
+ if (!empty($_SERVER['HTTP_REFERER'])) {
+ $link = $_SERVER['HTTP_REFERER'];
+ $link = str_replace('&', '&', $link); // make it valid XHTML
+ } else {
+ $link = $CFG->wwwroot .'/';
+ }
+ }
+
+ $output = $OUTPUT->continue_button($link);
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Returns a string containing a link to the user documentation for the current
+ * page. Also contains an icon by default. Shown to teachers and admin only.
+ *
+ * @global object
+ * @global object
+ * @param string $text The text to be displayed for the link
+ * @param string $iconpath The path to the icon to be displayed
+ * @return string The link to user documentation for this current page
+ */
+function page_doc_link($text='', $iconpath='') {
+ global $CFG, $PAGE;
+
+ if (empty($CFG->docroot) || during_initial_install()) {
+ return '';
+ }
+ if (!has_capability('moodle/site:doclinks', $PAGE->context)) {
+ return '';
+ }
+
+ $path = $PAGE->docspath;
+ if (!$path) {
+ return '';
+ }
+ return doc_link($path, $text, $iconpath);
+}
+
+/**
+ * Print a standard header
+ *
+ * @param string $title Appears at the top of the window
+ * @param string $heading Appears at the top of the page
+ * @param string $navigation Array of $navlinks arrays (keys: name, link, type) for use as breadcrumbs links
+ * @param string $focus Indicates form element to get cursor focus on load eg inputform.password
+ * @param string $meta Meta tags to be added to the header
+ * @param boolean $cache Should this page be cacheable?
+ * @param string $button HTML code for a button (usually for module editing)
+ * @param string $menu HTML code for a popup menu
+ * @param boolean $usexml use XML for this page
+ * @param string $bodytags This text will be included verbatim in the <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=' ', $menu='',
+ $usexml=false, $bodytags='', $return=false) {
+ global $PAGE, $OUTPUT;
+
+ $PAGE->set_title($title);
+ $PAGE->set_heading($heading);
+ $PAGE->set_cacheable($cache);
+ $PAGE->set_focuscontrol($focus);
+ if ($button == '') {
+ $button = ' ';
+ }
+ $PAGE->set_button($button);
+
+ if ($navigation == 'home') {
+ $navigation = '';
+ }
+ if (gettype($navigation) == 'string' && strlen($navigation) != 0 && $navigation != 'home') {
+ debugging("print_header() was sent a string as 3rd ($navigation) parameter. "
+ . "This is deprecated in favour of an array built by build_navigation(). Please upgrade your code.", DEBUG_DEVELOPER);
+ }
+
+ // TODO $navigation
+ // TODO $menu
+
+ if ($meta) {
+ throw new coding_exception('The $meta parameter to print_header is no longer supported. '.
+ 'You should be able to do weverything you want with $PAGE->requires and other such mechanisms.');
+ }
+ if ($usexml) {
+ throw new coding_exception('The $usexml parameter to print_header is no longer supported.');
+ }
+ if ($bodytags) {
+ throw new coding_exception('The $bodytags parameter to print_header is no longer supported.');
+ }
+
+ $output = $OUTPUT->header($navigation, $menu);
+
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+function print_footer($course = NULL, $usercourse = NULL, $return = false) {
+ global $PAGE, $OUTPUT;
+ // TODO check arguments.
+ if (is_string($course)) {
+ debugging("Magic values like 'home', 'empty' passed to print_footer no longer have any effect. " .
+ 'To achieve a similar effect, call $PAGE->set_generaltype before you call print_header.', DEBUG_DEVELOPER);
+ } else if (!empty($course->id) && $course->id != $PAGE->course->id) {
+ throw new coding_exception('The $course object you passed to print_footer does not match $PAGE->course.');
+ }
+ if (!is_null($usercourse)) {
+ debugging('The second parameter ($usercourse) to print_footer is no longer supported. ' .
+ '(I did not think it was being used anywhere.)', DEBUG_DEVELOPER);
+ }
+ $output = $OUTPUT->footer();
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
\ No newline at end of file
$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);
--- /dev/null
+<?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
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
}
/**
- * 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));
+ }
}
/**
*/
+/**
+ * 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.
/** Used to cache renderers as they are created. */
protected $renderers = array();
+ protected $opencontainers;
+
/**
* Constructor.
* @param object $theme the theme we are rendering for.
public function __construct($theme, $page) {
$this->theme = $theme;
$this->page = $page;
+ $this->opencontainers = new xhtml_container_stack();
}
/* Implement the interface method. */
/* 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);
}
}
}
*/
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));
}
}
$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);
}
}
}
// 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);
}
}
*/
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) {
}
protected function output_attribute($name, $value) {
+ $value = trim($value);
if ($value || is_numeric($value)) { // We want 0 to be output.
return ' ' . $name . '="' . $value . '"';
}
}
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;
}
}
* 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;
}
// 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);
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;
}
* @return string the HTML to be output.
*/
protected function process_end($template, $arguments) {
- return $this->containerstack->pop($template);
+ return $this->opencontainers->pop($template);
}
/**
*/
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.
$container = new stdClass;
$container->type = $type;
$container->closehtml = $closehtml;
- array_push($this->opencontainsers, $container);
+ array_push($this->opencontainers, $container);
}
/**
* @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 .
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>)
*/
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;
* debug warning. After calling this method, the instance can no longer be used.
*/
public function discard() {
- $this->opencontainsers = null;
+ $this->opencontainers = null;
}
/**
* 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;
}
}
* @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&ss=1&uri=' . urlencode(qualified_me()) . '">Validate HTML</a></li>
+ <li><a href="http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=-1&url1=' . urlencode(qualified_me()) . '">Section 508 Check</a></li>
+ <li><a href="http://www.contentquality.com/mynewtester/cynthia.exe?rptmode=0&warnp2n3e=1&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() {
}
}
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');
+ }
}
/**
* 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
}
+/**
+ * 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.
*
* @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> </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> </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;
+ }
+}
* @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 =========================================================
protected $_bodyclasses = array();
+ protected $_title = '';
+
+ protected $_heading = '';
+
protected $_pagetype = null;
+ protected $_generaltype = 'normal';
+
protected $_subpage = '';
protected $_docspath = null;
protected $_url = null;
+ protected $_alternateversions = array();
+
protected $_blocks = null;
protected $_requires = null;
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
/// 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
}
/**
- * 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() {
}
/**
- * 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
}
/**
- * 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,
}
/**
- * 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.
}
/**
- * 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.
*/
}
/**
- * 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.
*/
}
/**
- * 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
}
/**
- * 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() {
}
/**
- * 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() {
}
/**
- * 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() {
}
/**
- * 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() {
}
/**
- * 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() {
}
/**
- * 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.)
*/
}
/**
- * 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() {
}
/**
- * 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() {
}
/**
- * 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;
}
/**
$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
}
}
+ /**
+ * $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('"', '"', $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
}
}
+ /**
+ * 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
}
}
+ /**
+ * @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.
$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));
}
/**
*/
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();
}
/**
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
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
$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
$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;
$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;
}
/**
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) {
* 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') {
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() {
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() {
$this->foldertocleanup = $CFG->themedir;
$this->page = new stdClass;
- $this->page->opencontainers = new xhtml_container_stack();
}
public function tearDown() {
$this->foldertocleanup = $CFG->themedir;
$this->page = new stdClass;
- $this->page->opencontainers = new xhtml_container_stack();
}
public function tearDown() {
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();
}
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() {
// 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);
+ }
}
/**
$plugin = ($plugin==='moodle') ? null : $plugin;
- $backtrace = print_backtrace($backtrace, true, true);
+ $backtrace = format_backtrace($backtrace, true);
$version = null;
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
* @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=' ', $menu='',
$usexml=false, $bodytags='', $return=false) {
}
}
-/**
- * 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
* @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')) {
$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
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;
}
$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 .= ' <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&id=1&modid=site_errors">'.get_string('logs').'</a>)';
+ }
+ $loggedinas .= '</div>';
+ }
+ }
+ }
+ }
+
+ return $loggedinas;
}
/**
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
}
}
-/**
- * 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('&', '&', $link); // make it valid XHTML
- } else {
- $link = $CFG->wwwroot .'/';
- }
- }
-
- $options = array();
- $linkparts = parse_url(str_replace('&', '&', $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.
}
}
-/**
- * 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
*
}
}
-/**
- * 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.
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
*
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
*
* @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;
}
/**
/// 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
$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();
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.
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");
$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;
* 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);
$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
$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';
$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';
} 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))
}
$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();
$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
/// 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
+////////////////////////////////////////////////////////////////////////////////
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+<?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