Skip to content

Commit

Permalink
MDL-36048 Allow course formats to add course headers and footers
Browse files Browse the repository at this point in the history
- Added functions in class format_base
- Added global functions in course/lib.php
- Added calling of course header/footer functions to the base theme
- output renderer checks if theme calls the coures content header/footer functions, if not calls them explicitly and displays a development warning
  • Loading branch information
marinaglancy committed Nov 14, 2012
1 parent 3776335 commit 5ef2370
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 31 deletions.
67 changes: 67 additions & 0 deletions course/format/lib.php
Expand Up @@ -793,6 +793,73 @@ public function page_set_course(moodle_page $page) {
*/
public function page_set_cm(moodle_page $page) {
}

/**
* Course-specific information to be output on any course page (usually above navigation bar)
*
* Example of usage:
* define
* class format_FORMATNAME_XXX implements renderable {}
*
* create format renderer in course/format/FORMATNAME/renderer.php, define rendering function:
* class format_FORMATNAME_renderer extends plugin_renderer_base {
* protected function render_format_FORMATNAME_XXX(format_FORMATNAME_XXX $xxx) {
* return html_writer::tag('div', 'This is my header/footer');
* }
* }
*
* Return instance of format_FORMATNAME_XXX in this function, the appropriate method from
* plugin renderer will be called
*
* @return null|renderable null for no output or object with data for plugin renderer
*/
public function course_header() {
return null;
}

/**
* Course-specific information to be output on any course page (usually in the beginning of
* standard footer)
*
* See {@link format_base::course_header()} for usage
*
* @return null|renderable null for no output or object with data for plugin renderer
*/
public function course_footer() {
return null;
}

/**
* Course-specific information to be output immediately above content on any course page
*
* See {@link format_base::course_header()} for usage
*
* @return null|renderable null for no output or object with data for plugin renderer
*/
public function course_content_header() {
return null;
}

/**
* Course-specific information to be output immediately below content on any course page
*
* See {@link format_base::course_header()} for usage
*
* @return null|renderable null for no output or object with data for plugin renderer
*/
public function course_content_footer() {
return null;
}

/**
* Returns instance of page renderer used by this plugin
*
* @param moodle_page $page
* @return renderer_base
*/
public function get_renderer(moodle_page $page) {
return $page->get_renderer('format_'. $this->get_format());
}
}

/**
Expand Down
111 changes: 111 additions & 0 deletions lib/outputrenderers.php
Expand Up @@ -759,6 +759,23 @@ public function header() {
$header = $this->doctype() . $header;
}

// If this theme version is below 2.4 release and this is a course view page
if ((!isset($this->page->theme->settings->version) || $this->page->theme->settings->version < 2012101500) &&
$this->page->pagelayout === 'course' && $this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) {
// check if course content header/footer have not been output during render of theme layout
$coursecontentheader = $this->course_content_header(true);
$coursecontentfooter = $this->course_content_footer(true);
if (!empty($coursecontentheader)) {
// display debug message and add header and footer right above and below main content
// Please note that course header and footer (to be displayed above and below the whole page)
// are not displayed in this case at all.
// Besides the content header and footer are not displayed on any other course page
debugging('The current theme is not optimised for 2.4, the course-specific header and footer defined in course format will not be output', DEBUG_DEVELOPER);
$header .= $coursecontentheader;
$footer = $coursecontentfooter. $footer;
}
}

send_headers($this->contenttype, $this->page->cacheable);

$this->opencontainers->push('header/footer', $footer);
Expand Down Expand Up @@ -845,6 +862,100 @@ public function container_end_all($shouldbenone = false) {
return $this->opencontainers->pop_all_but_last($shouldbenone);
}

/**
* Returns course-specific information to be output immediately above content on any course page
* (for the current course)
*
* @param bool $onlyifnotcalledbefore output content only if it has not been output before
* @return string
*/
public function course_content_header($onlyifnotcalledbefore = false) {
global $CFG;
if ($this->page->course->id == SITEID) {
// return immediately and do not include /course/lib.php if not necessary
return '';
}
static $functioncalled = false;
if ($functioncalled && $onlyifnotcalledbefore) {
// we have already output the content header
return '';
}
require_once($CFG->dirroot.'/course/lib.php');
$functioncalled = true;
$courseformat = course_get_format($this->page->course);
if (($obj = $courseformat->course_content_header()) !== null) {
return $courseformat->get_renderer($this->page)->render($obj);
}
return '';
}

