Course formats
Important:
This content of this page has been updated and migrated to the new Moodle Developer Resources. The information contained on the page should no longer be seen up-to-date. Why not view this page on the new site and help us to migrate more content to the new site! |
Course formats are plugins that determine the layout of course resources.
Course formats determine how the course main page looks like (/course/view.php) in both view and editing mode. They are also responsible for building navigation tree inside the course (displayed to user in navigation block and breadcrumb). They can organise the course content in sections. Course creator or teacher can specify course format for the course in course edit form.
Moodle 2.4 and above: Course formats also can add its own options fields to the course edit form. They can add course-dependent content to header/footer of any page inside the course, not only /course/view.php
Components
course/format/FORMATNAME/lang/en/format_FORMATNAME.php
Contains the English language strings used in the format. You can also define strings for other languages.
course/format/FORMATNAME/config.php (deprecated since 2.4)
Contains $format['defaultblocks'] which defines the default blocks loaded with the format.
course/format/FORMATNAME/format.php
This is is the layout itself. It is included in course/view.php.
course/format/FORMATNAME/lib.php
The main library of the format. In Moodle versions up to 2.3 it should contain implementations of course format callbacks. In versions 2.4 and above it should contain a class format_FORMATNAME extending format_base. Also it may contain callbacks for other core and contributed APIs if necessary
course/format/FORMATNAME/styles.css, styles_THEMENAME.css
Optional stylesheet. Note that this file is included on all pages on the site, even in the courses that use other formats. In 2.4+ the class format-FORMATNAME is automatically added to body for all pages inside the course, it is recommended to prefix all directives in your styles.css with body.format-FORMATNAME
File styles.css will be included always, styles_THEMENAME.css only if theme_THEMENAME is used for the site (or for the course).
course/format/FORMATNAME/settings.php (version 2.4 and above)
Optional plugin administrative settings. See "Individual settings" in Admin settings
course/format/FORMATNAME/renderer.php
Optional but very recommended file containing renderer for this course format. This file will contain class format_FORMATNAME_renderer extends plugin_renderer_base. See Output renderers
Since course format is all about the display it is very important to separate HTML and PHP. All HTML code should be in your format_FORMATNAME_renderer class in renderer.php. Ideally format.php will only call one function from renderer. Use of renderer is required if you want to output content header and footer.
course/format/FORMATNAME/version.php
Version definitions, see version.php. It is highly recommended always to have it and it is required if you have any files in db folder
course/format/db/install.xml, course/format/db/install.php, course/format/db/upgrade.php
Definitions of tables used by this plugin and upgrade script, see Upgrade API
course/format/backup/
Implementation of backup and restore for additional tables defined in your plugin. See Backup API. This is only needed if you define additional tables in your db folder. Data from table course_format_options is backed up for your plugin automatically
course/format/db/access.php
Capabilities introduced by this plugin, see Access API. Please note that if you define new capabilities inside course format they should not affect accessibility of course modules because other components (for example reports and/or gradebook) will not know about them
Javascript and YUI files
Also course format may contain Javascript files and/or YUI modules. See Category:Javascript for documentation. Make sure that course format checks course_ajax_enabled() before including AJAX libraries
Creating a New Format
The easiest way to create a new course format is to copy an existing one.
1. Copy the folder containing the format files.
2. Rename the folder to the new name. Course format names cannot exceed 21 characters. (In Moodle 2.3 and below the limit is 10 characters)
3. Rename language files in course/format/FORMATNAME/lang/
4. Change $string['pluginname'] in course/format/FORMATNAME/lang/en/format_FORMATNAME.php to the new name.
5. Moodle 2.3 and below: Rename callback functions in lib.php. The names of the functions is formed as callback_FORMATNAME_CALLBACKNAME()
Moodle 2.4 and above: Rename class name in lib.php to format_FORMATNAME.
6. Search and replace other occurences of the old format name, for example in renderer, capabilities names, settings, javascript libraries, etc.
7. The new format is ready for modification.
8. After modifying the code, check it with the 'Code checker [1]'.
Upgrading format to the next Moodle version
Read the files course/format/upgrade.txt, lib/upgrade.txt and also upgrade.txt of the core APIs that you use in your course format plugin and make changes according to them. When testing don't forget to enable Developer debugging level and error display (Settings->Developer->Debugging)
If you upgrade your course format plugin from Moodle 2.3 to Moodle 2.4 - copy class format_legacy to your lib.php and rename it to format_FORMATNAME. Then go through the class functions and replace calling of functions with the corresponding callbacks' code. Move blocks list from config.php to the function format_FORMATNAME::get_default_blocks()
Developing course formats for Moodle 2.4 and above
File lib.php in your course format will contain class format_FORMATNAME extends format_base. The parent class is located in course/format/lib.php and has detailed PHPdocs for each functions that you can override. Some functions are defined as final and you can not override them. Some functions such as get_course(), get_format_options(), update_format_options() and get_renderer() usually do not need to be overriden unless you know exactly what you are doing.
Here are the main features in course formats and responsible for them format_base functions
Course sections
There is existing functionality in Moodle core to support organising course modules into sections. Course format plugins do not have to use them but the most of them do. Database table {course_sections} stores basic information about sections. Also sections info is cached and returned by get_fast_modinfo() so every action changing the sections must be followed by rebuild_course_cache(). Course module must always belong to the section. Even if your course format does not use sections, the section with number 0 is always created.
You must define $string['sectionname'] if your language file even if format does not use sections because it can be called unconditionally from other parts of the code, even though it won't be displayed.
format_base method in 2.4+ | description | Moodle 2.3- callback |
---|---|---|
uses_sections() | returns true or false if the format uses sections or not. There is a global function course_format_uses_sections() that invokes it. It affects default navigation tree building. Various modules and reports may call this function to know whether to display section name for the particular module or not. | callback_FORMATNAME_uses_sections() |
get_section_name() | Returns the name for particular section. This function may be called often so it should use only fields cached in section_info object (field course_sections.name is always cached)
In 3.0+, it checks if the $string['sectionname'] is available in the lang file. If the section name string is not available, it returns an empty string. |
callback_FORMATNAME_get_section_name(). |
get_view_url() | Returns the URL for particular section, it can be either anchor on course view page or separate page. See parent function PHPdocs for more details | 2.3 only: callback_FORMATNAME_get_section_url(). Prior to Moodle 2.3 sections could not have separate URLs |
is_section_current() | Specifies if the section is current, for example current week or highlighted topic. This function is only used if your renderer uses it for example if your renderer extends format_section_renderer_base. This function is not called from anywhere else in Moodle core. | format_section_renderer_base::is_section_current() |
format_base method in 3.0+ | description |
---|---|
get_default_section_name() | This method gets the default section name if the user has not provided a value for the section name. In format_base, it basically calls get_section_name(), which returns the $string['sectionname'] + the section number of the current section, if available, or blank, otherwise. It can be used in conjunction with your course format's get_section_name() implementation. For reference, please refer to the implementations in format_topics and format_weeks classes. |
AJAX support in course format
There are features in core that course format may use or ban, for example modchooser (activity chooser), inline edit of module title, drag and drop of sections, activities and blocks on the page, drag and drop files to the course page to create activities.
There is also a global setting $CFG->enableajax that admin can disable via config.php or in Settings block that will disable AJAX even if course format allows it.
If you have additional AJAX functionality in course format plugin, you must check course_ajax_enabled() before including it.
format_base method in 2.4+ | description | Moodle 2.3- |
---|---|---|
supports_ajax() | returns the minimum versions for browsers that support AJAX. Usually it is enough to copy the function code from format_topics | callback_FORMATNAME_ajax_support() |
ajax_section_move() | code executed after sections were rearranged using drag and drop. See example in format_topics where sections have automatic names depending on their sequence number | callback_FORMATNAME_ajax_section_move() |
Default blocks
Course format can specify which blocks should be added to the course page when course is created in this format.
If course format is changed during course edit, blocks are not changed.
Whatever course format specifies in the method, site admin can override it with $CFG->defaultblocks_override or $CFG->defaultblocks_FORMATNAME
format_base method in 2.4+ | description | Moodle 2.3- |
---|---|---|
get_default_blocks() | see PHPdocs in format_base class | file config.php with $format['defaultblocks'] in it |
Moodle 3.2
Supporting the automatic creation of the Announcements forum
Prior to Moodle 3.2, course formats need to define 'news_items' in the get_default_blocks() method in order for the Announcements forum to be automatically created upon course creation, or when editing a course and changing its course format. Since the use of blocks is being minimised in 3.2, relying on get_default_blocks() in order to determine whether the Announcements forum will be automatically created or not is no longer recommended.
From 3.2 onwards, it is recommended for course format plugin developers to override format_base::supports_news() to return true to indicate that the course format supports the creation of the Announcements forum.
See the following snippet for a course format that supports the automatic creation of the Announcements forum:
class format_awesome extends format_base {
...
/**
* Indicates whether the course format supports the creation of a news forum.
*
* @return bool
*/
public function supports_news() {
return true;
}
}
It's that simple!
If the course format's supports_news() method returns true, the News items to show select field will be shown on the Edit course settings page. Course creators must select a non-zero value for this field in order for the Announcements forum to be automatically created.
Node for the course will be created in navigationlib for you and all standard available branches like 'Participants' or 'Reports' will be added to it. After that course format can add nodes for sections and modules. There is a default implementation that adds branches for course sections and modules under them. Or if course format does not use sections, all modules will just be placed under course mode. Course format is able to override the default navigation tree building.
Note that if navigationlib can not find the node for the current course module, the node will be added automatically (after this callback).
The breadcrumb that appears on the top of the page also reads navigation tree.
You can see examples of overriding course navigation in format_singleactivity and format_flexsections. In Single activity we pretend that course node is the activity node and in Flexible sections the sections are added to the navigation tree hierarchically.
format_base method in 2.4+ | description | Moodle 2.3- |
---|---|---|
extend_course_navigation() | See PHPdocs in format_base class. This function is called when navigation tree is built on the page and also when user expands non-active node in navigation via AJAX request. Only the node with active section should be expanded, do not add children nodes to not expanded nodes (for example do not add nodes for modules in collapsed sections) | callback_FORMATNAME_display_content(), callback_FORMATNAME_load_content() |
Course format options
The core table {course_format_options} in Moodle database is designed to store additional options for course formats. This may be options for the whole course or options for course section.
Course format options must not have the same names as fields in database table {course}, section options must not have the same names as fields in {course_sections}. Also make sure names do not duplicate completion and conditional fields in edit forms.
Some facts about course format options in core classes:
- Core formats format_weeks and format_topics have options: numsections, hiddensections, coursedisplay. They are also defined as default in class format_legacy because prior to 2.4 they were fields in {course} table and were part of course edit form.
- Class format_base by default does not define any options.
- Core formats format_social and format_scorm do not have have any options.
- Neither core course format uses additional section options. Flexible sections format has a section option "display collapsed/expanded" and it is also defined as cached because it affects often-called function get_view_url()
When teacher changes the course format in the course edit form AND the old and the new course formats share the same option name, the value of this option is copied from one format to another. For example, if course had format Topics and had 8 sections in it and teacher changes format to weeks, the course will have 8 weeks in it.
During backup the course format options are stored as if they were additional fields in {course} table. Therefore courses in topics and weeks formats that were backed up in Moodle 2.3 will be restored in 2.4 without data loss even though the values of numsections, hiddensections and coursedisplay will be stored in another table. Do not store IDs of elements (courses, sections, etc.) in course format options because they will not be backed up and restored properly. You can use section numbers because they are relative inside the course. If absolute ids are necessary you can create your own backup/restore scripts, see Backup API.
Webservices expect course format options to be passed in additional entity but for backward compartibility numsections, hiddensections and coursedisplay can also be passed as if they were fields in {course} table.
format_base method in 2.4+ | Description |
---|---|
get_course() | (no need to override) returns object with all fields from db table {course} AND all course format options |
get_section() | (no need to override) returns instance of section_info. It will contain all fields from table {course_sections} AND all course format options for this section |
course_format_options() | By overriding this method course format specifies which additional options it has for course |
section_format_options() | By overriding this method course format specifies which additional options it has for course section. Note that since section information is cached you may want to cache some additional options as well. See PHPdocs for more information |
get_format_options() | (usually no need to override) low level function to retrieve course format options values. It is more convenient to use methods get_course() and get_section() |
create_edit_form_elements() | This function is called to alter course edit form and standard section edit form. The default implementation creates simple form elements for each option defined in either course_format_options() or section_format_options(). Overwrite it if you want to have more comprehensive form elements or if you do not want options to appear in edit forms, etc. |
edit_form_validation() | Overwrite if course format plugin needs additional validation for it's option in course edit form |
update_format_options() | (usually no need to override) low level function to insert/update records in db table {course_format_options} |
update_course_format_options() | updates course format options with the data from the edit course form. Plugin can override for example to include calculated options fields, especially when course format is being changed. For example format_topics and format_weeks automatically fill field numsections when user switches from other format |
update_section_format_options() | updates course format options for the section with the data from edit section form |
editsection_form() | Return an instance of moodleform to edit a specified section. Default implementation returns instance of editsection_form that automatically adds additional fields defined in section_format_options() |
get_default_course_enddate() | Overwrite if the course format is time-based. The base class calculates the default course end date based on the number of sections. |
Executing code before output
It is often needed to execute some code before output started. You may want to
- redirect from one page to another. Examples are format_scorm format_singleactivity that don't have course view page and redirect /course/view.php to module view page
- perform an action that results in changes in navigation tree or other output. Example is when /course/view.php has a parameter in query that tells to change section visibility
- include additional JS or CSS files in the page head rather than body
File format.php is included after the output is started and the above cases can not be solved inside it.
Every module or page inside a course must call require_login() or $PAGE->set_cm() or $PAGE->set_course(). As soon as page knows the current module and/or course, the callbacks from current course format are invoked.
format_base method in 2.4+ | description |
---|---|
page_set_cm() | Override if you want to execute some code when course module is set for the page |
page_set_course() | Override if you want to execute some code when course is set for the page. This function is always invoked on any course page |
Course format may add content header and footer to any page inside the course (including modules pages). They will be displayed right above or below the page main content, right or left from side blocks. Also course formats may add course header and footer. They will be displayed above or below both content and blocks. Typical usages may be:
- course navigation (prev/next/back)
- course custom menu
- disclaimer information or other text in the bottom of each course page
- etc
This is a new feature in Moodle 2.4, you have to make sure that if the site uses the custom theme, it supports it. Refer to theme/upgrade.txt. Also theme may specify that some pagelayouts (report, print, etc) do NOT display the course header/footer.
Using this functionality REQUIRES use of renderers. Example of using the course headers/footers you can find in tracker issue MDL-36048
format_base method in 2.4+ | description |
---|---|
course_content_header() | Returns content to be displayed immediately above the page content in the main area (between side blocks) |
course_content_footer() | Returns content to be displayed immediately below the page content in the main area (between side blocks) |
course_header() | Returns content to be displayed above all content, usually below heading and above breadcrumb but it depends on the theme |
course_footer() | Returns content to be displayed below content and blocks, usually above the page footer, exact poisition depends on the theme |
Handling events
As any other plugin types course formats can listen to system events. See Events API. Examples of events that format may listen to:
- course_created - when course is created. Usually not necessary because format_FORMATNAME::update_course_format_options() is called with null as second argument
- course_updated - when course is updated. Again format_FORMATNAME::update_course_format_options() is called. But if user changed format from A to B the function from format B is invoked. In this case if format A wants to remove some data it should listen to event;
- course_deleted - when course is deleted. Format may want to remove some data (all data from course_format_options is removed automatically)
- mod_created - course module created
- mod_updated - course module updated
- mod_deleted - course module deleted