/// first old *.php update and then the new upgrade.php script
upgrade_plugins('enrol', 'enrol', "$CFG->wwwroot/$CFG->admin/index.php"); // Return here afterwards
+/// Check all course formats and upgrade if necessary
+ upgrade_plugins('format','course/format',"$CFG->wwwroot/$CFG->admin/index.php");
+
/// Check for local database customisations
/// first old *.php update and then the new upgrade.php script
require_once("$CFG->dirroot/lib/locallib.php");
}
}
+ //Backup course format data, if any.
+ echo '<li>'.get_string("courseformatdata").'</li>';
+ if($status) {
+ if (!$status = backup_format_data($backup_file,$preferences)) {
+ notify("An error occurred while backing up the course format data");
+ }
+ }
+
//Prints course end
if ($status) {
if (!$status = backup_course_end($backup_file,$preferences)) {
}
+ //Prints course's format data (any data the format might want to save).
+ function backup_format_data ($bf,$preferences) {
+ global $CFG;
+
+ // Check course format
+ if(!($format=get_field('course','format','id',$preferences->backup_course))) {
+ return false;
+ }
+ // Write appropriate tag. Note that we always put this tag there even if
+ // blank, it makes parsing easier
+ fwrite ($bf,start_tag("FORMATDATA",2,true));
+
+ $file=$CFG->dirroot."/course/format/$format/backuplib.php";
+ if(file_exists($file)) {
+ // If the file is there, the function must be or it's an error.
+ require_once($file);
+ $function=$format.'_backup_format_data';
+ if(!function_exists($function)) {
+ return false;
+ }
+ if(!$function($bf,$preferences)) {
+ return false;
+ }
+ }
+
+ // This last return just checks the file writing has been ok (ish)
+ return fwrite ($bf,end_tag("FORMATDATA",2,true));
+ }
+
//Prints course's modules info (table course_modules)
//Only for selected mods in preferences
function backup_course_modules ($bf,$preferences,$section) {
return $info;
}
+ //This function read the xml file and store its data from the course format in an object
+ function restore_read_xml_formatdata ($xml_file) {
+
+ //We call the main read_xml function, with todo = FORMATDATA
+ $info = restore_read_xml ($xml_file,'FORMATDATA',false);
+
+ return $info;
+ }
+
//This function read the xml file and store its data from the metacourse in a object
function restore_read_xml_metacourse ($xml_file) {
return $status;
}
+ //Called to set up any course-format specific data that may be in the file
+ function restore_set_format_data($restore,$xml_file) {
+ global $CFG,$db;
+
+ $status = true;
+ //Check it exists
+ if (!file_exists($xml_file)) {
+ return false;
+ }
+ //Load data from XML to info
+ if(!($info = restore_read_xml_formatdata($xml_file))) {
+ return false;
+ }
+
+ //Process format data if there is any
+ if (isset($info->format_data)) {
+ if(!$format=get_field('course','format','id',$restore->course_id)) {
+ return false;
+ }
+ // If there was any data then it must have a restore method
+ $file=$CFG->dirroot."/course/format/$format/restorelib.php";
+ if(!file_exists($file)) {
+ return false;
+ }
+ require_once($file);
+ $function=$format.'_restore_format_data';
+ if(!function_exists($function)) {
+ return false;
+ }
+ return $function($restore,$info->format_data);
+ }
+
+ // If we got here then there's no data, but that's cool
+ return true;
+ }
+
//This function creates all the metacourse data from xml, notifying
//about each incidence
function restore_create_metacourse($restore,$xml_file) {
// echo $this->level.str_repeat(" ",$this->level*2)."<".$tagName."><br />\n"; //Debug
}
+ //This is the startTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
+ function startElementFormatData($parser, $tagName, $attrs) {
+ //Refresh properties
+ $this->level++;
+ $this->tree[$this->level] = $tagName;
+
+ //Output something to avoid browser timeouts...
+ backup_flush();
+
+ //Accumulate all the data inside this tag
+ if (isset($this->tree[3]) && $this->tree[3] == "FORMATDATA") {
+ if (!isset($this->temp)) {
+ $this->temp = '';
+ }
+ $this->temp .= "<".$tagName.">";
+ }
+
+ //Check if we are into FORMATDATA zone
+ //if ($this->tree[3] == "FORMATDATA") //Debug
+ // echo $this->level.str_repeat(" ",$this->level*2)."<".$tagName."><br />\n"; //Debug
+ }
+
//This is the startTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
function startElementMetacourse($parser, $tagName, $attrs) {
}
+ //This is the endTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
+ function endElementFormatData($parser, $tagName) {
+ //Check if we are into FORMATDATA zone
+ if ($this->tree[3] == 'FORMATDATA') {
+ if (!isset($this->temp)) {
+ $this->temp = '';
+ }
+ $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
+ }
+
+ if($tagName=='FORMATDATA') {
+ //Did we have any data? If not don't bother
+ if($this->temp!='<FORMATDATA></FORMATDATA>') {
+ //Prepend XML standard header to info gathered
+ $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
+ $this->temp='';
+
+ //Call to xmlize for this portion of xml data (the FORMATDATA block)
+ $this->info->format_data = xmlize($xml_data,0);
+ }
+ //Stop parsing at end of FORMATDATA
+ $this->finished=true;
+ }
+
+ //Clear things
+ $this->tree[$this->level] = "";
+ $this->level--;
+ $this->content = "";
+ }
+
//This is the endTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
function endElementMetacourse($parser, $tagName) {
//Check if we are into METACOURSE zone
} else if ($todo == "SECTIONS") {
//Define handlers to that zone
xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
+ } else if ($todo == 'FORMATDATA') {
+ //Define handlers to that zone
+ xml_set_element_handler($xml_parser, "startElementFormatData", "endElementFormatData");
} else if ($todo == "METACOURSE") {
//Define handlers to that zone
xml_set_element_handler($xml_parser, "startElementMetacourse", "endElementMetacourse");
}
}
+ if($status) {
+ //If we are deleting and bringing into a course or making a new course, same situation
+ if($restore->restoreto == 0 || $restore->restoreto == 2) {
+ if (!defined('RESTORE_SILENTLY')) {
+ echo '<li>'.get_string('courseformatdata').'</li>';
+ }
+ if (!$status = restore_set_format_data($restore, $xml_file)) {
+ $error = "Error while setting the course format data";
+ if (!defined('RESTORE_SILENTLY')) {
+ notify($error);
+ } else {
+ $errorstr=$error;
+ return false;
+ }
+ }
+ }
+ }
+
//Now create log entries as needed
if ($status and ($restore->logs)) {
if (!defined('RESTORE_SILENTLY')) {
$courseformats = get_list_of_plugins('course/format');
$formcourseformats = array();
foreach ($courseformats as $courseformat) {
- $formcourseformats["$courseformat"] = get_string("format$courseformat");
+ $formcourseformats["$courseformat"] = get_string("format$courseformat","format_$courseformat");
+ if($formcourseformats["$courseformat"]=="[[format$courseformat]]") {
+ $formcourseformats["$courseformat"] = get_string("format$courseformat");
+ }
}
$mform->addElement('select', 'format', get_string('format'), $formcourseformats);
$mform->setHelpButton('format', array('courseformats', get_string('courseformats')), true);
Course formats
+==============
+
+To create a new course format, make another folder in here.
+
+If you want a basic format, you only need to write the 'standard files' listed
+below.
+
+If you want to store information in the database for your format, or control
+access to features of your format, you need some of the optional files too.
+
+All names below assume that your format is called 'yourformat'.
+
+
+Standard files
--------------
-To add a new course format, just duplicate one of the
-existing folders in here with a new name (eg coollayout).
-Then edit lang/en/moodle and add a new string like:
+* yourformat/format.php
+
+ Code that actually displays the course view page. See existing formats for
+ examples.
+
+* yourformat/config.php
+
+ Configuration file, mainly controlling default blocks for the format.
+ See existing formats for examples.
+
+* yourformat/lang/en_utf8/format_yourformat.php
+
+ Language file containing basic language strings for your format. Here
+ is a minimal language file:
+
+<?php
+$string['formatyourformat']='Your format'; // Name to display for format
+$string['nameyourformat']='section'; // Name of a section within your format
+?>
+
+ The first string is used in the dropdown menu of course settings. The second
+ is used when editing an activity within a course of your format.
+
+ Note that existing formats store their language strings in the main
+ moodle.php, which you can also do, but this separate file is recommended
+ for contributed formats.
+
+ You can also store other strings in this file if you wish. They can be
+ accessed as follows, for example to get the section name:
+
+ get_string('nameyourformat','format_yourformat');
+
+ Of course you can have other folders as well as just English if you want
+ to provide multiple languages.
+
+
+Optional files (database access)
+--------------------------------
+
+If these files exist, Moodle will use them to set up database tables when you
+visit the admin page.
+
+* yourformat/db/install.xml
+
+ Database table definitions. Use your format name at the start of the table
+ names to increase the chance that they are unique.
+
+* yourformat/db/upgrade.php
+
+ Database upgrade instructions. Similar to other upgrade.php files, so look
+ at those for modules etc. if you want to see.
+
+ The function must look like:
+
+ function xmldb_format_yourformat_upgrade($oldversion=0) {
+ ...
+
+* yourformat/version.php
+
+ Required if you use database tables.
+
+ <?php
+ $plugin->version = 2006120100; // Plugin version (update when tables change)
+ $plugin->requires = 2006092801; // Required Moodle version
+ ?>
+
+
+Optional files (backup)
+-----------------------
+
+If these files exist, backup and restore run automatically when backing up
+the course. You can't back up the course format data independently.
+
+* yourformat/backuplib.php
+
+ Similar to backup code for other plugins. Must have a function:
+
+ function yourformat_backup_format_data($bf,$preferences) {
+ ...
+
+* yourformat/restorelib.php
+
+ Similar to restore code for other plugins. Must have a function:
+
+ function yourformat_restore_format_data($restore,$data) {
+ ...
+
+ ($data is the xmlized data underneath FORMATDATA in the backup XML file.
+ Do print_object($data); while testing to see how it looks.)
+
+
+Optional file (capabilities)
+----------------------------
+
+If this file exists, Moodle refreshes your format's capabilities
+(checks that they are all included in the database) whenever you increase
+the version in yourformat/version.php.
+
+* yourformat/db/access.php
+
+ Contains capability entries similar to other access.php files.
+
+ The array definition must look like:
+
+ $format_yourformat_capabilities = array(
+ ...
+
+ Format names must look like:
+
+ format/yourformat:specialpower
+
+ Capability definitions in your language file must look like:
+
+ $string['yourformat:specialpower']='Revolutionise the world';
+
+
+
+Optional file (styles)
+----------------------
-$string['formatcoollayout'] = 'Cool Layout';
+* yourformat/styles.php
+ If this file exists it will be included in the CSS Moodle generates.
return true;
}
+/**
+ * @param string $format Course format ID e.g. 'weeks'
+ * @return Name that the course format prefers for sections
+ */
+function get_section_name($format) {
+ $sectionname = get_string("name$format","format_$format");
+ if($sectionname == "[[name$format]]") {
+ $sectionname = get_string("name$format");
+ }
+ return $sectionname;
+}
+
?>
$form->mode = "update";
$form->sesskey = !empty($USER->id) ? $USER->sesskey : '';
- $sectionname = get_string("name$course->format");
+ $sectionname = get_section_name($course->format);
$fullmodulename = get_string("modulename", $module->name);
if ($form->section && $course->format != 'site') {
$form->type = $type;
}
- $sectionname = get_string("name$course->format");
+ $sectionname = get_section_name($course->format);
$fullmodulename = get_string("modulename", $module->name);
if ($form->section && $course->format != 'site') {
$form->return = $return;
$form->update = $update;
- $sectionname = get_string("name$course->format");
+ $sectionname = get_section_name($course->format);
$fullmodulename = get_string("modulename", $module->name);
if ($form->section && $course->format != 'site') {
$string['coursecreators'] = 'Course creator';
$string['coursecreatorsdescription'] = 'Course creators can create new courses and teach in them.';
$string['coursefiles'] = 'Course files';
+$string['courseformatdata'] = 'Course format data';
$string['courseformats'] = 'Course formats';
$string['coursegrades'] = 'Course grades';
$string['coursehidden'] = 'This course is currently unavailable to students';
$defpath = $CFG->dirroot.'/'.$compparts[0].
's/'.$compparts[1].'/db/access.php';
$varprefix = $compparts[0].'_'.$compparts[1];
+ } else if ($compparts[0] == 'format') {
+ // Similar to the above, course formats are 'format' while they
+ // are stored in 'course/format'.
+ $defpath = $CFG->dirroot.'/course/'.$component.'/db/access.php';
+ $varprefix = $compparts[0].'_'.$compparts[1];
} else {
$defpath = $CFG->dirroot.'/'.$component.'/db/access.php';
$varprefix = str_replace('/', '_', $component);
case 'enrol':
$string = get_string($stringname, 'enrol_'.$componentname);
break;
+
+ case 'format':
+ $string = get_string($stringname, 'format_'.$componentname);
+ break;
default:
$string = get_string($stringname);
if ($status) {
// OK so far, now update the plugins record
set_config($pluginversion, $plugin->version);
- if (!update_capabilities($dir.'/'.$plug)) {
+ if (!update_capabilities($type.'/'.$plug)) {
error('Could not set up the capabilities for '.$module->name.'!');
}
notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
// OK so far, now update the plugins record
set_config($pluginversion, $plugin->version);
- if (!update_capabilities($dir.'/'.$plug)) {
+ if (!update_capabilities($type.'/'.$plug)) {
error('Could not update '.$plugin->name.' capabilities!');
}
notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
} else if (strpos($module, 'report_') === 0) { // It's a report lang file
$locations[] = $CFG->dirroot .'/'.$CFG->admin.'/report/'.substr($module, 7).'/lang/';
$locations[] = $CFG->dirroot .'/course/report/'.substr($module, 7).'/lang/';
+ } else if (strpos($module, 'format_') === 0) { // Course format
+ $locations[] = $CFG->dirroot .'/course/format/'.substr($module,7).'/lang/';
} else { // It's a normal activity
$locations[] = $CFG->dirroot .'/mod/'.$module.'/lang/';
}
}
}
+ if (!isset($THEME->courseformatsheets) || $THEME->courseformatsheets) { // Search for styles.php in course formats
+ if ($mods = get_list_of_plugins('format','',$CFG->dirroot.'/course')) {
+ foreach ($mods as $mod) {
+ if (file_exists($CFG->dirroot.'/course/format/'.$mod.'/styles.php')) {
+ $files[] = array($CFG->dirroot, '/course/format/'.$mod.'/styles.php');
+ }
+ }
+ }
+ }
+
if (!empty($THEME->langsheets)) { // Search for styles.php within the current language
if (file_exists($CFG->dirroot.'/lang/'.$lang.'/styles.php')) {
$files[] = array($CFG->dirroot, '/lang/'.$lang.'/styles.php');
/// different styles.
+$THEME->courseformatsheets = true;
+
+/// When this is enabled, this theme will search for files
+/// named "styles.php" inside all course formats and
+/// include them. This allows course formats to provide
+/// their own default styles.
+
+
$THEME->navmenuwidth = 50;
/// You can use this to control the cutoff point for strings