/**
* Returns course-specific information to be output immediately below content on any course page
* (for the current course)
*
* @param bool $onlyifnotcalledbefore output content only if it has not been output before
* @return string
*/
public function course_content_footer($onlyifnotcalledbefore = false) {
global $CFG;
if ($this->page->course->id == SITEID) {
// return immediately and do not include /course/lib.php if not necessary
return '';
}
static $functioncalled = false;
if ($functioncalled && $onlyifnotcalledbefore) {
// we have already output the content footer
return '';
}
$functioncalled = true;
require_once($CFG->dirroot.'/course/lib.php');
$courseformat = course_get_format($this->page->course);
if (($obj = $courseformat->course_content_footer()) !== null) {
return $courseformat->get_renderer($this->page)->render($obj);
}
return '';
}

/**
* Returns course-specific information to be output on any course page in the header area
* (for the current course)
*
* @return string
*/
public function course_header() {
global $CFG;
if ($this->page->course->id == SITEID) {
// return immediately and do not include /course/lib.php if not necessary
return '';
}
require_once($CFG->dirroot.'/course/lib.php');
$courseformat = course_get_format($this->page->course);
if (($obj = $courseformat->course_header()) !== null) {
return $courseformat->get_renderer($this->page)->render($obj);
}
return '';
}

/**
* Returns course-specific information to be output on any course page in the footer area
* (for the current course)
*
* @return string
*/
public function course_footer() {
global $CFG;
if ($this->page->course->id == SITEID) {
// return immediately and do not include /course/lib.php if not necessary
return '';
}
require_once($CFG->dirroot.'/course/lib.php');
$courseformat = course_get_format($this->page->course);
if (($obj = $courseformat->course_footer()) !== null) {
return $courseformat->get_renderer($this->page)->render($obj);
}
return '';
}

/**
* Returns lang menu or '', this method also checks forcing of languages in courses.
*
Expand Down
14 changes: 7 additions & 7 deletions theme/base/config.php
Expand Up @@ -119,39 +119,39 @@
'popup' => array(
'file' => 'general.php',
'regions' => array(),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologininfo'=>true),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologininfo'=>true, 'nocourseheaderfooter'=>true),
),
// No blocks and minimal footer - used for legacy frame layouts only!
'frametop' => array(
'file' => 'general.php',
'regions' => array(),
'options' => array('nofooter'=>true),
'options' => array('nofooter'=>true, 'nocoursefooter'=>true),
),
// Embeded pages, like iframe/object embeded in moodleform - it needs as much space as possible
'embedded' => array(
'file' => 'embedded.php',
'regions' => array(),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
),
// Used during upgrade and install, and for the 'This site is undergoing maintenance' message.
// This must not have any blocks, and it is good idea if it does not have links to
// other places - for example there should not be a home link in the footer...
'maintenance' => array(
'file' => 'general.php',
'regions' => array(),
'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true),
'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
),
// Should display the content and basic headers only.
'print' => array(
'file' => 'general.php',
'regions' => array(),
'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>false, 'nocustommenu'=>true),
'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>false, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
),
// The pagelayout used when a redirection is occuring.
'redirect' => array(
'file' => 'embedded.php',
'regions' => array(),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
),
// The pagelayout used for reports.
'report' => array(
Expand All @@ -164,7 +164,7 @@
'file' => 'general.php',
'regions' => array('side-pre', 'side-post'),
'defaultregion' => 'side-pre',
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologinlinks'=>true),
'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologinlinks'=>true, 'nocourseheaderfooter'=>true),
),
);

Expand Down
20 changes: 19 additions & 1 deletion theme/base/layout/general.php
Expand Up @@ -13,6 +13,16 @@
$custommenu = $OUTPUT->custom_menu();
$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));

$courseheader = $coursecontentheader = $coursecontentfooter = $coursefooter = '';
if (empty($PAGE->layout_options['nocourseheaderfooter'])) {
$courseheader = $OUTPUT->course_header();
$coursecontentheader = $OUTPUT->course_content_header();
if (empty($PAGE->layout_options['nocoursefooter'])) {
$coursecontentfooter = $OUTPUT->course_content_footer();
$coursefooter = $OUTPUT->course_footer();
}
}

$bodyclasses = array();
if ($showsidepre && !$showsidepost) {
if (!right_to_left()) {
Expand Down Expand Up @@ -43,7 +53,7 @@
<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses.' '.join(' ', $bodyclasses)) ?>">
<?php echo $OUTPUT->standard_top_of_body_html() ?>
<div id="page">
<?php if ($hasheading || $hasnavbar) { ?>
<?php if ($hasheading || $hasnavbar || !empty($courseheader)) { ?>
<div id="page-header">
<?php if ($hasheading) { ?>
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
Expand All @@ -56,6 +66,9 @@
}
echo $PAGE->headingmenu
?></div><?php } ?>
<?php if (!empty($courseheader)) { ?>
<div id="course-header"><?php echo $courseheader; ?></div>
<?php } ?>
<?php if ($hascustommenu) { ?>
<div id="custommenu"><?php echo $custommenu; ?></div>
<?php } ?>
Expand All @@ -76,7 +89,9 @@
<div id="region-main-wrap">
<div id="region-main">
<div class="region-content">
<?php echo $coursecontentheader; ?>
<?php echo $OUTPUT->main_content() ?>
<?php echo $coursecontentfooter; ?>
</div>
</div>
</div>
Expand Down Expand Up @@ -113,6 +128,9 @@
</div>

<!-- START OF FOOTER -->
<?php if (!empty($coursefooter)) { ?>
<div id="course-footer"><?php echo $coursefooter; ?></div>
<?php } ?>
<?php if ($hasfooter) { ?>
<div id="page-footer" class="clearfix">
<p class="helplink"><?php echo page_doc_link(get_string('moodledocslink')) ?></p>
Expand Down
21 changes: 19 additions & 2 deletions theme/base/layout/report.php
Expand Up @@ -18,6 +18,15 @@
if ($hascustommenu) {
$bodyclasses[] = 'has_custom_menu';
}
$courseheader = $coursecontentheader = $coursecontentfooter = $coursefooter = '';
if (empty($PAGE->layout_options['nocourseheaderfooter'])) {
$courseheader = $OUTPUT->course_header();
$coursecontentheader = $OUTPUT->course_content_header();
if (empty($PAGE->layout_options['nocoursefooter'])) {
$coursecontentfooter = $OUTPUT->course_content_footer();
$coursefooter = $OUTPUT->course_footer();
}
}

echo $OUTPUT->doctype() ?>
<html <?php echo $OUTPUT->htmlattributes() ?>>
Expand All @@ -29,7 +38,7 @@
<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses.' '.join(' ', $bodyclasses)) ?>">
<?php echo $OUTPUT->standard_top_of_body_html() ?>
<div id="page">
<?php if ($hasheading || $hasnavbar) { ?>
<?php if ($hasheading || $hasnavbar || !empty($courseheader)) { ?>
<div id="page-header">
<?php if ($hasheading) { ?>
<h1 class="headermain"><?php echo $PAGE->heading ?></h1>
Expand All @@ -42,6 +51,9 @@
}
echo $PAGE->headingmenu
?></div><?php } ?>
<?php if (!empty($courseheader)) { ?>
<div id="course-header"><?php echo $courseheader; ?></div>
<?php } ?>
<?php if ($hascustommenu) { ?>
<div id="custommenu"><?php echo $custommenu; ?></div>
<?php } ?>
Expand All @@ -58,7 +70,9 @@
<div id="page-content" class="clearfix">
<div id="report-main-content">
<div class="region-content">
<?php echo $coursecontentheader; ?>
<?php echo $OUTPUT->main_content() ?>
<?php echo $coursecontentfooter; ?>
</div>
</div>
<?php if ($hassidepre) { ?>
Expand All @@ -73,6 +87,9 @@
</div>

<!-- START OF FOOTER -->
<?php if (!empty($coursefooter)) { ?>
<div id="course-footer"><?php echo $coursefooter; ?></div>
<?php } ?>
<?php if ($hasfooter) { ?>
<div id="page-footer" class="clearfix">
<p class="helplink"><?php echo page_doc_link(get_string('moodledocslink')) ?></p>
Expand All @@ -87,4 +104,4 @@
</div>
<?php echo $OUTPUT->standard_end_of_body_html() ?>
</body>
</html>
</html>
3 changes: 3 additions & 0 deletions theme/base/style/core.css
Expand Up @@ -154,6 +154,7 @@ a.skip:active {position: static;display: block;}
*/
.headermain {float:left;margin:15px;font-size:2.3em;}
.headermenu {float:right;margin:10px;font-size:0.8em;text-align:right;}
#course-header {clear:both;}

/**
* Navbar
Expand Down Expand Up @@ -189,6 +190,8 @@ a.skip:active {position: static;display: block;}
.performanceinfo .cachesused .cache-store-stats {text-indent: 1em;}
.performanceinfo .cachesused .cache-total-stats {font-weight:bold;margin-top:0.3em;}

#course-footer {clear:both;}

/**
* Tabs
*/
Expand Down

0 comments on commit 5ef2370

Please sign in to comment.